Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

tgraupmann

OpenGL glRotatef (this question lies between OpenGL and Math)

This topic is 5451 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

[url]http://www.opengl.org/developers/documentation/man_pages/hardcopy/GL/html/gl/rotate.html[/url] Look at the above spec. In this statement: Where c = cos(angle), s = sine(angle), and ||( x,y,z )|| = 1 (if not, the GL will normalize this vector). What does this mean? ||( x,y,z )|| = 1 Is it the determinant? How do you take the determinant of a 1 x 3? (if not, the GL will normalize this vector). So this will normalize x, y, z. Like so, correct? float mag = (float)sqrt(x*x+y*y+z*z); x /= mag; y /= mag; z /= mag; I took it to mean that x, y, z should always be normalized. Here''s what I came up with, but am I correct? By angle I''m sure it means radians. Here''s what I''m using. I just doesn''t look like it''s rotating right. CMatrix16 Rotate(float rotDegree, float X, float Y, float Z) { // glRotate multiplies the current matrix // with the following matrix. // // ---------------------- // | xx(1-c)+c , xy(1-c)-zs , xz(1-c)+ys , 0 | // ---------------------- // | yx(1-c)+zs , yy(1-c)+c , yz(1-c)-xs , 0 | // ---------------------- // | xz(1-c)-ys , yz(1-c)+xs , zz(1-c)+c , 0 | // ---------------------- // | 0 , 0 , 0 , 1 | // ---------------------- // Our matrix will do the same: // // ---------------------- // | a00, b04, c08, d12 | // ---------------------- // | e01, f05, g09, h13 | // ---------------------- // | i02, j06, k10, l14 | // ---------------------- // | m03, n07, o11, p15 | // ---------------------- // // a00 will be set to xx(1-c)+c // b04 will be set to xy(1-c)-zs // c08 will be set to xz(1-c)+ys // // e01 will be set to yx(1-c)+zs // f05 will be set to yy(1-c)+c // g09 will be set to yz(1-c)-xs // // i02 will be set to xz(1-c)-ys // j06 will be set to yz(1-c)+xs // k10 will be set to zz(1-c)+c // // and then the current // matrix will be multiplied // by this new transform //normalize x, y, z float magnitude = (float)sqrt(X*X + Y*Y + Z*Z); float x = X / magnitude; float y = Y / magnitude; float z = Z / magnitude; //covert angle to radians float angle = rotDegree / 180.0f * 3.141593f / magnitude; float c = (float)cos(angle); float s = (float)sin(angle); CMatrix16 R; R.SetIdentity(); R.M[0] = x*x*(1-c)+c; R.M[4] = x*y*(1-c)-z*s; R.M[ 8 ] = x*z*(1-c)+y*s; R.M[1] = y*x*(1-c)+z*s; R.M[5] = y*y*(1-c)+c; R.M[9] = y*z*(1-c)-x*s; R.M[2] = x*z*(1-c)-y*s; R.M[6] = y*z*(1-c)+x*s; R.M[10] = z*z*(1-c)+c; *this = *this * R; return R; }

Share this post


Link to post
Share on other sites
Advertisement
quote:
Original post by tgraupmann
[url]http://www.opengl.org/developers/documentation/man_pages/hardcopy/GL/html/gl/rotate.html[/url]

Look at the above spec. In this statement:
Where c = cos(angle), s = sine(angle), and ||( x,y,z )|| = 1
(if not, the GL will normalize this vector).

What does this mean?
||( x,y,z )|| = 1


The || syntax means "magnitude". It''s the length of the vector described by x, y, and z.

quote:

So this will normalize x, y, z. Like so, correct?

float mag = (float)sqrt(x*x+y*y+z*z);
x /= mag;
y /= mag;
z /= mag;

I took it to mean that x, y, z should always be normalized. Here''s what I came up with, but am I correct?


Ayup.

quote:
By angle I''m sure it means radians.

BZZT. You''d think that, wouldn''t you? I still have no freaking clue why OpenGL doesn''t think in radians. But, in fact, it uses degrees.



How appropriate. You fight like a cow.

Share this post


Link to post
Share on other sites

// Use this code and be happy


void RotatationMatrix(REAL* m, REAL* axis, REAL rad)
{

// REAL is a typedef (float/double)


if(!Vector_IsNormalized(axis))
{
Vector_Normalize(axis);
}

// Some precomputation


REAL cosA = Math::Cos(rad); // simply returns Cos/Sin

REAL sinA = Math::Sin(rad);
REAL icosA = (1-cosA);

REAL x = axis[0];
REAL y = axis[1];
REAL z = axis[2];

REAL xsinA = x * sinA;
REAL ysinA = y * sinA;
REAL zsinA = z * sinA;

// Fill the matrix


m[0] = cosA + x*x*icosA;
m[4] = x*y*icosA - zsinA;
m[8] = x*z*icosA + ysinA;
m[12] = 0.0f;

m[1] = x*y*icosA + zsinA;
m[5] = cosA + y*y*icosA;
m[9] = y*z*icosA - xsinA;
m[13] = 0.0f;

m[2] = x*z*icosA - ysinA;
m[6] = y*z*icosA + xsinA;
m[10] = cosA + z*z*icosA;
m[14] = 0.0f;

m[3] = 0.0f;
m[7] = 0.0f;
m[11] = 0.0f;
m[15] = 1.0f;

}

Share this post


Link to post
Share on other sites
I found that my implementation is working correctly. I was seeing a precision problem with OpenGL, where using floats the numbers are off by E-05 after about 64 calls. With double precision OpenGL is off by E-15. Plus it''s always good to use lots of digits for PI if you really want precision.

Call by call the calculations are identical to OpenGLs implementation. The more calls between glMultMatrixd, the more the results skew from OpenGL until it becomes noticeable. I figure it''s best to stick with one implementation and not mix match. Otherwise, odd behavior will become apparent.

Here is the code I used:


CMatrix16 Rotate(double rotDegree, double X, double Y, double Z)
{
// glRotate multiplies the current matrix
// with the following matrix.
//
// ----------------------
// | xx(1-c)+c , xy(1-c)-zs , xz(1-c)+ys , 0 |
// ----------------------
// | yx(1-c)+zs , yy(1-c)+c , yz(1-c)-xs , 0 |
// ----------------------
// | xz(1-c)-ys , yz(1-c)+xs , zz(1-c)+c , 0 |
// ----------------------
// | 0 , 0 , 0 , 1 |
// ----------------------

// Our matrix will do the same:
//
// ----------------------
// | a00, b04, c08, d12 |
// ----------------------
// | e01, f05, g09, h13 |
// ----------------------
// | i02, j06, k10, l14 |
// ----------------------
// | m03, n07, o11, p15 |
// ----------------------
//
// a00 will be set to xx(1-c)+c
// b04 will be set to xy(1-c)-zs
// c08 will be set to xz(1-c)+ys
//
// e01 will be set to yx(1-c)+zs
// f05 will be set to yy(1-c)+c
// g09 will be set to yz(1-c)-xs
//
// i02 will be set to xz(1-c)-ys
// j06 will be set to yz(1-c)+xs
// k10 will be set to zz(1-c)+c
//
// and then the current
// matrix will be multiplied
// by this new transform

//normalize angle, x, y, z
double magnitude = sqrt(X*X + Y*Y + Z*Z);
double x=X, y=Y, z=Z;
if(magnitude != 1.0)
{
x /= magnitude;
y /= magnitude;
z /= magnitude;
}

//covert angle to radians
double angle = (rotDegree / 180.0) * 3.1415926535897932384626433832795;
double c = (double)cos(angle);
double s = (double)sin(angle);
CMatrix16 R;
R.SetIdentity();
R.M[0] = x*x*(1-c)+c;
R.M[4] = x*y*(1-c)-z*s;
R.M[ 8 ] = x*z*(1-c)+y*s;
R.M[1] = y*x*(1-c)+z*s;
R.M[5] = y*y*(1-c)+c;
R.M[9] = y*z*(1-c)-x*s;
R.M[2] = x*z*(1-c)-y*s;
R.M[6] = y*z*(1-c)+x*s;
R.M[10] = z*z*(1-c)+c;

*this = *this * R;

return *this;
}

Share this post


Link to post
Share on other sites

  • 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!