要实现克隆动画模型的功能,需要注意以下几点:
- 克隆GLTF模型需要使用SkeletonUtils库,进行特殊模型复制
- 对于每一个模型都要创建单独的mixer控制动画
在读取模型时需要将其作为模具全局存储:
1 2 3 4 5 6 7
| const gltfLoader = new GLTFLoader() const shibaInuURL = new URL('../asserts/ShibaInu.gltf', import.meta.url) let shibaInuModel gltfLoader.load(shibaInuURL.href, gltf => { gltf.scene.scale.set(0.3, 0.3, 0.3) shibaInuModel = gltf },undefined,err=>console.error(err))
|
鼠标点击平面时,使用SkeletonUtils克隆,
并创建相应mixer动画控制器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| const mousePosition = new THREE.Vector2() const raycaster = new THREE.Raycaster() const objects = [] const mixers = [] const isExist = () => objects.find(obj => obj.position.x === highlight.position.x && obj.position.z === highlight.position.z)
function getInterSections(e) { mousePosition.x = e.offsetX / window.innerWidth * 2 - 1 mousePosition.y = 1 - e.offsetY / window.innerHeight * 2 raycaster.setFromCamera(mousePosition, camera) return raycaster.intersectObject(plane) }
window.onmousemove = e => { let interSections = getInterSections(e) if (interSections[0]) { let position = interSections[0].point.floor().addScalar(0.5) highlight.position.set(position.x, 0, position.z) highlight.material.color.set(isExist() ? 0xff0000 : 0xffffff) } }
window.onmousedown = e => { if (isExist() || !getInterSections(e)[0]) return let obj = SkeletonUtils.clone(shibaInuModel.scene) scene.add(obj) obj.position.set(highlight.position.x, 0, highlight.position.z) objects.push(obj)
const mixer = new THREE.AnimationMixer(obj) const action = mixer.clipAction( THREE.AnimationClip.findByName(shibaInuModel.animations, 'Idle_2') ) action.play() mixers.push(mixer)
highlight.material.color.set(0xff0000) }
|
在动画中对每一个mixer进行更新:
1 2 3 4 5 6 7 8 9 10
| let clock = new THREE.Clock() function animate(time) { const delta = clock.getDelta() mixers.forEach(mixer => { mixer.update(delta) }) highlight.material.opacity = Math.abs(Math.sin(time/120)) renderer.render(scene, camera); }
|