Quaternion help: limit camera rotation

I am struggling with some quaternion math. I am trying to limit the camera’s rotation to be within a variable angle offset. When the script is enabled, I want to take the camera’s current rotation, and prevent it from rotating too far up, down, left and right.

I created a public test project: https://playcanvas.com/project/703297/overview/camera-rotation-clamp

The code is functional, but the math is wrong. It’s set up with 2 different camera clamps. The 2nd one is supposed to allow +/- 45 degress of x-rotation (vertical). But, clearly it allows for much more than that.

Here’s the relevant code from the postUpdate function:

    var curRot = this.cameraEntity.getRotation();
    rotationDifference(this.initialRotation,curRot,CameraClampRotation.uQ);
    var uE = CameraClampRotation.uQ.getEulerAngles();

    if( Abs(uE.x) > this.eulerX || Abs(uE.y) > this.eulerY ) {
        // Do not allow this rotation. Use the value from the previous frame.
        this.cameraEntity.setRotation(this.validRotation);
    } else {
        // Store this rotation as valid.
        this.validRotation.copy(curRot);
    }

Can anyone assist with the quats and converting that into Eulers, here?

Oh, and here is that ‘rotationDifference’ function:

function rotationDifference(q1, q2, retQ) {
    retQ.copy(q2).invert();
    retQ.mul2(q1,retQ);
}

Hi @Cain_Quigley,

Not sure of the quaternion math on this. But if it’s ok with your use case, as an alternative, you could monitor the rotation of the camera entity in euler angles and decide if you will further process the input or not.

Euler angles are not stored in the entity and are actually derived from the transformation matrix. As a rotation can be represented multiple ways via euler angles, it is recommended that you store the euler angles in the script and use that instead.

In this case, the fly camera is storing the x and y euler angles

If you apply the limits in the fly camera here on the this.ex and this.ey, that would be your easiest solution.

1 Like

Actually, that’s pretty close to what I ended up doing. I used the ‘getYaw’ and ‘getPitch’ functions from the LookCamera, and used that to limit the rotation per-frame.

Originally, I was hoping to use quaternions to avoid the boundary conditions when using angles.

1 Like

If you want to avoid boundary issues, you can get store and limit by offsets of the starting angles.

I can’t really see how quaternions could be used as they represent an orientation. Not sure how you would use them to limit rotation on a single axis.