Hi, I’m trying to figure out how Skeleton animations work. I build a custom Geometry, create a Mesh and bind the mesh to a Skeleton. Then I animate the Skeleton. I cann see the Skeleton move but the Mesh does not move accordingly. It seems that there’s something missing. Does anyone have an idea? Thanks!
Here is the code:
// Build the Geometry
const geometry = new THREE.BufferGeometry();
const vertices = [
// front
{ pos: [-1, -1, 1], norm: [ 0, 0, 1], uv: [0, 0], color: [0,0.75,0] },
{ pos: [ 1, -1, 1], norm: [ 0, 0, 1], uv: [1, 0], color: [0,0.75,0] },
{ pos: [-1, 1, 1], norm: [ 0, 0, 1], uv: [0, 1], color: [0,0.75,0] },
{ pos: [-1, 1, 1], norm: [ 0, 0, 1], uv: [0, 1], color: [0,0.75,0] },
{ pos: [ 1, -1, 1], norm: [ 0, 0, 1], uv: [1, 0], color: [0,0.75,0] },
{ pos: [ 1, 1, 1], norm: [ 0, 0, 1], uv: [1, 1], color: [0,0.75,0] },
// right
{ pos: [ 1, -1, 1], norm: [ 1, 0, 0], uv: [0, 0], color: [255,0,0] },
{ pos: [ 1, -1, -1], norm: [ 1, 0, 0], uv: [1, 0], color: [255,0,0] },
{ pos: [ 1, 1, 1], norm: [ 1, 0, 0], uv: [0, 1], color: [255,0,0] },
{ pos: [ 1, 1, 1], norm: [ 1, 0, 0], uv: [0, 1], color: [255,0,0] },
{ pos: [ 1, -1, -1], norm: [ 1, 0, 0], uv: [1, 0], color: [255,0,0] },
{ pos: [ 1, 1, -1], norm: [ 1, 0, 0], uv: [1, 1], color: [255,0,0] },
// back
{ pos: [ 1, -1, -1], norm: [ 0, 0, -1], uv: [0, 0], color: [255,0,0] },
{ pos: [-1, -1, -1], norm: [ 0, 0, -1], uv: [1, 0], color: [255,0,0] },
{ pos: [ 1, 1, -1], norm: [ 0, 0, -1], uv: [0, 1], color: [255,0,0] },
{ pos: [ 1, 1, -1], norm: [ 0, 0, -1], uv: [0, 1], color: [255,0,0] },
{ pos: [-1, -1, -1], norm: [ 0, 0, -1], uv: [1, 0], color: [255,0,0] },
{ pos: [-1, 1, -1], norm: [ 0, 0, -1], uv: [1, 1], color: [255,0,0] },
// left
{ pos: [-1, -1, -1], norm: [-1, 0, 0], uv: [0, 0], color: [255,0,0] },
{ pos: [-1, -1, 1], norm: [-1, 0, 0], uv: [1, 0], color: [255,0,0] },
{ pos: [-1, 1, -1], norm: [-1, 0, 0], uv: [0, 1], color: [255,0,0] },
{ pos: [-1, 1, -1], norm: [-1, 0, 0], uv: [0, 1], color: [255,0,0] },
{ pos: [-1, -1, 1], norm: [-1, 0, 0], uv: [1, 0], color: [255,0,0] },
{ pos: [-1, 1, 1], norm: [-1, 0, 0], uv: [1, 1], color: [255,0,0] },
// top
{ pos: [ 1, 1, -1], norm: [ 0, 1, 0], uv: [0, 0], color: [255,255,0] },
{ pos: [-1, 1, -1], norm: [ 0, 1, 0], uv: [1, 0], color: [255,255,0] },
{ pos: [ 1, 1, 1], norm: [ 0, 1, 0], uv: [0, 1], color: [255,255,0] },
{ pos: [ 1, 1, 1], norm: [ 0, 1, 0], uv: [0, 1], color: [255,255,0] },
{ pos: [-1, 1, -1], norm: [ 0, 1, 0], uv: [1, 0], color: [255,255,0] },
{ pos: [-1, 1, 1], norm: [ 0, 1, 0], uv: [1, 1], color: [255,255,0] },
// bottom
{ pos: [ 1, -1, 1], norm: [ 0, -1, 0], uv: [0, 0], color: [255,0,0] },
{ pos: [-1, -1, 1], norm: [ 0, -1, 0], uv: [1, 0], color: [255,0,0] },
{ pos: [ 1, -1, -1], norm: [ 0, -1, 0], uv: [0, 1], color: [255,0,0] },
{ pos: [ 1, -1, -1], norm: [ 0, -1, 0], uv: [0, 1], color: [255,0,0] },
{ pos: [-1, -1, 1], norm: [ 0, -1, 0], uv: [1, 0], color: [255,0,0] },
{ pos: [-1, -1, -1], norm: [ 0, -1, 0], uv: [1, 1], color: [255,0,0] },
];
const positions = [];
const normals = [];
const uvs = [];
const colors = [];
for (const vertex of vertices)
{
positions.push(...vertex.pos);
normals.push(...vertex.norm);
uvs.push(...vertex.uv);
colors.push(...vertex.color);
}
geometry.setAttribute(
'position',
new THREE.BufferAttribute(new Float32Array(positions), 3));
geometry.setAttribute(
'normal',
new THREE.BufferAttribute(new Float32Array(normals), 3));
geometry.setAttribute(
'uv',
new THREE.BufferAttribute(new Float32Array(uvs), 2));
geometry.setAttribute(
'color',
new THREE.BufferAttribute(new Float32Array(colors), 3));
// Set Skin Indices and Weights
const skinIndices = [];
const skinWeights = [];
const position = geometry.attributes.position;
for ( let i = 0; i < position.count; i ++ )
{
skinIndices.push( 0, 1, 0, 0 );
skinWeights.push( 1, 0.5, 0, 0 );
}
geometry.setAttribute( 'skinIndex', new THREE.Uint16BufferAttribute( skinIndices, 4 ) );
geometry.setAttribute( 'skinWeight', new THREE.Float32BufferAttribute( skinWeights, 4 ) );
// Create Material and Mesh
const material = new THREE.MeshPhongMaterial( { flatShading: true, wireframe: false, vertexColors: THREE.VertexColors } );
this.mesh = new THREE.SkinnedMesh( geometry, material );
// Build the Skeleton
var bones = [];
var bone1 = new THREE.Bone();
bone1.position.x = 1;
bones.push(bone1);
var bone2 = new THREE.Bone();
bone2.position.x = -2;
bones.push(bone2);
bone1.add(bone2);
var skeleton = new THREE.Skeleton(bones);
this.mesh.add(bone1);
this.mesh.bind(skeleton);
this.mesh.rotation.x = 0.3;
this.mesh.rotation.y = 0.3;
this.mesh.rotation.z = 0.3;
this.scene.add(this.mesh);
const helper = new THREE.SkeletonHelper( this.mesh );
this.scene.add( helper );
// Animation loop
this.mesh.skeleton.bones[0].position.x += 0.01;