OpenGL: How can I move the 2nd object without moving the whole scene?

Ok, I'm trying to recreate an old classic rocket command using OpenGL in C ++. This is my first foray into OpenGL, although I feel pretty comfortable with C ++ at this point.

I decided that my first task was to figure out how to move 2d objects around the screen, it seemed that it would be quite simple. I created two quick method calls to make triangles or squares:

void makeTriangle(color3f theColor, vertex2f &p1, vertex2f &p2, vertex2f &p3, int &xOffset, int &yOffset) { //a triangle glBegin(GL_POLYGON); glColor3f(theColor.red, theColor.green, theColor.blue); glVertex2f(p1.x, p1.y); glVertex2f(p2.x, p2.y); glVertex2f(p3.x, p3.y); glEnd(); } void makeQuad(color3f theColor, vertex2f &p1, vertex2f &p2, vertex2f &p3, vertex2f &p4, int &xOffset, int &yOffset) { //a rectangle glBegin(GL_POLYGON); glColor3f(theColor.red, theColor.green, theColor.blue); glVertex2f(p1.x, p1.y); glVertex2f(p2.x, p2.y); glVertex2f(p3.x, p3.y); glVertex2f(p4.x, p4.y); glEnd(); } 

color3f and vertex2f are simple classes:

 class vertex2f { public: float x, y; vertex2f(float a, float b){x=a; y=b;} }; class color3f { public: float red, green, blue; color3f(float a, float b, float c){red=a; green=b; blue=c;} }; 

And here is my main file:

 #include <iostream> #include "Shapes.hpp" using namespace std; int xOffset = 0, yOffset = 0; bool done = false; void keyboard(unsigned char key, int x, int y) { if( key == 'q' || key == 'Q') { exit(0); done = true; } if( key == 'a' ) xOffset = -10; if( key == 'd' ) xOffset = 10; if( key == 's' ) yOffset = -10; if( key == 'w' ) yOffset = 10; } void init(void) { //Set color of display window to white glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //Set parameters for world-coordiante clipping window glMatrixMode(GL_PROJECTION); gluOrtho2D(-400.0,400.0,-300.0,300.0); } void display(void) { glClear(GL_COLOR_BUFFER_BIT); color3f aGreen(0.0, 1.0, 0.0); vertex2f pa(-400,-200); vertex2f pb(-400,-300); vertex2f pc(400,-300); vertex2f pd(400,-200); makeQuad(aGreen,pa,pb,pc,pd,xOffset,yOffset); color3f aRed(1.0, 0.0, 0.0); vertex2f p1(-50.0,-25.0); vertex2f p2(50.0,-25.0); vertex2f p3(0.0,50.0); makeTriangle(aRed,p1,p2,p3,xOffset,yOffset); glFlush(); } int main(int argc, char** argv) { // Create Window. glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); glutCreateWindow("test"); // Some initialization. init(); while(!done) { //display functions glutDisplayFunc(display); glutKeyboardFunc(keyboard); // Start event loop. glutMainLoop(); } return 0; } 

The square is defined as the “background” at the moment and consists only of a green rectangle along the bottom of the screen. The red triangle is the “object” I want to move. When you press the key, the offset is saved in the specified direction.

I tried using glTranslatef(xOffset,yOffset,0); , but the problem is that it moves both elements on the screen, not just the red triangle. I tried putting the whole call to draw a triangle between the push and pop matrix operation:

 PushMatrix(); glTranslatef(xOffset,yOffset,0); glBegin(GL_POLYGON); glColor3f(theColor.red, theColor.green, theColor.blue); glVertex2f(p1.x, p1.y); glVertex2f(p2.x, p2.y); glVertex2f(p3.x, p3.y); glEnd(); PopMatrix(); 

As far as I can tell, this destroys any changes that the translation made in advance. I also tried just changing the x and y coordinates before calling a draw, but this just causes a brief flicker before leaving the triangle in its original position:

 p1.x += xOffset; p2.x += xOffset; p3.x += xOffset; p1.y += yOffset; p2.y += yOffset; p3.y += yOffset; 

There must be a good easy way to do this, and I'm just reviewing it. Can anyone suggest a suggestion?

EDIT:

My actual problem was that I never updated the screen after the initial draw. I needed to specify a simple function inside my main loop:

 glutIdleFunc(IdleFunc); 

If the actual IdleFunc looks like this:

 GLvoid IdleFunc(GLvoid) { glutPostRedisplay(); } 

Instead of using glFlush() inside my drawing function, I had to use glutSwapBuffers() . In doing so, the code I first came up with:

 p1.x += xOffset; p2.x += xOffset; p3.x += xOffset; p1.y += yOffset; p2.y += yOffset; p3.y += yOffset; 

Works great for my purposes. I didn’t need to translate the matrix, I just needed to draw an element in another place from one scene to another.

+4
source share
3 answers

GL_MODELVIEW is what you need.

From the OpenGL FAQ, 2.1: http://www.opengl.org/resources/faq/technical/gettingstarted.htm

 program_entrypoint { // Determine which depth or pixel format should be used. // Create a window with the desired format. // Create a rendering context and make it current with the window. // Set up initial OpenGL state. // Set up callback routines for window resize and window refresh. } handle_resize { glViewport(...); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Set projection transform with glOrtho, glFrustum, gluOrtho2D, gluPerspective, etc. } handle_refresh { glClear(...); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Set view transform with gluLookAt or equivalent // For each object (i) in the scene that needs to be rendered: // Push relevant stacks, eg, glPushMatrix, glPushAttrib. // Set OpenGL state specific to object (i). // Set model transform for object (i) using glTranslatef, glScalef, glRotatef, and/or equivalent. // Issue rendering commands for object (i). // Pop relevant stacks, (eg, glPopMatrix, glPopAttrib.) // End for loop. // Swap buffers. } 
+3
source

If I read your code correctly, you only want to rotate one element to the right? If yes, do the following:

  • Call glPushMatrix();
  • then do your spin
  • Save how much you turned.
  • then draw the rotated element
  • then call glPopMatrix();

This will only result in rotation of one object.

EDIT:

I see that this “destroys” the previous turn. Could you clarify? This is the correct way to translate / rotate a single object.

I also notice that you are not initializing the Modelview matrix. You must initialize the Modelview matrix after setting up your PROJECTION matrix. You also need to make sure that you initialize both identity matrices. And finally, make sure that you initialize both matrices each time the screen refreshes. To test this, set a breakpoint on the matrix initialization and see if it hits only once or every frame.

+1
source

You answer your question, that is, the solution:

 glPushMatrix(); glTranslatef(xOffset,yOffset,0); glBegin(GL_POLYGON); glColor3f(theColor.red, theColor.green, theColor.blue); glVertex2f(p1.x, p1.y); glVertex2f(p2.x, p2.y); glVertex2f(p3.x, p3.y); glEnd(); glPopMatrix(); 

This will change the model matrix when drawing the rectangle, and then bring the view matrix back to what it was before. Did you really try to do this? What when is it wrong?

+1
source

Source: https://habr.com/ru/post/1347833/


All Articles