three.js 士兵示例(根據(jù)規(guī)定定位移動(dòng))

運(yùn)用相關(guān):vue3、three.js

模型下載:https://github.com/mrdoob/three.js/??


<template>

? <div ref="sceneRef">

</template>

<script setup>

import {onMounted,ref }from 'vue'

import *as THREEfrom "three"

import { OrbitControls }from 'three/examples/jsm/controls/OrbitControls'

import { GLTFLoader }from 'three/examples/jsm/loaders/GLTFLoader.js'

import gsapfrom 'gsap'

let scene,camera,renderer,orbitControls

let sceneRef =ref()

let model =ref(null)//用于模型移動(dòng)

let mixer =ref(null)

let clock =new THREE.Clock()

let curve =null

//啟動(dòng)動(dòng)畫

function startAnimation(skinnedMesh, animations, animationName) {

// 申明動(dòng)畫場景

? const m_mixer =new THREE.AnimationMixer(skinnedMesh)

// 查找動(dòng)畫

? const clip = THREE.AnimationClip.findByName(animations, animationName)

if (clip) {

// 播放

? ? const action =m_mixer.clipAction(clip)

action.play()

}

return m_mixer

}

// 曲線/移動(dòng)

function makeCurve() {

// 創(chuàng)建曲線

? curve =new THREE.CatmullRomCurve3([

new THREE.Vector3(0,0,0),

new THREE.Vector3(5,0,0),

new THREE.Vector3(0,0,5)

])

// 曲線類型

? curve.curveType ="catmullrom"

? // 設(shè)置曲線閉環(huán)

? curve.closed =true

? // 設(shè)置曲線張力0-1

? curve.tension =0.5

? // 獲取點(diǎn)位

? const points =curve.getPoints(100)

// 存儲(chǔ)屬性

? const geometry =new THREE.BufferGeometry().setFromPoints(points)

// 更改線的顏色

? const material =new THREE.LineBasicMaterial({color:0x000000})

// 生成線

? const? curveObject =new THREE.Line(geometry,material)

// 加入場景

? scene.add(curveObject)

let obj ={num:0 }

gsap.to(obj, {

num:1,

// 時(shí)間

? ? duration:30,

// 循環(huán)

? ? repeat: -1,

// 緩動(dòng)效果

? ? ease:'none',

onUpdate() {

let point =curve.getPoint(obj.num)

model.value.scene.position.copy(point)

let pointNext =curve.getPoint(obj.num -0.001)

model.value.scene.lookAt(pointNext)

}

})

// console.log(points)

// console.log('gltf', model)

}

// 引入模型

function loadModel() {

const gltfLoader =new GLTFLoader()

gltfLoader.setPath('/modules/')

.load('Soldier.glb', (gltf) => {

console.log(gltf,'gltf')

// 旋轉(zhuǎn)模型

? ? gltf.scene.rotation.y =Math.PI

? ? // 模型縮放

? ? gltf.scene.scale.set(1,1,1)

// 遍歷模型對象(網(wǎng)格對象:改變屬性)

? ? gltf.scene.traverse((object) => {

if (object.isMesh) {

// 陰影

? ? ? ? object.castShadow =true

? ? ? ? // 接受投影

? ? ? ? object.receiveShadow =true

? ? ? }

})

// 獲取跑步動(dòng)畫

? ? mixer.value =startAnimation(

gltf.scene,

gltf.animations,

gltf.animations[3].name

? ? )

model.value = gltf

makeCurve()

scene.add(gltf.scene)

})

}

