const mesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({ color: 0xffff00 }));
const rotatemat = new THREE.Matrix4()
const translationmat = new THREE.Matrix4()
const dir = new THREE.Vector3().subVectors(camera.position.clone(), mesh.position.clone())
renderer.setAnimationLoop(() => {
translatemat.makeTranslation(num, -num, 0)
mesh.position.applyMatrix4(translatemat)
rotatemat.makeRotationAxis(camera.getWorldDirection(mesh.up).normalize(), p)
const camp = new THREE.Vector3().addVectors(mesh.position.clone(), dir.clone())
camp.applyMatrix4(rotatemat)
camera.position.copy(camp)
camera.lookAt(mesh.position)
})
I calculate the direction vector between the camera coordinates and the object coordinates, move the object and update the camera position, but the camera does not rotate around the up axis of the object. I don’t know what the problem is?
It seems that there is something wrong with my rotation axis. How can I calculate the rotation axis of the camera around the object
Unfortunately I don’t think this tutorial is available on other sites. But here’s the github repo with the code from the video, hopefully you can access that
Here is a completely different approach that I use to accomplish the same thing.
I link the camera to a 3D object, which acts like a “selfie stick”.
I then link the 3D object to the 3D object of interest so that it is holding the stick
I use mouse input to orbit the camera around the object of interest:
mouseX = longitude
mouseY = latitude.
Here is some sample code:
// Camera Variables
let CamDst = 500; // distance from object you are looking at
let CamLat = 30; // vertical position of camera (+/-90 degrees) 30 = up
let CamLon = 0; // horizontal position of camera (0-360 degrees) 0 = straight ahead
let LatMax = 90; // limit input value to 90 degrees, so you don't go "upside down"
let LatMin = -90; // Same for down
// Create Camera and Holder
const camera = new THREE.PerspectiveCamera(45, width/height, 1, 15000);
camera.rotation.order = "YXZ";
const camobj = new THREE.Object3D(); // This is like a camera "selfie stick" that holds the camera
camobj.rotation.order = "YXZ"; // You rotate the "stick" to position the camera in space
camobj.add(camera); // Attach the camera to the stick
camera.position.z = -CamDst; // Length of "stick"
camera.rotation.y = 180*DegRad; // Camera looks towards the object holding the "stick"
// Object of Interest (you can add the mesh later)
const ctrobj = new THREE.Object3D(); // Create object
ctrobj.rotation.order = "YXZ";
ctrobj.add(camobj); // Attach camera "stick" to the object
scene.add(ctrobj);
// I use mouse input to rotate the lat/lon of the "stick", which causes the camera to orbit the object:
// * up/down changes latitude (limit to +/-90 degrees)
// * left/right changes longitude
// * mouse wheel changes distance from object
// I call the function below with each frame (but it is so small, you can just include it in your code)
function moveCamera() {
camera.position.z = -CamDst; // in case, change distance from object
camobj.rotation.x = Mod360(CamLat)*DegRad;
camobj.rotation.y = Mod360(CamLon+180)*DegRad;
}
Note: that you can also “bank” the camera using rotation.z - something you can’t do with LookAt
Also, note: I am using 3Dobjects, rather than just a mesh because you can link to a 3Dobject.
This is a pretty flexible setup:
You can easily look outwards (just make camera.roation.y = 0)
You can attach the camera holder to different objects of interest (e.g. different planets rotating the sun) to look at them.
You can use linked objects to change the orientation of your axis.
After reading the code provided by you, the content of the code is to store the object to be linked in one object3d and the camera in another object3d, then add the camera’s object3d to the obejct3d where the linked object is stored, and change the rotation of the camera through the mouse mouseover event. What I need to change is the position and orientation of the object. I think the camera, as a child of the object, will rotate and translate with it
Yes, I should have used that terminology. The camera stick (CamObj) is a child of the object of interest and the Camera is a child of CamObj. To make the camera orbit the object, you change the x/y rotation of CamObj.
In the image you posted, if the person is the image of interest, you can make CamObj a child of the person and then make the camera orbit the person.
Or, if you want the camera to trail the person, you would simply rotate CamObj to a fixed location (e.g. y-rotation = 180 and x-rotation = 30).
To avoid confusion, one thing you will want to decide is whether to make the angles represent the location of the camera relative to the object or to have them represent the direction the camera is pointing. I think the latter makes more sense, but you may have to make some slight changes to the sample code above.
ADD
I believe that you merely have to flip the sign of the Y value (latitude) and add 180 degrees to the X value (longitude).
Now that I see what you are doing, I wonder if it would be better to use some version of the pointerlockcontrols.js routine? That routine allows you to rotate and also to “strafe” (i.e. move forward, backwards, left and right). It is designed for first person simulations, where you are the character, but perhaps there is a way to modify it to act on a character located directly in front of your camera?
Or perhaps you can use the code as a template for creating your own version?
I used a stripped-down version in my flight simulation but all I wanted was a subroutine to capture changes in mouse position, rather than mouse screen position - which is what you normally get.
Now I use some methods in pointerlockcontrols to update the coordinates. Among them, I also add pressing and holding the middle of the mouse to rotate the camera