形变一般指的是对几何体顶点位置的修改。 在Three.js中BufferGeometry实例的morphAttributes可以用来存储形变数据, 结合Animation的api实现形变动画。
以一个立方体为例
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshPhongMaterial({ color: 0xffff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
创建两个形变数据,一个是往x轴拉伸,另一个是往y轴拉伸
morphAttribute存储形变数据,而morphTargetInfluences决定形变的程度
const pos = geometry.getAttribute("position");
const expendY = [];
const expendX = [];
for (let i = 0; i < pos.count; i++) {
expendY.push(pos.getX(i));
expendY.push(pos.getY(i) + (pos.getY(i) > 0 ? 2 : 0));
expendY.push(pos.getZ(i));
expendX.push(pos.getX(i) + (pos.getX(i) > 0 ? 2 : 0));
expendX.push(pos.getY(i));
expendX.push(pos.getZ(i));
}
geometry.morphAttributes.position = [
new THREE.Float32BufferAttribute(expendY, 3),
new THREE.Float32BufferAttribute(expendX, 3),
];
cube.morphTargetInfluences = [0, 0];
创建帧动画
有4帧,每帧有两个元素,values总共有8个元素
const expand = new THREE.KeyframeTrack(
".morphTargetInfluences",
[0, 1, 2, 3],
[0, 0, 1, 0, 0, 0, 0, 1]
);
const clip = new THREE.AnimationClip("expand", 3, [expand]);
const mixer = new THREE.AnimationMixer();
const action = mixer.clipAction(clip, cube);
// action.loop = THREE.LoopPingPong;
// action.loop = THREE.LoopOnce;
action.play();
动画渲染
const clock = new THREE.Clock();
renderer.setAnimationLoop((t) => {
mixer.update(clock.getDelta());
renderer.render(scene, camera);
});