PDA

View Full Version : Manually do a glRotatef

DannyG
10-02-2010, 02:58 PM
Before drawing some objects I am modifying the modelview matrix like so

gl.glTranslatef(tX, tY, tZ);
gl.glRotatef(angle, rX, rY, 0);

which produces the result I want. However my project requires to do these matrix modifications manually.

So modifying my vertices like this gives the desired translation (I am using vertex arrays)

vertice[i] = vertice[i] + tX;
vertice[i+1] = vertice[i+1] + tY;
vertice[i+2] = vertice[i+2] + tZ;

However the rotation seems to be troublesome..
I looked up the way glRotatef modifies the matrix
http://www.opengl.org/sdk/docs/man/xhtml/glRotate.xml

So I recreated it, leaving out the Z stuff as that is 0, will return 0 within the subcalculations and therefore is not of any matter.

[A B C]
[D E F]
[G H I]

float c = (float) Math.cos(angle);
float s = (float) Math.sin(angle);
float A = rX*rX*(1-c) + c;
float B = rX*rY*(1-c);
float C = rY*s;
float D = rY*rX*(1-c);
float E = rY*rY*(1-c) + c;
float F = -rX*s;
float G = -rY*s;
float H = rX*s;
float I = c;

Then I multiplied the current (normalized) vector [rX, rY, 0] with this matrix to create a new vector (again leaving out the Z as it is 0)

float nX = (float) (A*rX + B*rY);
float nY = (float) (D*rX + E*rY);

Now when I modify my vertices with this new vector, it does not give the same results as it would with glRotatef

vertice[i] = vertice[i] * nX;
vertice[i+1] = vertice[i+1] * nY;

I tried swapping the translations and rotations without any joy. As far as I know, no prior modifications are made to the current model matrix.

Am I overlooking something here?

david_f_knight
10-02-2010, 04:57 PM
I haven't studied your stuff closely yet, but there is one thing that jumps right out. glRotatef() takes its angle in degrees, but cos() and sin() take their angles in radians. So, you need to convert angle from degrees into radians, like so:

radians = degrees * PI / 180.0.;

DannyG
10-02-2010, 05:15 PM
Hi David,

yes that's true, I forgot to mention that I did convert angle to degrees when using in glRotatef and to radians when using it in the cos / sin functions

marshats
10-02-2010, 06:13 PM
Use normalized rX, rY, rZ in your calculation of A,B,C ... I. Then you have the complete normalized rotation matrix R. Do not multiply it by [rX,Ry,0].

But Beyond that I am confused what you are doing. You should be simply concatenating matrices then at the very end do a single matrix*vector operation. ie T*R*Model_vertices transforms the model vertices to achieve translate+rotate.

I am assuming that you are saying the model vertex is [vx,vy,vz]=[v[i],v[i+1],v[i+2]] and you want to rotate and translate it. If you are trying to avoid building the matrices and you calculate A,B,C ... with _normalized [rX,rY,rX] then the answer really is

vx_tmp=[A*vx+B*vy+C*vz]+tx
vy_tmp=[D*vx+E*vy+F*vz]+ty
vz_tmp=[G*vx+H*vy+I*vz]+tz
*_tmp required because vx,vy,xz must not change in intermediate calculations.
vx=vx_tmp
vy=vy_tmp
vz=vz_tmp

Now if you ever want to translate first then rotate, the non-matrix approach is going to give a lot different answer. In the long run, it may be worth time and effort to learn how to do everything with 4x4 matrices.

DannyG
10-03-2010, 04:48 AM
Hi Marshats,

vX, vY (and vZ but is left out) are indeed normalized in my calculations.

Shouldn't the outcome vx, vy, vz after the rotation matrix multiplication be scalars that the initial vertice x,y,z should be multiplied with? In which case you'd get extreme numbers if the tx, ty and tz are added to those..

marshats
10-03-2010, 08:02 AM
Shouldn't the outcome vx, vy, vz after the rotation matrix multiplication be scalars that the initial vertice x,y,z should be multiplied with?

No, you should not end up with a scalar! This is where thinking in terms of 4x4 matrices is very helpful as follows;

openGL defines the translation and rotation matrices as
T=[1 0 0 tx R=[A B C 0
0 1 0 ty D E F 0
0 0 1 tz G H I 0
0 0 0 1] 0 0 0 1]
where A,B,C ... I are computed by rotating angle degrees about
the normalized axis of rotation vector [rx,ry,rz]/sqrt(rx^2+ry^2+rz^2]

gl.glTranslatef(tx, ty, tz);
gl.glRotatef(angle, rx, ry, rz);

are equivalent to setting the modelview matrix to T*R

T*R=[A B C tx now assume model vertex v=[vx
D E F ty vy
G H I tz vz
0 0 0 1] 1]

hence when you call glDraw* with model vertices composed of many [vx,vy,vz,1]
each vertex is transformed (rotation first + translation second)
by definition above to

T*R*v=[A*vx+B*vy+C*vz+tx*1 [vx_tmp
D*vx+E*vy+F*vz+ty*1 = vy_tmp
G*vx+H*vy+I*vz+tz*1 vz_tmp
0*vx+0*vy+0*vz+ 1*1] 1]

which is the answer given in the previous post.

DannyG
10-03-2010, 12:22 PM
Hi Marshats,

I didn't mean a single scalar, but x,y,z scalars which are in fact the vx_tmp, vy_tmp and vz_tmp numbers of the outcome vector in your calculation.

I need to do this

original vertex x * vx_tmp
original vertex y * vy_tmp
original vertex z * vz_tmp

in order to calculate the final vertex right?

Because as normalized vectors are being used, how would the calculation take the original vertex position into account?

marshats
10-03-2010, 12:39 PM

vx = original vertex x
vy = original vertex y
vz = original vertex z

The final vertex is simply
[vx_tmp,vy_tmp,vz_tmp,1]

vx_tmp = A*original_vertex_x+B*original_vertex_y+C*original _vertex_z+tx*1
... similarly for vy_tmp and vz_tmp

PS A better name than *_tmp would probably be *_rotated_and_translated_result but that was too long for me to type each time ;)

DannyG
10-03-2010, 02:03 PM
YES!! IT WORKS!