I have this mini project i do with C++ / OpenGL that allows the user to draw shapes on the screen using his mouse.
Now i want to allow the user to move/pan the screen left and right using his keyboard, let's say there are 4 shapes on the screen on different places, i want them all to move left when "A" key is pressed.
I already managed to do it in a previous project and even zoom in / out but in this program something just doesn't work, the closest thing that i managed to do is that all the new shapes user is creating after the "A" key is pressed are in the new place instead of where his mouse is.
Here are my main,init,display and keyboard code:
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(W_WIDTH, W_HEIGHT);
glutInitWindowPosition(100, 100);
glutCreateWindow("OpenGL Excercise");
init();
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutPassiveMotionFunc(My_mouse_routine);
createMenu();
glutMainLoop();
}
void init()
{
// Select a clear color
glClearColor(0.933, 0.933, 0.933, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
gluOrtho2D(0, W_WIDTH, W_HEIGHT, 0);
}
void display() {/* clear all pixels */
// draw text at the bottom
char* text_to_draw = "Press right mouse button for menu...";
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, W_WIDTH, 0, W_HEIGHT);
glColor3f(0.129, 0.129, 0.129);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glRasterPos2i(10, W_HEIGHT - 15); // move in 10 pixels from the left and bottom edges
for (int i = 0; i < (int)strlen(text_to_draw); ++i) {
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, text_to_draw[i]);
}
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glFlush();
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
exit(0);
case 'A':
case 'a':
glMatrixMode(GL_PROJECTION); //start editing the projection matrix
glLoadIdentity(); //remove current projection
glPopMatrix();
gluOrtho2D(1,0,1,0); //create new one
glPushMatrix();
glMatrixMode(GL_MODELVIEW); //back to editing the modelview matrix
glFlush();
default:
break;
}
glutPostRedisplay();
}
And finally here's an example for a rectangle drawing:
GLfloat colors[][3] = { { 0.957f, 0.263f, 0.212f },{ 0.298f, 0.686f, 0.314f },{ 0.129f, 0.588f, 0.953f }, };
static int col = 0;
glColor3f(colors[col][0], colors[col][1], colors[col][2]);
glBegin(GL_POLYGON);
glVertex3f(mouse_x - 50, mouse_y - 50, 0.0);
glVertex3f(mouse_x + 50, mouse_y - 50, 0.0);
glVertex3f(mouse_x + 50, mouse_y + 50, 0.0);
glVertex3f(mouse_x - 50, mouse_y + 50, 0.0);
glEnd(); /* don't wait!!! start processing buffered OpenGL routines */
col += 1;
if (col == sizeof(colors) / sizeof(colors[0])) {
col = 0;
}
glutPostRedisplay();
I know there are a lot of questions about this issue in this site and hundreds of other site, and i'm almost positive it has something to do with the matrices, but i have no idea what am i doing wrong.
Why do you change projection matrix on A
keystroke ?
I assume you want to use WSAD (which is extremly uncomfortable for the old-school OPQAM guys like me) to pan the view.
The first problem is that you changing GL_PROJECTION
on A
keystroke but reseting it while rendering in display()
render the keystroke code doing nothing. To remedy that you should init the GL_PROJECTION
in your init()
function. Btw you are missing glMatrixMode
there and remove it from display()
.
Another problem is that you are using camera/view matrix inside GL_PROJECTION
instead of GL_MODELVIEW
which is called:
Which will lead you to serious problems when you go for advanced lighting and fog (unless you switch to GLSL).
And lastly as you set view by ortho then you should pan just with glTranslate
That is at least my opinion.
where is your scene stored?
From your text I assumed this should be some simple vector paint like editor able to add/draw shapes into scene. So you need to have some kind of lists capable of storing all the info for your scene like:
I do not see such info in your code, instead I see using mouse coordinates directly which is fine for preview of last added point but will fail for more complex shapes like line.
Here take a look at:
for some ideas how it can be done.