Animate vertices position of BoxGeometry

Hello,
I’m creating a BoxGeometry that represents a sponge (with 6 image textures, 1 per face).

const geometry = new THREE.BoxGeometry(2, 0.5, 2, 4, 1, 1)

I’ve added more width subdivisions cause i need to animate some vertices up and down to simulate a light squeeze of the sponge.

Some time ago I would have done it like this:

sponge.geometry.vertices[2].set(1, 0.15, -1);
sponge.geometry.verticesNeedUpdate = true

But from what I read the vertices coordinates are now stored in a flat way:

mesh.geometry.getAttribute( 'position' )

→ that returns an array of numbers, not grouped in Vector3.

Could you help me understand how to change the vertices position with this new object structure?

Thank you :sunny:

You basically use this pattern:

const positionAttribute = geometry.getAttribute( 'position' );

const vertex = new THREE.Vector3();

for ( let i = 0; i < positionAttribute.count; i ++ ) {

	vertex.fromBufferAttribute( positionAttribute, i );
	
	vertex.set( ... ); // update vertex

	positionAttribute.setXYZ( i, vertex.x, vertex.y, vertex.z );

}

positionAttribute.needsUpdate = true;

If you plan to update the position attribute per frame (typically in animations), add this configuration once when you create the geometry.

positionAttribute.setUsage( THREE.DynamicDrawUsage );
2 Likes

thank you very much

Hi Mugen87,

When i try this on a dodecahedron, the array has 107 vertices instead of the 20 it needs to have, how do i select 1 specific vertex and animate this 1 vertex

const geoDodeca = new THREE.DodecahedronGeometry( 3, 0 );
// geoDodeca.attributes.position.needsUpdate = true;
const matDodeca = new THREE.MeshLambertMaterial(
	{
		// wireframe: true,
		color: 0x0077ff,
		depthTest: true,
		depthWrite: true,
		flatShading: true,
		dithering: true,
		transparent: true,
		opacity: 0.3
	}
)

let meshDodeca = new THREE.Mesh(geoDodeca, matDodeca);
meshDodeca.name = 'dodecaMesh';
arrObjects.push(meshDodeca)

// :. selecting the dodeca vertices
const positionAttribute = meshDodeca.geometry.getAttribute( 'position' );
positionAttribute.needsUpdate = true;
positionAttribute.setUsage( THREE.DynamicDrawUsage );
const vertex = new THREE.Vector3();

// for ( let i = 0; i < 20; i ++ ) {
for ( let i = 0; i < positionAttribute.count; i ++ ) {
	vertex.fromBufferAttribute( positionAttribute, i );

	// do something with vertex
	// vertex.set( ... ); // update vertex
	// positionAttribute.setXYZ( i, vertex.x, vertex.y, vertex.z );
	console.log('Vtx id: ' + i + '   ' + vertex.x + ', ' + vertex.y + ', ' + vertex.z )
	// console.log(vertex)
}