Jump to content
  • Advertisement
Sign in to follow this  
YellowMaple

Rotation about an arbitrary axis

This topic is 4440 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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
Advertisement
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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!