PDA

View Full Version : ModelView Vs Projection



Ehsan Nekooee
09-06-2009, 02:43 PM
Hi everyone

First, I need to say that I just searched but my problem still stood still !
I wrote my own transformation and rotation functions and I called them elRotateX() for example for rotating around X,y,z axis.



void elRotateX()
{
GLfloat mat[] = {
1, 0, 0, 0, // X Column
0, cos(xRot), -sin(xRot), 0, // Y Column
0, sin(xRot), cos(xRot), 0, // Z Column
0, 0, 0, 1 // Trans
};
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(mat);
}


I also wrote my own



void elLoadIdentity()
{
GLfloat mat[] = {
1, 0, 0, 0, // X Column
0, 1, 0, 0, // Y Column
0, 0, 1, 0, // Z Column
0, 0, 0, 1 // Trans
};
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(mat);
}



and this is the imporatant part of my resize function:


glMatrixMode( GL_PROJECTION );
elLoadIdentity();
gluPerspective(25,(float)w/(float)h,1,200);
glMatrixMode(GL_MODELVIEW);
elLoadIdentity();



My rotation variables (xRot, yRot, zRot) are increased or decreased by Arrow keys.
When I use elRotate functions as above just rotates around Z axis. I pushed and popped matrixes and I replaced GL_MODELVIEWs
with GL_PROJECTION but I can't rotate all three axises together.(for example x,y rotates but z doesn't)
I read some Matrix concepts and I found out MODELVIEW you need to move whole scene with the inverse transformation.
but i didn't get what exactly Projection does.

In my case how can I rotate all three axises?

spurserh
09-06-2009, 02:47 PM
This might help. Here is my replacement for glRotatef. It comes from the formula on this page http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/gl/rotate.html

Just replace BaseType with float if you are unfamiliar with templates:



/**
* @param angle The angle is specified in radians.
*/
template<typename BaseType>
static Matrix MakeRotationMatrix(typename BaseType::Type angle,Vec<BaseType> const&amp;axis)
{
assert(BaseType::mComponentCount==(N-1));
assert(N==4);

Vec<BaseType> normAxis=axis.Normalized();
typename BaseType::Type x=normAxis.x,y=normAxis.y,z=normAxis.z;
typename BaseType::Type c=::cos(angle);
typename BaseType::Type s=::sin(angle);

Matrix ret;
ret[0][0]=x*x*(1-c)+c;
ret[0][1]=x*y*(1-c)-z*s;
ret[0][2]=x*z*(1-c)+y*s;

ret[1][0]=y*x*(1-c)+z*s;
ret[1][1]=y*y*(1-c)+c;
ret[1][2]=y*z*(1-c)-x*s;

ret[2][0]=x*z*(1-c)-y*s;
ret[2][1]=y*z*(1-c)+x*s;
ret[2][2]=z*z*(1-c)+c;

return ret;
}


- Sean

Ehsan Nekooee
09-06-2009, 02:53 PM
Thanx spurserh.

I'll surely try that.
But something tells me that there is something wrong with my glMatriXMode() function.
The thing is I don't know exactly where to use GL_PROJECTION or GL_MODELVIEW.

Ilian Dinev
09-06-2009, 03:09 PM
The projection matrix should only hold the 2 transformations: elLoadIdentity() and gluPerspective(..) . Nothing more!
The camera (view) and stuff are all put inside the modelview matrix.

The problem you're facing is caused by these 2 lines inside your elRotateX() :
glMatrixMode(GL_MODELVIEW); // unnecessary
glLoadMatrixf(mat); // uhoh, you're overwriting!



In elRotateX():
1) remove the redundant glMatrixMode(GL_MODELVIEW);
2) replace glLoadMatrixf(mat) with glMultMatrixf(mat)

In elLoadIdentity():
1) remove the line glMatrixMode(GL_MODELVIEW);
you're good to go.



P.S. for some fun, see how OpenGL behaves if you put all transformations into only one of the 2 matrices: either in GL_PROJECTION or GL_MODELVIEW... the results are identical :D (as long as you don't rely on vertex-normals) . This is because in the end both matrices get internally concatenated into a "ModelViewProjection" matrix.

Ehsan Nekooee
09-07-2009, 03:05 AM
It works now perfectly.

Thanks Ilian