function init() {

// 場景

? scene =new THREE.Scene()

// 相機(jī) 透視相機(jī) fov視場角 aspect寬高比 near靠近攝像機(jī)的裁剪平面的距離 far遠(yuǎn)處的裁剪平面的距離

? camera =new THREE.PerspectiveCamera(75,window.innerWidth /window.innerHeight,0.1,1000)

// 渲染器

? renderer =new? THREE.WebGLRenderer()

// 相機(jī)位置

? camera.position.set(5,5,5)

// 相機(jī)看向那邊

? camera.lookAt(scene.position)

// 添加輔助坐標(biāo)x(紅色),y(綠色),z(藍(lán)色)

? const axes =new THREE.AxesHelper(20)

scene.add(axes)

// 場景背景

? scene.background =new THREE.Color(0xa0a0a0)

// 場景邊界霧化效果

? scene.fog =new THREE.Fog(0xa0a0a0,10,30)

// 半球形光源

? const hemiLight =new THREE.HemisphereLight(0xffffff,0x444444)

hemiLight.position.set(0,10,0)

scene.add(hemiLight)

// 創(chuàng)建一個(gè)虛擬的球形網(wǎng)格 Mesh 的輔助對象來模擬 半球形光源HemisphereLight

? const hemiLightHelper =new THREE.HemisphereLightHelper(hemiLight,5)

scene.add(hemiLightHelper)

// 地面 Mesh三位網(wǎng)格對象(集合體對象,材質(zhì)) PlaneGeometry創(chuàng)建平面幾何體 MeshPhongMaterial模擬光滑表面的高光效果

? const mesh =new THREE.Mesh(new THREE.PlaneGeometry(100,100),new THREE.MeshPhongMaterial({color:0x999999,depthWrite:false}))

mesh.rotation.x = -Math.PI /2

? mesh.receiveShadow =true

? scene.add(mesh)

// 平行光

? const directionalLight =new THREE.DirectionalLight(0xffffff)

// 燈光需要開啟“引起陰影”

? directionalLight.castShadow =true

? // 陰影樣式

? directionalLight.shadow.camera.near =0.5

? directionalLight.shadow.camera.far =50

? directionalLight.shadow.camera.left = -10

? directionalLight.shadow.camera.right =10

? directionalLight.shadow.camera.top =10

? directionalLight.shadow.camera.bottom = -10

? directionalLight.position.set(0,5,5)

// 陰影清晰度 默認(rèn)512

? directionalLight.shadow.mapSize.set(2048,2048)

scene.add(directionalLight)

// 用于模擬場景中平行光 DirectionalLight 的輔助對象. 其中包含了表示光位置的平面和表示光方向的線段

? const directionalLightHelper =new THREE.DirectionalLightHelper(directionalLight,5)

scene.add(directionalLightHelper)

// 渲染陰影

? renderer.shadowMap.enabled =true

? renderer.setSize(window.innerWidth,window.innerHeight)

sceneRef.value.appendChild(renderer.domElement)

}

function animate() {

requestAnimationFrame(animate)

if(mixer.value){

mixer.value.update(clock.getDelta())

}

renderer.render(scene,camera)

}

function initOrbitControls() {

orbitControls =new OrbitControls(camera,renderer.domElement)

// orbitControls.enableDamping = true

? //相機(jī)位置與觀察目標(biāo)點(diǎn)最大值

? // orbitControls.maxDistance = 1300

// orbitControls.maxPolarAngle = Math.PI / 2

? // // 上下旋轉(zhuǎn)范圍

? // orbitControls.minPolarAngle = -Math.PI / 2 //默認(rèn)值0

? // orbitControls.maxPolarAngle = Math.PI / 2 //默認(rèn)值Math.PI

? // // // 左右旋轉(zhuǎn)范圍

? // orbitControls.minAzimuthAngle = -Math.PI / 2

// orbitControls.maxAzimuthAngle = Math.PI / 2

}

// 監(jiān)聽窗口大小變化事件

window.addEventListener('resize',function() {

// 更新渲染器尺寸

? renderer.setSize(window.innerWidth,window.innerHeight);

// 更新相機(jī)寬高比

? camera.aspect =window.innerWidth /window.innerHeight;

camera.updateProjectionMatrix();

});

onMounted(() => {

init()

loadModel()

initOrbitControls()

animate()

})

<style scoped lang="scss">

</style>



?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容