1
votes

In a three.js project, I'm using a modified version of PointerLockControls.js for the camera control. I want to modify the rotation functionality so that there is no absolute "up" axis by which the camera rotates, but rather moving the mouse up or down will pitch indefinitely, same for left and right for yawing (and keys for rolling).

I can't seem to get the yawing component working, as it seems to rotate around the same axis regardless of pitch. (ie moving left or right when face facing straight upwards will just rotate the camera)

Any help in the right direction would be great!

1

1 Answers

1
votes

I had the same problem recently, so I had a look at some of the THREE.*Controls files, similar to you.

Using those as a basis, I made this: https://github.com/squarefeet/THREE.ObjectControls

The important bits are the following (see here for context):

var updateTarget = function( dt ) {
    var velX = positionVector.x * dt,
        velY = positionVector.y * dt,
        velZ = positionVector.z * dt;

    rotationQuaternion.set(
        rotationVector.x * dt,
        rotationVector.y * dt,
        rotationVector.z * dt,
        1
    ).normalize();

    targetObject.quaternion.multiply( rotationQuaternion );

    targetObject.translateX( velX );
    targetObject.translateY( velY );
    targetObject.translateZ( velZ );
};

The rotationVector is probably of most interest to you, so here's what it's doing:

  • It's using a THREE.Vector3 to describe the rotation, the rotationVector variable in this example.

  • Each component of the rotationVector (x, y, z) is relative to pitch, yaw, and roll respectively.

  • Set a quaternion's x, y, and z values to the of the rotation vector, making sure the w component is always 1 (to learn what the w component does, see here, it's a great answer.

  • Normalizing this quaternion will get us a quaternion of length 1, which is very handy when we come to the next step...

  • targetObject in this case is an instance of THREE.Object3D (a THREE.Mesh, which inherits from THREE.Object3D), so it has a quaternion we can play with.

  • So now, it's just a matter of multiplying your targetObject's quaternion by your shiny new rotationQuaternion.

  • Since our object is now rotated to where we want, we can move it along it's new axis angles by using translateX/Y/Z.

The important thing to note here is that quaternions don't act like Euler vectors. Rather than adding two quaternions together to get a new angle, you multiply them.

Anyway, I hope that helps you somewhat!