I'm implementing an interface for resizing a cube by clicking + dragging its faces.
I'd like to implement this by updating the position attribute on the buffer geometry object, and either recreate the mesh or just set the needsUpdate flag and let it update itself. Neither of these options have worked for me. My latest attempt is below.
this.boxGeo = new THREE.BoxGeometry(2,2,2)
this.boxMesh = new THREE.Mesh(this.boxGeo, this.boxMaterial)
...
// let disp = the amount we want to move the face
// vertex indices
let indices = this.planes[index].indices
// new typed array for position attribute
let positions = new Float32Array(8 * 3)
// for each of the 8 verts
for (let i=0; i < 8; i++) {
if(!indices.includes(i) || disp === 0) {
positions[i * 3] = this.boxGeo.vertices[i].x
positions[i * 3 + 1] = this.boxGeo.vertices[i].y
positions[i * 3 + 2] = this.boxGeo.vertices[i].z
} else {
// modify verts
let d = new THREE.Vector3(disp, disp, disp).multiply(plane.normal)
positions[i * 3] = this.boxGeo.vertices[i].x + d.x
positions[i * 3 + 1] = this.boxGeo.vertices[i].y + d.y
positions[i * 3 + 2] = this.boxGeo.vertices[i].z + d.z
}
}
// update geometry
this.boxMesh.geometry._bufferGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))
I've tried a few other methods including more closely following the documentation here: https://threejs.org/docs/#manual/en/introduction/How-to-update-things
Any help or advice would be much appreciated!
EDIT: Per comments below, I'm taking a closer look at my ...attribute.position.array and noticing that it looks like each face lists all its vertices so I can't access them (or set them) as above. Any advice on docs I should go read? Is there an easier way to do this?
So per @Murgen87's comment the code below works to update the position attribute. It looks like the BoxGeometry primitive does not use indexed faces though, and now I'm thinking it might just be easier to scale / translate the box.
let positions =
this.boxMesh.geometry._bufferGeometry.getAttribute('position')
// this loop doesn't pick the right positions for my use case
faces.map((f, i) => {
positions.array[f * 6 + i * 3] += displacement.x
positions.array[f * 6 + i * 3 + 1] += displacement.y
positions.array[f * 6 + i * 3 + 1] += displacement.z
})
positions.needsUpdate = true;
My last remaining question would be why can't I do:
box.geometry.vertices.multiply(displacement)
box.geometry.verticesNeedsUpdate = true
... And this just led me to answer my own question!
needsUpdate
totrue
. Also notice that it is not supported to change the size of a buffer attribute. If this is required, you have to dispose the entire geometry and create a new one. – Mugen87