glOrtho & gluUnProject troubles...

  • Follow


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

0
Reply libero.spagnolini (6) 12/9/2005 12:09:29 AM

I solved it by choosing different coordinates for different views to
compute pan offset:
void ComputeDistances(int oldP[2], int newP[2], float* dx, float* dy)
{
..
..
..
	switch(side){
		case FRONT:
			*dx = nP[0] - oP[0];
			*dy = nP[1] - oP[1];
			break;
		case TOP:
			*dx = nP[0] - oP[0];
			*dy = -(nP[2] - oP[2]);
			break;
		case RIGHT:
			*dx = -(nP[2] - oP[2]);
			*dy = nP[1] - oP[1];
	}
}

I guess this works because gluUnProject return object coordinates so I
must, for instance in the top view, move along object z to get window
y.

Libe

0
Reply Libero 12/11/2005 12:51:06 PM


1 Replies
225 Views

(page loaded in 0.051 seconds)

Similiar Articles:






7/23/2012 10:37:38 AM


Reply: