Inverting quaternions

Still new to quaternions, so:

I’ve almost got a spaceship control from TrackballControls.
I’m confused why approach one with vectors (almost) works, but approach two with quaternions, is failing entirely currently

with vectors:
CAMERA.getWorldDirection( cameraDir )
SHIP.lookAt( cameraDir )

with quaternions:
var invQtrn = CAMERA.quaternion.inverse()
SHIP.setRotationFromQuaternion( invQtrn )

Vectors works smoothly but an axis is “forgotten” between it and the camera (gimbal lock ?)

Quaternions should be the same idea, turn ship directly away from camera, but it kind of jerks around in odd directions.

Original problem with vectors to give an idea:

image

If I do a normal (not inversed) quaternion, the ship stays level with the camera, just facing the wrong direction.

With the inverse quaternion it doesn’t seem to bear any more relation to the camera.

I think you don’t need to inverse the camera quaternion but instead multiply it with a rotation by 180° around the Y axis.

I think you’re right that it’s not a perfect inversion I’m looking for, but also it needs to be more than the Y axis I think.

[edit] - I see, you meant local Y axis. If I set set that directly, the result is the same as the Vector.lookAt - it loses the Z rotation for some reason.

I want the player to adopt the same quaternion as the camera. However, if I simply copy the camera.quaternion, the player looks AT the camera for reasons I’m not really sure of. TrackballControls has this line:

if ( _this.object.isPerspectiveCamera ) {

			_this.checkDistances();

			_this.object.lookAt( _this.target );

_this.object is the camera, _this.target is the player, and so I should be then copying that quaternion the player … ?

If everything is working as expected with the camera quaternion and the ship is only facing the reverse direction, then multiplying with a rotation of 180° around Y should be ok. At least it does work for me in my project.

I have sprites that are always facing the camera by setting their quaternion equal to the camera quaternion. To test, I have added a 180° Y rotation and they are now always back-facing the camera.

The code is:

        const cameraRot = this.camera.quaternion;

        const q = glMatrix.quat.create();
        glMatrix.quat.setAxisAngle(q, [0, 1, 0], glMatrix.glMatrix.toRadian(180));
        glMatrix.quat.mul(q, cameraRot, q);

I’m using glMatrix for math calculations, but it should be easy to convert it to threejs:

  • the setAxisAngle line creates a quaternion for a 180° rotation around Y. You can simply create a quaternion with (0,1,0,0) values if you want: q = new THREE.Quaternion(0,1,0,0)
  • the mul line does q = cameraRot * q

Then use q as your quaternion.

you are a golden god, thank you!
combined with a quaternion.slerp(), that is some really cool looking yaw and pitch controls…

that works great for commands where the ship needs to obey the camera (my right click “look”), but it seems a little trickier when the camera needs to obey the ship. TrackballControls doesn’t seem to like being “childed” to a Group, I think it’s meant to stay fixed in Scene space, so I’m not sure if I should really be using it or not.

But that was the biggest hurdle yet, so tyvm.

What’s your project?

It is that: