943,589 Members | Top Members by Rank

Ad:
May 8th, 2009
0

OpenGL - Transformation matrix

Expand Post »
Hello, everyone!

I'm starting to learn OpenGL and I have a problem with linear transformations.

The program is very basic: I want to draw 4 squares and make them move individually (by doing translations and rotation). I understand that I need to stock all the transformation in a matrix, so I can multiply it to the square information to get the good translation and rotation parameters. Unfortunately, the red square (the one missing) doesn't want to print on the screen. I have searched for a long time and I don't know what causes the problem: maybe a bad mode initialize or something else... Can someone help me? I have posted the code below.

N.B: You may need to add some includes for the code to work. My confguration of OpenGL only needs <gl/glut.h>

#include <gl/glut.h>
#include <stdio.h>

/**
	This program draws 4 squares and do moves on them (translations, rotations, ...)
*/

GLint windowX;
GLint windowY;

GLdouble redTransformationMatrix[16];

void reshape(GLint x, GLint y)
{
	windowX = x;
	windowY = y;

	glViewport(0,0,windowX,windowY);						// Reset The Current Viewport

	glMatrixMode(GL_PROJECTION);						// Select The Projection Matrix
	glLoadIdentity();									// Reset The Projection Matrix

	glMatrixMode(GL_MODELVIEW);							// Select The Modelview Matrix
	glLoadIdentity();									// Reset The Modelview Matrix
}

/**
	\brief	Initializes transformations.
*/
void init()
{
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glGetDoublev(GL_MODELVIEW_MATRIX, redTransformationMatrix);		//Sets the red square transformation matrix with an identity matrix.
}

/**
	\brief Function that is called when a key is pressed on the keyboard.
	\param key		The ASCII value of the key.
	\param x		The x value of the mouse position at the event.
	\param y		The y value of the mouse position at the event.
*/
void keyboardPressed(unsigned char key, int x, int y)
{
	switch (key)
	{
		case 'D':
		case 'd':
		{
			//Translation of the red square.
			glMatrixMode(GL_MODELVIEW);
			glLoadMatrixd(redTransformationMatrix);
			glTranslated(25.0, 0.0, 0.0);
			glGetDoublev(GL_MODELVIEW, redTransformationMatrix);
			glutPostRedisplay();
			break;
		}

	}
}

/**
	\brief Function that draws a square, knowing the middle point and the length of a side.
	\param middleX		The X coordinate of the middle point.
	\param middleY		The Y coordinate of the middle point.
	\param sideLength	The length of a side of the square.
*/
void DrawSquare(GLdouble middleX, GLdouble middleY, GLdouble sideLength)
{
	glBegin(GL_QUADS);
	glVertex2d(middleX - (sideLength / 2), middleY + (sideLength / 2));
	glVertex2d(middleX + (sideLength / 2), middleY + (sideLength / 2));
	glVertex2d(middleX + (sideLength / 2), middleY - (sideLength / 2));
	glVertex2d(middleX - (sideLength / 2), middleY - (sideLength / 2));
	glEnd();
}

/**
	\brief Function that is called for every display on the screen.
*/
void display()
{
	glMatrixMode(GL_MODELVIEW);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    // Reset the current modelview matrix
    glLoadIdentity();		//Makes sure that no affine transformation applies here.

	//We need to set the viewport and the orthonormal bounds.
	glViewport(0, 0, windowX, windowY);
	glOrtho(0.0, windowX, 0.0, windowY, -1.0, 1.0);

	//Let's draw the squares.
	//Red square -- trying here to apply the transformation matrix on the red square.
	glPushMatrix();
	glLoadMatrixd(redTransformationMatrix);
	glColor3d(1.0, 0.0, 0.0);
	DrawSquare(200.0, 600.0, 100.0);
	glPopMatrix();

	//Green square
	glColor3d(0.0, 1.0, 0.0);
	DrawSquare(600.0, 600.0, 100.0);
	//Blue square
	glColor3d(0.0, 0.0, 1.0);
	DrawSquare(600.0, 200.0, 100.0);
	//Yellow square
	glColor3d(1.0, 1.0, 0.0);
	DrawSquare(200.0, 200.0, 100.0);

	glutSwapBuffers();		//Very important, because we are using double buffers and we want to print.
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);

	glClearColor(0.0, 0.0, 0.0, 0.0);		//Black background color.

	windowX = 800;
	windowY = 800;

	glutInitWindowPosition(0, 0);
	glutInitWindowSize(windowX, windowY);

	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);

	glutCreateWindow("FourSquares");

	//Basic initialize...
	init();
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glutKeyboardFunc(keyboardPressed);
	glutReshapeFunc(reshape);
	glutDisplayFunc(display);

	//The events may start.
	glutMainLoop();

	return 0;
}
Similar Threads
Reputation Points: 72
Solved Threads: 26
Posting Whiz in Training
GDICommander is offline Offline
209 posts
since Jun 2008
May 8th, 2009
0

Re: OpenGL - Transformation matrix

You setup an orthographic projection matrix, and then in the pushmatrix/popmatrix block, you load a matrix in model space, this 'undoes' your projection until the matrix is popped...

