I'm currently creating a mesh in three.js using the following:
sphereGeometry = new THREE.SphereGeometry( 1, 16,16 );
mesh = new THREE.Mesh( sphereGeometry, material );
I've also created a torus:
torusGeometry = new THREE.TorusGeometry( 1, 0.42 );
At any point in my animation loop, I want to be able to swap the sphere out for the torus. Is this possible? How do I swap one geometry for another?
I'm currently creating a mesh in three.js using the following:
sphereGeometry = new THREE.SphereGeometry( 1, 16,16 );
mesh = new THREE.Mesh( sphereGeometry, material );
I've also created a torus:
torusGeometry = new THREE.TorusGeometry( 1, 0.42 );
At any point in my animation loop, I want to be able to swap the sphere out for the torus. Is this possible? How do I swap one geometry for another?
Share Improve this question asked Jun 19, 2013 at 22:35 mheaversmheavers 30.2k62 gold badges198 silver badges326 bronze badges 1- Did you get the geometry switching to work? – jh314 Commented Jun 26, 2013 at 3:46
6 Answers
Reset to default 12in Three.js R59, setGeometry and setMaterial were removed again from Three.Mesh
What you can do to replace geometry is removing your Mesh from Scene and creating a new one with your new geometry and your old material and add it back to your scene. This will work for sure :)
Switching geometries can be costly. I would simply add both to the scene and hide / reveal based on your situation.
You can use SetGeometryCommand
to change the geometry of a Mesh in realtime.
Usage:
editor.execute( new SetGeometryCommand( object, new THREE[ geometry.type ](
radiusTop,
radiusBottom,
height,
radialSegments,
heightSegments,
openEnded
) ) );
https://github.com/mrdoob/three.js/blob/dev/editor/js/commands/SetGeometryCommand.js
Something like this should work
// In this example we will distort a plane
let plane = new THREE.Mesh(g1, m1);
plane.rotation.x = Math.PI * 270 / 180;
plane.position.y = 0;
plane.position.z = 0;
scene.add(plane);
// Distort plane
let positions = plane.geometry.attributes.position.array;
let count = positions.length / 3;
for (let i = 0; i < count; i++) {
let v = new THREE.Vector3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]);
let distanceFromCenterY = Math.abs(v.x) / 100;
v.z += distanceFromCenterY > .2 ?
(Math.random() * (20 - .15) + .15) * distanceFromCenterY * 2 :
(Math.random() * (.8 - .2) + .2) + distanceFromCenterY;
// In this example we are updating the z coordinate or ther vertices
plane.geometry.attributes.position.array[ i * 3 + 2 ] = v.z;
}
youre probably not supposed to do it this way, but i tried it and it works for me.
let newgeom = new BoxGeometry(width, height, depth);
mesh.geometry.setAttribute('position', newgeom.attributes.position);
If you want to be more complete, do the same for uv
, normal
, and any other attribute you have to set
Note: in my case, i only changed the geometry when the user specifically changed the size of the object, which isn't all the time. I don't know how performant it would be if you're changing the size every frame.
Also, the old geometry and the new geometry both had the same number of points, just in different positions.
Try looking at this: http://threejs.org/docs/58/#Reference/Objects/Mesh
Especially this method:
mesh.setGeometry(geometry)
Here is how you would do it inside your render loop (you set the flag whenever you want to swap the sphere out for the torus)
var flag;
...
function render () {
if (flag) {
mesh.setGeometry(torusGeometry);
flag = false;
}
}
render();
If you want to flip back and forth (inside render loop):
if (conditions) {
mesh.setGeometry(sphereGeometry);
}
if (condition) {
mesh.setGeometry(torusGeometry);
}