Sign in to follow this  
YellowMaple

Rotation about an arbitrary axis

Recommended Posts

YellowMaple    174
I'm writing a prototype for a camera and I would like it to be able to orbit around some target point. It is written using OpenGL and C. It seems that if the camera eye is near or on the plane defined by the points (1, 0, -1), (-1, 0, 1), (0, 1, 0) it has trouble rotating for some reason. Also, using the same plane mentioned above, on one side of the plane, moving the mouse up points the camera down, while on the other side, moving the mouse up points the camera up. I'm using rotation matrices to do the work and I've used this as a guide to rotating around an arbitrary axis. I hope that made sense :p Let me know if I need to clarify anything. Thanks! The function below rotates the point 'point' around the axis 'axis' specified by 'angle' in degrees:
void rotateMatrixArbitrary(GLfloat angle, GLfloat* axis, GLfloat* point)
{
  GLfloat yzProj[ 3 ] = { 0.0f, axis[ 1 ], axis[ 2 ] };
  GLfloat xzProj[ 3 ] = { axis[ 0 ], 0.0f, axis[ 2 ] };
  GLfloat d = sqrt(yzProj[ 1 ] * yzProj[ 1 ] + yzProj[ 2 ] * yzProj[ 2 ]);
  
  MATRIX4 m1, m2, m3, mi1, mi2, tmp;

  initMatrix(&m1); initMatrix(&m2); initMatrix(&m3);
  initMatrix(&mi1); initMatrix(&mi2);
  initMatrix(&tmp);
  
  if(d != 0.0)
  {
    m1.matrix[ 1 ][ 1 ] = fabs(yzProj[ 2 ]) / d;
    m1.matrix[ 1 ][ 2 ] = -1.0f * fabs(yzProj[ 1 ]) / d;
    m1.matrix[ 2 ][ 1 ] = fabs(yzProj[ 1 ]) / d;
    m1.matrix[ 2 ][ 2 ] = fabs(yzProj[ 2 ]) / d;
  
    mi1.matrix[ 1 ][ 1 ] = fabs(yzProj[ 2 ]) / d;
    mi1.matrix[ 1 ][ 2 ] = fabs(yzProj[ 1 ]) / d;
    mi1.matrix[ 2 ][ 1 ] = -1.0f * fabs(yzProj[ 1 ]) / d;
    mi1.matrix[ 2 ][ 2 ] = fabs(yzProj[ 2 ]) / d;
  }
  
  d = sqrt(xzProj[ 0 ] * xzProj[ 0 ] + xzProj[ 2 ] * xzProj[ 2 ]);
  
  if(d != 0.0)
  {
    m2.matrix[ 0 ][ 0 ] = fabs(xzProj[ 2 ]) / d;
    m2.matrix[ 0 ][ 2 ] = fabs(xzProj[ 0 ]) / d;
    m2.matrix[ 2 ][ 0 ] = -1.0f * fabs(xzProj[ 0 ]) / d;
    m2.matrix[ 2 ][ 2 ] = fabs(xzProj[ 2 ]) / d;
  
    mi2.matrix[ 0 ][ 0 ] = fabs(xzProj[ 2 ]) / d;
    mi2.matrix[ 0 ][ 2 ] = -1.0f * fabs(xzProj[ 0 ]) / d;
    mi2.matrix[ 2 ][ 0 ] = fabs(xzProj[ 0 ]) / d;
    mi2.matrix[ 2 ][ 2 ] = fabs(xzProj[ 2 ]) / d;
  }

  rotateMatrixZ(angle, &m3);

  // Apply rotations
  matrixMult(m1, point);
  matrixMult(m2, point);
  matrixMult(m3, point);
  matrixMult(mi2, point);
  matrixMult(mi1, point);
}


This is the function which will rotate the camera eye based on mouse movements. the arguements x and y describe how much to rotate around the x (or rather the arbitrary axis) and the y axis respectively. It rotates around the point specified by cam.gaze:
void rotateCamera(GLfloat x, GLfloat y)
{
  // Translate eye so that target is at origin
  cam.eye[ 0 ] -= cam.gaze[ 0 ];
  cam.eye[ 1 ] -= cam.gaze[ 1 ];
  cam.eye[ 2 ] -= cam.gaze[ 2 ];
  
  MATRIX4 rotateY;
  
  rotateMatrixY(y, &rotateY);
  
  GLfloat dir[ 3 ] = { cam.eye[ 0 ], cam.eye[ 1 ], cam.eye[ 2 ] };
  normalize(dir);

  GLfloat rightVec[ 3 ];
  xprod(dir, cam.up, rightVec);
  normalize(rightVec);
  
  rotateMatrixArbitrary(x, rightVec, cam.eye);
  matrixMult(rotateY, cam.eye);

  // Translate eye back
  cam.eye[ 0 ] += cam.gaze[ 0 ];
  cam.eye[ 1 ] += cam.gaze[ 1 ];
  cam.eye[ 2 ] += cam.gaze[ 2 ];
}


Share this post


Link to post
Share on other sites
Lode    1003
Quote:
Original post by YellowMaple
I'm using rotation matrices to do the work and I've used this as a guide to rotating around an arbitrary axis.


There's one thing wrong with this guide in my opinion, because what many guides seem to avoid to mention is that you, the coder, can use just a single matrix to do the rotation around an arbitrary axis.

Here's this matrix as a 3x3 matrix but of course you can easily use this for 4x4. This particular code rotates a single vector but of course you can change it to use this matrix to do anything with it.


Vector3 rotateAroundArbitrary(const Vector3& v, Vector3 axis, float angle)
{
if((v.x == 0) && (v.y == 0) && (v.z == 0)) return Vector3_origin;

Vector3 w;
float c, s, t;

axis.normalize();

//calculate parameters of the rotation matrix
c = cos(angle);
s = sin(angle);
t = 1 - c;

//multiply v with rotation matrix
w.x = (t * axis.x * axis.x + c) * v.x
+ (t * axis.x * axis.y + s * axis.z) * v.y
+ (t * axis.x * axis.z - s * axis.y) * v.z;

w.y = (t * axis.x * axis.y - s * axis.z) * v.x
+ (t * axis.y * axis.y + c) * v.y
+ (t * axis.y * axis.z + s * axis.x) * v.z;

w.z = (t * axis.x * axis.z + s * axis.y) * v.x
+ (t * axis.y * axis.z - s * axis.x) * v.y
+ (t * axis.z * axis.z + c) * v.z;

w.normalize();
w = w * length(v);

return w;
}




I got this matrix from one of the articles on gamedev.net

[Edited by - Lode on May 23, 2006 5:08:02 AM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this