MKH
MKH

Reputation: 43

Flipping Opengl drawing without scale by negative numbers

I am trying to draw two 2D diamonds facing each other. So I drew the first diamond then I drew the second diamond after using:

glTranslated(0, -150, 0);

so it can appear exactly under my first diamond . However, I ran into a problem that I couldn't flip the second diamond so it could look like a mirror.

Here is what i am trying to do:

What i am trying to do

I searched online for solutions and they all mentioned that I should use

glScalef(1.0f,-1.0f,1.0f); 

but each time I use it the drawing disappears.

The function

glRotatef(angle,x,y,z); 

caught my attention but i couldn't use it properly resulting in wrong direction.

Here is how my image looks like right now without glRotate():

Without glRotate()

So I think I need the proper technique to use any of these functions.

Note: I am using many line loops and vertices to draw.

  #include <windows.h>  // For MS Windows
  #include <GL/glut.h>   // (or others, depending on the system in use)
  void init(void)
  {
     glClearColor(1.0, 1.0, 1.0, 0.0);  // Set display-window color to 
      white.
    glMatrixMode(GL_PROJECTION);       // Set projection parameters.
    gluOrtho2D(0.0, 400.0, 0.0, 400.0);
  }
  void drawDiamond()
     {
  glBegin(GL_LINE_LOOP);
  glVertex2f(125, 350);
  glVertex2f(245, 350);
  glVertex2f(290, 300);
  glVertex2f(182, 200);
  glVertex2f(75, 300);
  glEnd();


 glBegin(GL_LINE_LOOP);
 glVertex2f(109, 333);
 glVertex2f(138, 350);
 glVertex2f(159, 337);
 glVertex2f(123, 300);
glEnd();

glBegin(GL_LINE_LOOP);
glVertex2f(109, 333);
glVertex2f(123, 300);
glVertex2f(154, 225);
glVertex2f(92, 300);
glEnd();

glBegin(GL_LINE_LOOP);
glVertex2f(290, 300);
glVertex2f(75, 300);
glEnd();

glBegin(GL_LINE_LOOP);
glVertex2f(123, 300);
glVertex2f(159, 337);
glVertex2f(154, 300);
glVertex2f(171, 225);
glEnd();

glBegin(GL_LINE_LOOP);
glVertex2f(181, 300);
glVertex2f(159, 337);
glVertex2f(181, 350);
glVertex2f(209, 337);
glVertex2f(181, 300);
glVertex2f(171, 225);
glEnd();

glBegin(GL_LINE_LOOP);
glVertex2f(181, 300);
glVertex2f(209, 337);
glVertex2f(219, 300);
glVertex2f(195, 225);
glVertex2f(181, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(209, 337);
glVertex2f(243, 300);
glVertex2f(195, 225);
glVertex2f(219, 300);
glEnd();

glBegin(GL_LINE_LOOP);
glVertex2f(209, 337);
glVertex2f(229, 350);
glVertex2f(260, 333);
glVertex2f(243, 300);
glVertex2f(209, 337);
glEnd();

glBegin(GL_LINE_LOOP);
glVertex2f(260, 333);
glVertex2f(278, 300);
glVertex2f(210, 225);
glVertex2f(243, 300);
glEnd();

glBegin(GL_LINE_LOOP);
glVertex2f(195, 225);
glVertex2f(182, 200);
glEnd();

glBegin(GL_LINE_LOOP);
glVertex2f(171, 225);
glVertex2f(182, 200);
glEnd();

}

void display()
{
glClear(GL_COLOR_BUFFER_BIT);  // Clear display window.
glColor3f(0.0, 0.0, 0.0);      // Set line segment color to blue.

                               // your code goes here
drawDiamond();
glTranslatef(0.0f, -150, 0.0f);
drawDiamond();
glFlush();     // Process all OpenGL routines as quickly as possible.

}
void main(int argc, char** argv)
{
glutInit(&argc, argv);                         // Initialize GLUT.
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);   // Set display mode.
glutInitWindowPosition(50, 100);   // Set top-left display-window 
position.
glutInitWindowSize(400, 400);      // Set display-window width and 
height. 
glutCreateWindow("Diamond Project"); // Create display window. 

init();                            // Execute initialization procedure. 
glutDisplayFunc(display);       // Send graphics to display window. 


glutMainLoop();                    // Display everything and wait.      

}

Upvotes: 2

Views: 2813

Answers (3)

Rabbid76
Rabbid76

Reputation: 211287

What you want to do is to mirror (flip) the object around an axis, which is parallel to the X-axis, and goes through the bottom bounding of the object (diamond).

To do so, the bottom Y coordinate (bottomY) has to be found and the object has to be translated in the opposite direction. Note the bottom of the model coordinates (vertices) and not the bottom of final coordinates on the viewport:

float bottomY = 200.0f;
glTranslatef( 0.0f, -bottomY , 0.0f );

At next the object has to be flipped. This can either be done by

glRotatef(180.0f, 1.0f, 0.0f, 0.0f);

or by

glScalef(1.0f, -1.0f, 0.0f)

Note, both operations result in the same transformation matrix, because cos(90°) = cos(-90°), sin(90°) = -sin(90°).

Then the bottomY translation has to be reversed:

glTranslatef( 0.0f, bottomY, 0.0f );

But note that the OpenGL fixed function pipeline stack operates in the the reverse order, because the current matrix is multiplied by the matrix which is specified by the new operation.

Translation: See the documentation of glTranslate:

glTranslate produces a translation by x y z . The current matrix (see glMatrixMode) is multiplied by this translation matrix, with the product replacing the current matrix.

Rotation: See the documentation of glRotate:

glRotate produces a rotation of angle degrees around the vector x y z . The current matrix (see glMatrixMode) is multiplied by a rotation matrix with the product replacing the current matrix.

Scaling: See the documentation of glScale:

glScaleproduces a nonuniform scaling along the x, y, and z axes. The three parameters indicate the desired scale factor along each of the three axes. The current matrix (see glMatrixMode) is multiplied by this scale matrix.


This means the the following should do what you want:

float bottomY = 200.0f;

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

drawDiamond();

glTranslatef( 0.0f, bottomY , 0.0f );
glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );
glTranslatef( 0.0f, -bottomY , 0.0f );

drawDiamond();

and is the same as:

glTranslatef( 0.0f, bottomY , 0.0f );
glScalef( 1.0f, -1.0f, 1.0f );
glTranslatef( 0.0f, -bottomY , 0.0f );  

Upvotes: 1

corsel
corsel

Reputation: 325

For each vertex (I'm assuming that you use immediate mode for designating vertices), you can glVertex2i(myVertex.x, symmetryLine - myVertex.y, 0) where myVertex are the x and y values you previously used, and symmetryLine the value you wish to mirror against. Best way would be to use a negative glScale though. Your diamond is rotationally symmetric glRotate also works but you know, not a very elegant way to do it.

Upvotes: 0

Francis Cugler
Francis Cugler

Reputation: 7925

Depending on how your vertices are setup and depending on if you have Back Face Culling enabled you might have to change your diamond or (model's) center point to be the bottom tip from there you can then simply rotate about the X axis provided that you declared that as the Horizontal Axis. To do so shouldn't be all that hard. It would look something like:

glRotatef( 180.0f, 1, 0, 0 );

provided you are rotating in degrees as opposed to radians.

Upvotes: 0

Related Questions