Hello,
I'm in trouble with glOrtho and gluUnProject. To show better the
problem I'm posting a little glut test app at the end of the thread.
In my app I'd like to to display some orthographic views like Front,
Top,
Right; to do this, I'm setting an orthographic projection and before
drawing my model,
I call the appropriate glRotatef (line 62). At this point, my model
gets drawn properly but then when I try to pan, things get messed up.
For panning I compute the world space distance (dx and dy obtained with
gluUnProject) of the mouse drag and offset the center of my view volume
of that amount (line 147-148).
Ok here's the trouble: I don't understand why panning works great in
the Front view (the one I didn't apply any glRotatef) and works only in
one direction in Top and Right...
Maybe gluUnProject and glOrtho don't like each others or maybe (more
likely) I don't understand how glOrtho works.
Any tips?
Thanxs
Libe
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <GL/glut.h>
#define XRES 500
#define YRES 500
typedef enum OrthoSide_
{
TOP, RIGHT, FRONT
} OrthoSide;
typedef struct OrthoView_
{
OrthoSide side;
float near_;
float far_;
float top;
float bottom;
float right;
float left;
float cx; // pan offset
float cy;
} OrthoView;
OrthoSide side = FRONT;
OrthoView orthoViews[3];
int oldPos[2], newPos[2];
void init()
{
int s = 2;
int i = 0;
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
for (i = 0; i < 3; ++i) {
orthoViews[i].top = 1. * s;
orthoViews[i].bottom = 1. * s;
orthoViews[i].right = 1. * s;
orthoViews[i].left = 1. * s;
orthoViews[i].near_ = 1. * s;
orthoViews[i].far_ = 1. * s;
orthoViews[i].side = (OrthoSide)i;
orthoViews[i].cx = orthoViews[i].cy = 0.0;
}
}
void display()
{
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho(orthoViews[side].cx - orthoViews[side].left,
orthoViews[side].cx + orthoViews[side].right,
orthoViews[side].cy - orthoViews[side].bottom,
orthoViews[side].cy + orthoViews[side].top,
-orthoViews[side].near_,
orthoViews[side].far_);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
switch(side) {
case TOP:
glRotatef(90.0, 1.0, 0.0, 0.0);
break;
case RIGHT:
glRotatef(-90.0, 0.0, 1.0, 0.0);
break;
case FRONT:
// default gl orientation
break;
default:
break;
}
glutWireTeapot(0.5);
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(1);
break;
case '1':
side = TOP;
break;
case '2':
side = RIGHT;
break;
case '3':
side = FRONT;
break;
default:
break;
}
glutPostRedisplay();
}
void myReshape(GLsizei w, GLsizei h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
}
void ComputeDistances(int oldP[2], int newP[2], float* dx, float* dy)
{
GLdouble modelview[16];
GLdouble proj[16];
GLint view[4];
GLdouble nP[3], oP[3];
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
glGetDoublev( GL_PROJECTION_MATRIX, proj );
glGetIntegerv( GL_VIEWPORT, view );
// flip y to get it openGL like (0,0) bottom left
gluUnProject( newP[0], view[3] - newP[1], 0.0f,
modelview,
proj,
view,
&nP[0],
&nP[1],
&nP[2] );
gluUnProject( oldP[0], view[3] - oldP[1], 0.0f,
modelview,
proj,
view,
&oP[0],
&oP[1],
&oP[2] );
*dx = nP[0] - oP[0];
*dy = nP[1] - oP[1];
}
int motion(int x, int y)
{
float dx, dy;
newPos[0] = x;
newPos[1] = y;
ComputeDistances(oldPos, newPos, &dx, &dy);
printf("dx: %f, dy: %f\n", dx, dy);
orthoViews[side].cx -= dx;
orthoViews[side].cy -= dy;
oldPos[0] = newPos[0];
oldPos[1] = newPos[1];
glutPostRedisplay();
}
void buttonDown(int button, int state, int x, int y)
{
if ((state == GLUT_DOWN)) {
oldPos[0] = x;
oldPos[1] = y;
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (XRES,YRES);
glutCreateWindow("Ortho Pan Test");
init();
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutReshapeFunc(myReshape);
glutMotionFunc(motion);
glutMouseFunc(buttonDown);
glutMainLoop();
return 0;
}
|