So after a lot of researching about quaternions I almost got the quaternion camera working. Almost, cause it rotates in a proper way only in a vertical axis. Other rotations stretches and deforms the view (like on a picture below).

enter image description here

  • Wobbling horizontal moves makes only Z axis stretched

I don't like to post topics like "Please, debug my brain", but I'm in a dead end right now, and I don't know how to fix it.

My implementation looks like this:

  1. I Convert an axis-angle rotation to a quaternion and normalize it.
  2. Then multiply it with a camera identity quaternion.
  3. And then multiply a position of a camera (which is a 4x4 model-view matrix) by a product of above multiplication converted to matrix.

My free quaternion camera class looks like this (for now):

function QuaternionCamera() {
    // Fake 4x4 Matrix
    this.position = new Matrix4x3();
    this.rotation = new Quaternion();

QuaternionCamera.prototype = {
    verticalRotation: function(angle) {
        this.rotation.multiply(new Quaternion().axisToQuaternion(angle, 0, 1, 0));

    horizontalRotation: function(angle) {
        this.rotation.multiply(new Quaternion().axisToQuaternion(angle, 1, 0, 0));

And on mouse movement, it runs this:

    camera.verticalRotation(degToRad(deltaX / 6));
    camera.horizontalRotation(degToRad(deltaY / 6));

I believe that this is a proper way to do it, so I'll just dump my math library, maybe you could find a typo in there (cause I have checked it a hunderd of times and found nothing): http://pastebin.com/0zYLaR1V

PS How to get rid off an additional little roll when rotating camera around, so it will move in a game fashion way?

PS2 And where did the imaginery numbers gone when implementing quaternion math to programming language?? ^^ This is a true mystery for me.

  • \$\begingroup\$ If you're applying your rotations strictly sequentially like this, separated by axis, and converting to a matrix every time you need to transform a vector, then I'm not sure that you're gaining anything by using a quaternion representation in the first place. I love quaternions, but for the code you've shown above Euler angles would have the same effect and be easier to read/debug. In fact, Euler angles are often useful for camera movement in games, since they give a clear mapping for axis-selective constraints (John Nesky gave a talk on this at this year's GDC). \$\endgroup\$
    – DMGregory
    Apr 2, 2014 at 21:33
  • \$\begingroup\$ @DMGregory By saying "separated by axis" you mean that I have got two functions, one for vertical and one for horizontal rotation? If so, is in this case this function appropiate for quaternions? rotateCamera: function(angleX, angleY) { var quatX = new Quaternion(); var quatY = new Quaternion(); quatX = (new Quaternion().axisToQuaternion(angleY, 1, 0, 0)); quatY = (new Quaternion().axisToQuaternion(angleX, 0, 1, 0)); this.rotation.multiply(quatX.multiply(quatY)); this.position.multiply(this.rotation.quaternionToMatrix()); this.rotation.makeIdentity(); }, \$\endgroup\$
    – Winged
    Apr 3, 2014 at 8:10
  • \$\begingroup\$ The code above is 'taken' from this post stackoverflow.com/questions/7938373/… and in OP's opinion it should work just fine. And in my case, it still suffers the same problem. And the reason why I want to implement quaternion camera is LERP and SLERP. \$\endgroup\$
    – Winged
    Apr 3, 2014 at 9:15
  • 2
    \$\begingroup\$ If your quaternion is always normalized and your quaterion to matrix code is correct, than you can not have any stretching or slanting. I would check where your quaternion starts to get unnormalized. \$\endgroup\$
    – rioki
    Apr 3, 2014 at 9:31

1 Answer 1


Ahahaha, problem solved, I'm such a math genius ^^: my math library had a typo in function that converts quaternion to a matrix : 1 - 2 * (this.y * this.y - this.z * this.z); - minus times minus makes plus, not minus, as in here: http://www.gameprogrammer.net/delphi3dArchive/quaternions_bestanden/quat1.gif

  • \$\begingroup\$ You can mark your answer as accepted by clicking the check-mark below the voting buttons. (This gives you some rep and helps inform other users you've found an answer that works for you.) \$\endgroup\$
    – Anko
    Apr 3, 2014 at 12:31

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .