#### Archived

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

# 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.

## 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 on other sites
If I rotate by 90 degrees 4 times, then I should return the point I started. But it''s not working.

##### Share on other sites
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 on other sites
// Use this code and be happyvoid RotatationMatrix(REAL* m, REAL* axis, REAL rad){// REAL is a typedef (float/double)if(!Vector_IsNormalized(axis)){  Vector_Normalize(axis);}// Some precomputationREAL	cosA 	 = Math::Cos(rad); // simply returns Cos/SinREAL	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 on other sites
This is a working code! The result is the same
as

...
glRotate();
glGetFloatv();
...

So cut and paste it!

##### 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;
}

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;
}

1. 1
2. 2
3. 3
Rutin
18
4. 4
JoeJ
14
5. 5

• 14
• 10
• 23
• 9
• 44
• ### Forum Statistics

• Total Topics
632634
• Total Posts
3007564
• ### Who's Online (See full list)

There are no registered users currently online

×