Quantcast
Channel: Question and Answer » webgl
Viewing all articles
Browse latest Browse all 56

How can I restrict the rotation of an object to a subset of axes using quaternions?

$
0
0

I’ve got a question about quaternions in my WebGL application.

How can I rotate an object only around two axes? For example, how can I exclude/nullify rotation about the Y axis?

The problem is that when I rotate something around X axis, and then around Y axis, it rotates around Z axis slightly as well. I have read whole piles of posts about it (for example) but none of them really helped me. Reversal order of multiplication operations doesn’t work for me. My actual code below:

// Main rotation function:

rotateCamera: function(angleX, angleY) {
    if (angleY !== 0) {
        this.yawRotation.axisToQuaternion(angleY, this.tempVec.make(1, 0, 0)));
        this.rotation.multiply(this.yawRotation);
    }
    if (angleX !== 0) {
        this.pitchRotation.axisToQuaternion(angleX, this.tempVec.make(0, 1, 0)));
        this.rotation.multiply(this.pitchRotation);
    }
    this.rotation.normalize();

    MVMatrix.setRotation(this.rotation.quaternionToMatrix());

// Matrix setRotation function:

setRotation: function(m) {
    this.element[0] = m.element[0];
    (... some code omitted ...)
    this.element[10] = m.element[10];
},

And the ought-to-be-working code based on other posts (which is not working):

rotateCamera: function(angleX, angleY) {
    if (angleY !== 0) {
        this.yawRotation.axisToQuaternion(angleY, this.tempVec.make(1, 0, 0));
    }
    if (angleX !== 0) {
        this.pitchRotation.axisToQuaternion(angleX, this.tempVec.make(0, 1, 0));
    }
    this.yawRotation.multiply(this.rotation);
    this.rotation.copy(this.yawRotation);
    this.rotation.multiply(this.pitchRotation);
    this.rotation.normalize();

    MVMatrix.setRotation(this.rotation.quaternionToMatrix());
},

EDIT: I have added more info about the actual code.

EDIT2: Okeeeey, I almost found a working answer for my problem (adapted it from Rick Hoskinson’s post). My updated code below:

rotateCamera: function(radX, radY) {
    // Pitch (vertical rotation)
    if (radY !== 0) {
        this.pitch += radY;
        // Prevent camera from flipping upside-down (constrained by vertical "plane")
        this.pitch = Math.clamp(this.pitch, -Math.PI/2, Math.PI/2);

        this.rotation.axisToQuaternion(this.yaw, this.tempVec.make(0, 1, 0));
        this.rotation.multiply(this.tempQuat.axisToQuaternion(this.pitch, this.tempVec.make(1, 0, 0)));
    }
    // Yaw (horizontal rotation)
    if (radX !== 0) {
        this.yaw += radX;

        this.rotation.axisToQuaternion(this.yaw, this.tempVec.make(0, 1, 0));
        this.rotation.multiply(this.tempQuat.axisToQuaternion(this.pitch, this.tempVec.make(1, 0, 0)));
    }

    MVMatrix.setRotation(this.rotation.quaternionToMatrix());
}

Camera’s roll has been eliminated using this method, but strange camera motion appears when rotating from one of the sides and then looking below (or I should say trying to look below, cause it curves away from this direction).


Viewing all articles
Browse latest Browse all 56

Trending Articles