What’s the right way to rotate an object around a point in three.js?
Most tutorials/questions about three.js suggest the way to rotate an object around a point using three.js is to create a parent object at the position you want to rotate around, attach your object, and then move the child. Then when the parent is rotated the child rotates around the point. Eg;
//Make a pivot var pivot = new THREE.Object3D(); //Make an object var object = new THREE.Mesh( new THREE.BoxGeometry(2,2,2), new THREE.MeshBasicMaterial() ); //Add object to pivot pivot.add(object); //Move object away from pivot object.position.set(new THREE.Vector3(5,0,0)); //rotate the object 90 degrees around pivot pivot.rotation.y = Math.PI / 2;
This works but it’s incredibly limiting – if you want to rotate an object around a different point you can’t because an object can’t have two parents.
The next method that works is applying a rotated matrix to the object’s position, e.g.;
//Make an object var object = new THREE.Mesh( new THREE.BoxGeometry(2,2,2), new THREE.MeshBasicMaterial() ); //Move the object object.position.set(new THREE.Vector3(5,0,0); //Create a matrix var matrix = new THREE.Matrix4(); //Rotate the matrix matrix.makeRotationY(Math.PI / 2); //rotate the object using the matrix object.position.applyMatrix4(matrix);
Again, this works, but there doesn’t appear to be a way to set the point of rotation. It’s always the origin of the world.
Another option is a utility method in sceneUtils to detach a child from a parent object and another method to attach a new parent, but the documentation for that warns against using it, and it’s never used in any example code.
Ultimately I want to be able to make a cube follow an S shaped path, but without this (seemingly) basic thing I’m finding it rather difficult.
tl;dr I want to rotate a three.js object around a series of different points. What would be a good way to approach that?
This answer might help: Three JS Pivot point
There are several ways to approach this problem. As you mentioned, you CAN swap the pivot point in the parenting approach, but it’s a lot of work, converting the object position to/from the different coordinate systems.
Instead, you can always look at it this way (pseudo-code):
Move the object to the pivot point
1.1. SUBTRACT the the pivot point from your object’s original position
Apply your rotation
Move the object BACK by the same position vector
1.1. ADD the the pivot point to your object’s new position
Note: Everything is in world coordinates, so you may need to convert appropriately.
Simple solution: move to the anchor point, rotate, and move back.
Let’s assume you want to rotate a
camera around an
camera is an instance of
anchorPoint is an instance of
THREE.Vector3 here ):
/// step 1: calculate move direction and move distance: let moveDir = new THREE.Vector3( anchorPoint.x - camera.position.x, anchorPoint.y - camera.position.y, anchorPoint.z - camera.position.z ); moveDir.normalize(); let moveDist = camera.position.distanceTo(anchorPoint); /// step 2: move camera to anchor point camera.translateOnAxis(moveDir, moveDist); /// step 3: rotate camera camera.rotateX(valX); camera.rotateY(valY); camera.rotateZ(valZ); /// step4: move camera along the opposite direction moveDir.multiplyScalar(-1); camera.translateOnAxis(moveDir, moveDist);
This works but it’s incredibly limiting – if you want to rotate an
object around a different point you can’t because an object can’t have
this is true, but I’m wondering what you expect as a default behavior in having 2 parents. You can nest things – ie, a camera being held by a woman in a car has 2 tiers of parenting: Camera->Woman->Car. But if instead you wanted some parallel parenting relationship (?) lets say the woman is holding the camera, but you want a man to also be holding the camera at the same time. How do you get the man turn around and film something without taking it from the woman or vice versa? The idea of multiple parents falls apart when you try to imagine what happens by default. Does the woman move with the camera? then isn’t the camera actually her parent in this scenario?
You can always detach the object and then attach it to another if you want to change between parents. It warns you against manually detaching because the object will go from being in local space to it’s parent into world space/ the local space of its new parent.
Luckily there are some things in the scene utils meant for exactly this: namely attach and detach. So when you want to hand an object off without going from local to world coordinates and teleporting it weird places, you can use the attach/detach functions.
Keep in mind this will do weird stuff unless newParent is in exactly the same location as the previous parent at the time of the handoff because we’re not guaranteeing anything about the relation of our object to the parent other than that it will remain the same as at the time of the handoff.