You could either replace this:
glPushMatrix();
glLoadMatrixd(redTransformationMatrix);
glColor3d(1.0, 0.0, 0.0);
DrawSquare(200.0, 600.0, 100.0);
glPopMatrix();
with this:
glPushMatrix();
glMultMatrixd(redTransformationMatrix);
glColor3d(1.0, 0.0, 0.0);
DrawSquare(200.0, 600.0, 100.0);
glPopMatrix();
Which will work in this case, or much better, use the projection matrix aswell.

The projection matrix is automatically multiplied onto the modelview matrix during vertex transform, and that's typically where glOrtho/glFrustum/etc are used. Eg:
//  VIEWPORT AND BUFFER CLEAR FIRST, BECAUSE THEY ARE MATRIX-MODE INDEPENDANT

glViewport(0, 0, windowX, windowY);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// SETUP ORTHOGRAPHIC PROJECTION

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, windowX, 0.0, windowY, -1.0, 1.0);

// NOW RESET THE MODELVIEW

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// ... ETC...
Moderator
Featured Poster
Reputation Points: 522
Solved Threads: 64
Veteran Poster
MattEvans is offline Offline
1,091 posts
since Jul 2006
May 10th, 2009
0

Re: OpenGL - Transformation matrix

Thanks for the help! My main error was the use of the GL_MODELVIEW flag instead of the GL_MODELVIEW_MATRIX flag.

Now I would like to do rotations. I know how to use glRotate*(), but I don't want to provide a vector expressed by the origin. For example, I would like to put a vector at the center of a square and make this square rotate around this vector. Any ideas to guide me?
Reputation Points: 72
Solved Threads: 26
Posting Whiz in Training
GDICommander is offline Offline
209 posts
since Jun 2008
May 10th, 2009
1

Re: OpenGL - Transformation matrix

It's easy enough to arbitrarily set the rotation point, e.g. this will work:

case 'E':
case 'e':
{
	//Rotation of the red square.
	glMatrixMode(GL_MODELVIEW_MATRIX);
	glLoadMatrixd(redTransformationMatrix);
	glTranslated(200.0, 600.0, 0.0);
	glRotated(1.0,0.0, 0.0, 1.0);
	glTranslated(-200.0, -600.0, 0.0);
	glGetDoublev(GL_MODELVIEW_MATRIX, redTransformationMatrix);
	glutPostRedisplay();
	break;
}

The general rule is, translate to the origin, rotate, and then translate back again.

However, you are making your life abit more difficult by offsetting the square outside of the matrix.. that is, you are doing matrix transforms, and then offseting by 200, 600 in that space.. you'll find it easier to initialize your matrix to that 200, 600 offset, and then always draw the square at 0,0 in the space of your matrix transform.

That is, if you do this:

void init()
{
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslated (200.0, 600.0, 100.0);
	glGetDoublev(GL_MODELVIEW_MATRIX, redTransformationMatrix);
}
...
void display()
{
...
	glPushMatrix();
	glLoadMatrixd(redTransformationMatrix);
	glColor3d(1.0, 0.0, 0.0);
	DrawSquare(0.0, 0.0, 0.0);
	glPopMatrix();
...
}

Then, you can just do this:

case 'E':
case 'e':
{
	//Rotation of the red square.
	glMatrixMode(GL_MODELVIEW_MATRIX);
	glLoadMatrixd(redTransformationMatrix);
	glRotated(1.0,0.0, 0.0, 1.0);
	glGetDoublev(GL_MODELVIEW_MATRIX, redTransformationMatrix);
	glutPostRedisplay();
	break;
}

You will find, when you do get it rotating properly, that any subsequent translation will be in the local space of the previous transform. That is, what you consider to be moving in 'x' will actually be moving in the rotated x direction. If that's what you want, great, otherwise, you can keep transforming in global 'x' by reversing the translate multiplication order, like this:

case 'D':
case 'd':
{
	//Translation of the red square.
	glMatrixMode(GL_MODELVIEW_MATRIX);
	glLoadIdentity ( );
	glTranslated(25.0, 0.0, 0.0);
	glMultMatrixd(redTransformationMatrix);
	glGetDoublev(GL_MODELVIEW_MATRIX, redTransformationMatrix);
	glutPostRedisplay();
	break;
}
Last edited by MattEvans; May 10th, 2009 at 5:58 pm.
Moderator
Featured Poster
Reputation Points: 522
Solved Threads: 64
Veteran Poster
MattEvans is offline Offline
1,091 posts
since Jul 2006
May 11th, 2009
0

Re: OpenGL - Transformation matrix

Thank you for all your tips. Now I understand how to do rotations and translations properly.
Reputation Points: 72
Solved Threads: 26
Posting Whiz in Training
GDICommander is offline Offline
209 posts
since Jun 2008

This thread is solved

Either the thread starter or a moderator has marked this thread as solved. You can most likely trust the responses and answers given. There is most likely no reason for any further responses to be posted here. If you have a related question, please start a new thread in this forum instead.

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in Game Development Forum Timeline: High Score program
Next Thread in Game Development Forum Timeline: RPG Battle Algorithms





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC