5. Using Threejs Animation system to create morph animations for meshes#
Animation system: Keyframtrack, AnimationClip, AnimationMixer, AnimationAction
Geometry: gometry.morphAttributes.position
Mesh: mesh.morphTargetInfluences
5.1. Create morph animation for single mesh#
Step1: create a base geometry, and two morph geometries.
const geometry = new THREE.BoxBufferGeometry(3, 32, 32);
const box1 = new THREE.BoxBufferGeometry(1, 1, 8);
const box2 = new THREE.BoxGeometry(8, 1, 1);
-Step2: Set morphAttributes.position to empty array.
// for initialise morph array
geometry.morphAttributes.position = [];
Step3: Store the positions of the remaining geometries in the morph array of the base geometry.
geometry.morphAttributes.position[0] = box1.attributes.position;
geometry.morphAttributes.position[1] = box2.attributes.position;
Step4: create
meshfor base geometry.
const mesh = new THREE.Mesh(
geometry,
new THREE.MeshBasicMaterial({
color: "#ff00ff",
})
);
Step5: Add a
namefor this mesh.
mesh.name = "my_mesh";
Step6: Create
Keyframtrackfor this mesh. In here, we mush notice that themesh name must be used in Keyframtrack. Otherwise, when we use threejs gltfexporter, it will get unknow error.
const trackA = new THREE.KeyframeTrack(
`my_mesh.morphTargetInfluences[0]`,
[0, 1, 2],
[0, 1, 0]
);
const trackB = new THREE.KeyframeTrack(
`my_mesh.morphTargetInfluences[1]`,
[2, 3, 4],
[0, 1, 0]
);
Step7: Create clip for KeyframeTrack.
const duration = 4;
const clip = new THREE.AnimationClip("change_s", duration, [trackA, trackB]);
Step8: Create mixer for the mesh.
const mixer = new THREE.AnimationMixer(mesh);
Step9: Get
AnimationActionfrom mixer.
const AnimationAction = mixer.clipAction(clip);
// we can use this to change animation speed.
AnimationAction.timeScale = 20;
AnimationAction.play();
Step10: Update mixer in requestAnimationFrame function.
const clock = new THREE.Clock();
const tick = () => {
// Render
renderer.render(scene, camera);
window.requestAnimationFrame(tick);
// Best be putted after renderer.render(scene, camera);
mixer.update(clock.getDelta());
};
tick();
5.2. Create uniform morph animations for multiple models#
Step1: Perform the
first seven stepsof creating a deformation animation of a single model, for each meh and its geometry.Step2: Create a Group to add these meshes.
const group = new THREE.Group();
const meshA = new THREE.Mesh(geometry1, matrial1);
const meshB = new THREE.Mesh(geometry2, matrial2);
const meshC = new THREE.Mesh(geometry3, matrial3);
meshA.name = "meshA";
meshA.name = "meshB";
meshA.name = "meshC";
group.add(meshA, meshB, meshC);
Step3: When creating a clip, all the Keyframetracks of the mesh need to be thrown into the track array.
const meshA_trackA = new THREE.KeyframeTrack(
`meshA.morphTargetInfluences[0]`,
[0, 1, 2],
[0, 1, 0]
);
const meshA_trackB = new THREE.KeyframeTrack(
`meshA.morphTargetInfluences[1]`,
[2, 3, 4],
[0, 1, 0]
);
const meshB_trackA = new THREE.KeyframeTrack(
`meshB.morphTargetInfluences[0]`,
[0, 1, 2],
[0, 1, 0]
);
const meshB_trackB = new THREE.KeyframeTrack(
`meshB.morphTargetInfluences[1]`,
[2, 3, 4],
[0, 1, 0]
);
const meshC_trackA = new THREE.KeyframeTrack(
`meshC.morphTargetInfluences[0]`,
[0, 1, 2],
[0, 1, 0]
);
const meshC_trackB = new THREE.KeyframeTrack(
`meshC.morphTargetInfluences[1]`,
[2, 3, 4],
[0, 1, 0]
);
const clipA = new THREE.AnimationClip("Copper3D_animation_A", duration, [
meshA_trackA,
meshA_trackB,
]);
const clipB = new THREE.AnimationClip("Copper3D_animation_B", duration, [
meshB_trackA,
meshB_trackB,
]);
const clipC = new THREE.AnimationClip("Copper3D_animation_C", duration, [
meshC_trackA,
meshC_trackB,
]);
Step4: Create mixer for mesh.
const mixer = new THREE.AnimationMixer(group);
const AnimationAction_A = mixer.clipAction(clipA);
AnimationAction_A.timeScale = 200;
AnimationAction_A.play();
const AnimationAction_B = mixer.clipAction(clipB);
AnimationAction_B.timeScale = 200;
AnimationAction_B.play();
const AnimationAction_C = mixer.clipAction(clipC);
AnimationAction_C.timeScale = 200;
AnimationAction_C.play();
Then repeat above
step10.
5.3. Create material color animate for mesh#
Step1: create mesh
const object2 = new THREE.Mesh(
geometry,
new THREE.MeshBasicMaterial({
color: "#ff00ff",
})
);
Step2: add
namefor mesh
object2.name = "Box";
Step3: create frames for mesh meterial
const colorKF = new THREE.KeyframeTrack(
"Box.material.color",
[0, 10, 20],
[1, 0, 0, 0, 1, 0, 0, 0, 1]
);
Step4: creat clips
const duration = 20;
const clip1 = new THREE.AnimationClip("Copper3D_Color_", duration, [colorKF]);
Step5: create mixer
const mixer = new THREE.AnimationMixer(object2);
const AnimationAction = mixer.clipAction(clip1);
AnimationAction.timeScale = 200;
AnimationAction.play();