14

I have a camera that moves in a few different ways in the scene. The camera should rotate around a target position. In my case, this is a point on a mesh that the user has targeted. Because the camera usually doesn't require moving relative to this point, I was not able to use the pivot idea here: https://github.com/mrdoob/three.js/issues/1830. My current solution uses the following code:

var rotationY = new THREE.Matrix4();
var rotationX = new THREE.Matrix4();
var translation = new THREE.Matrix4();
var translationInverse = new THREE.Matrix4();
var matrix = new THREE.Matrix4();
function rotateCameraAroundObject(dx, dy, target) {  
    // collect up and right vectors from camera perspective
    camComponents.up = rotateVectorForObject(new THREE.Vector3(0,1,0), camera.matrixWorld);
    camComponents.right = rotateVectorForObject(new THREE.Vector3(1,0,0), camera.matrixWorld);

    matrix.identity();

    rotationX.makeRotationAxis(camComponents.right, -dx);
    rotationY.makeRotationAxis(camComponents.up, -dy);
    translation.makeTranslation(
        target.position.x - camera.position.x,
        target.position.y - camera.position.y,
        target.position.z - camera.position.z);
    translationInverse.getInverse(translation);

    matrix.multiply(translation).multiply(rotationY).multiply(rotationX).multiply(translationInverse);
    camera.applyMatrix(matrix);
    camera.lookAt(target.position); 
}

The issue is that we do not want to use lookAt, because of the reorientation. We want to be able to remove that line.

If we use the code above without lookAt, we rotate around the point but we do not look at the point. My understanding is that my method should rotate the camera's view as much as the camera itself is rotate, but instead the camera is rotated only a small amount. Could anyone help me understand what's wrong?

EDIT: Cleaned up the original post and code to hopefully clarify my question.

My thinking is that I can translate to the origin (my target position), rotate my desired amount, and then translate back to the beginning position. Because of the rotation, I expect to be in a new position looking at the origin.

In fact, I'm testing it now without the translation matrices being used, so the matrix multiplication line is:

matrix.multiply(rotationY).multiply(rotationX);

and it seems to be behaving the same. Thanks for all the help so far!

ONE MORE THING! A part of the problem is that when the camera behaves badly close to the north or south poles. I am looking for a 'free roaming' sort of feel.

3
  • (1) camera.lookAt( vector ) does not take a matrix as an argument. (2) What, exactly, are you trying to do? Commented Feb 22, 2013 at 18:29
  • I messed it up while trying to clean up my code, sorry! I've edited the post to reflect the right information Commented Feb 22, 2013 at 18:58
  • I'm looking for the exact same thing .. in 2017. I may have missed something, but I really hope I don't have to pull out my Calc textbook and revisit vectors and 3D trig. I just want to be able to rotate "freely" around an object. It's a bit tricky, indeed. Commented May 26, 2017 at 20:40

2 Answers 2

13

Put the following in your render loop:

camera.position.x = target.position.x + radius * Math.cos( constant * elapsedTime );         
camera.position.z = target.position.z + radius * Math.sin( constant * elapsedTime );
camera.lookAt( target.position );

renderer.render( scene, camera );

Alternatively, you can use THREE.OrbitControls or THREE.TrackballControls. See the three.js examples.

Sign up to request clarification or add additional context in comments.

1 Comment

Hmm, something like this might work. I need this to move freely in all three directions, though. One of the key issues is the way it handles rotation near poles. I've updated the original post to clarify that! (hopefully)
0

The Gimbal lock that you are referring to (reorientation) is because of the use of Euler angles in the default implementation of the camera lookat. If you set

camera.useQuaternion = true;

before your call to lookat, then euler angles will not be used. Would this solve your problem ?

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.