Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am trying to create a WebGL camera based on quaternions. I looked at many tutorials, and none is as simple as it could be or it was not working. How can I create such a camera?

share|improve this question
    
I should clarify that the camera is supposed to be a FPS style camera for a ship in space and the camera shall have 6DOF and no gimbal lock. –  Ray Hulha Dec 23 '12 at 19:37
    
Season's greetings and welcome to GameDev! These things would make your question easier for others to answer: What exactly do you want to do? What have you tried? Why do you think it's not working? –  Anko Dec 23 '12 at 19:48
    
I think this question is a bit to broad and not really constructive. There are lots of ways to create a camera class. You could have a hundred answers to this and one wouldn't be any more correct than the other. –  Byte56 Dec 23 '12 at 22:42
add comment

1 Answer

So I finally came up with this solution. Any suggestions to make the code more efficient are welcome. The code uses the excellent glMatrix math library.

function Camera()
{
   this.position = vec3.create();
   this.rotation = quat4.create();

   quat4.fromAxes([0, 0, 1], [1, 0, 0], [0, 1, 0], this.rotation);
   //mat4.lookAt([0,0,0], [0,0,1], [0,1,0], this.mat);

   //quat4.normalize(this.rotation);

   this.getMVMatrix = function(mat)
   {
      // this next line doesn't work, it rotates around the origin. useful for an OrbitCamera I guess.
      // mat4.fromRotationTranslation(this.rotation, this.position, mat);

      // doesn't seem to be needed: mat4.identity( mat);
      quat4.toMat4( this.rotation, mat);
      mat4.translate( mat, this.position);
   }

   var mat = mat3.create();
   // get the values from column 2. They represent the direction of this matrx
   this.getDir = function()
   {
      //console.log(quat4.str(this));
      quat4.toMat3( this.rotation, mat);
      //console.log(mat3.str(mat));
      var a02 = mat[2],
          a12 = mat[5],
          a22 = mat[8];
      return vec3.createFrom( a02, a12, a22); // todo: reuse temp var
   }

   // get the values from column 1. They represent the up vector of this matrx
   this.getUp = function()
   {
      quat4.toMat3( this.rotation, mat);
      var a01 = mat[1],
          a11 = mat[4],
          a21 = mat[7];
      return vec3.createFrom( a01, a11, a21);
   }

   // get the values from column 0. They represent the left vector of this matrx
   this.getLeft = function()
   {
      quat4.toMat3( this.rotation, mat);
      var a00 = mat[0],
          a10 = mat[3],
          a20 = mat[6];
      return vec3.createFrom( a00, a10, a20);
   }

   this.moveForward = function(amount)
   {
      var dir = this.getDir();
      vec3.normalize(dir);
      vec3.scale(dir, amount);
      vec3.add( this.position, dir);
      //console.log(vec3.str(this.position));
      //console.log( vec3.str(quat4.multiplyVec3( this.rotation, vec3.create(0.0, 0.0, -1))) )
      //vec3.add( this.position, quat4.multiplyVec3( this.rotation, vec3.create(0.0, 0.0, -1)));
   }

   this.moveBackward = function(amount)
   {
      var dir = this.getDir();
      vec3.normalize(dir);
      vec3.scale(dir, amount);
      vec3.subtract( this.position, dir);
      //vec3.add( this.position, quat4.multiplyVec3( this.rotation, vec3.create(0.0, 0.0, amount)));
   }

   this.moveLeft = function(amount)
   {
      var dir = this.getLeft();
      vec3.normalize(dir);
      vec3.scale(dir, amount);
      vec3.add( this.position, dir);
      //vec3.add( this.position, quat4.multiplyVec3( this.rotation, vec3.create(-amount, 0.0, 0.0)));
   }

   this.moveRight = function(amount)
   {
      var dir = this.getLeft();
      vec3.normalize(dir);
      vec3.scale(dir, amount);
      vec3.subtract( this.position, dir);
      //vec3.add( this.position, quat4.multiplyVec3( this.rotation, vec3.create(amount, 0.0, 0.0)));
   }

   var tempQuat = quat4.create();
   this.lookUp = function(amount)
   {
      quat4.fromAngleAxis( -amount, this.getLeft(), tempQuat);
      quat4.multiply( this.rotation, tempQuat);
   }
   this.lookDown = function(amount)
   {
      quat4.fromAngleAxis( amount, this.getLeft(), tempQuat);
      quat4.multiply( this.rotation, tempQuat);
   }
   this.lookLeft = function(amount)
   {
      quat4.fromAngleAxis( -amount, this.getUp(), tempQuat);
      quat4.multiply( this.rotation, tempQuat);
   }
   this.lookRight = function(amount)
   {
      quat4.fromAngleAxis( amount, this.getUp(), tempQuat);
      quat4.multiply( this.rotation, tempQuat);
   }
}
share|improve this answer
2  
"So I finally came up with this solution." Dude, there's literaly a 3 minute window between your question an answer. –  dreta Dec 23 '12 at 19:38
2  
It's really hard to judge the goodness of an answer if I can't figure out what the question is... –  Anko Dec 23 '12 at 20:17
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.