2

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.      

}

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
MKH
  • 43
  • 5
  • By the look of things it appears you are using legacy OpenGL 1.0; if you are able to I would suggest using modern OpenGL version 3.3+ and use shaders. From there you can use a Model View Projection matrix to do all the transformations needed. Also using GLM math library makes things easier. – Francis Cugler Mar 05 '18 at 12:11
  • In my answer to [SO: OpenGl draw a cylinder with 2 points glRotated](https://stackoverflow.com/a/48803949/7478597), I mentioned `glRotatef()`. Btw. rotation about 180 deg. is not the same like mirroring. If rotated item is symmetrically it just looks similar. – Scheff's Cat Mar 05 '18 at 12:11
  • You need to rotate the object around only one of those axes and learn how to use the `glRotatef` function. – Ron Mar 05 '18 at 12:11
  • If you mirror things (e.g. with `glScalef(1, -1, 1)`), this affects the orientation of triangles. (Your model is turned inside out.) Hence, it could become necessary to reverse the back face culling to front face culling (and vice versa). – Scheff's Cat Mar 05 '18 at 12:13
  • Edit in a [mcve]. – genpfault Mar 05 '18 at 16:47

3 Answers3

1

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 );  
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • minY for second model is 50, but the model still disappears, since scale f(x,y,z) , multiplies vertices values by parameters which will result with negative vertices I can't draw (I can only draw 0 and above). – MKH Mar 05 '18 at 18:39
  • I'll edit my post and enter my code so my question will be more clear, – MKH Mar 05 '18 at 18:48
  • 1
    It worked !!! I really appreciate your help . The problem is much clearer now, so shifted it to the x-axis then rotate it 180 degrees then we shifted to the right spot . Thanks. – MKH Mar 05 '18 at 19:09
0

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.

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • so according to my understanding i should translate until it is suitable (at bottom tip) then i can simply rotate – MKH Mar 05 '18 at 12:57
  • However, I don't know where the new center point should be in order to use glRotate(). – MKH Mar 05 '18 at 13:08
  • @MKH It's not so much as translating; you don't want to translate the mesh as a whole for it will move it's location in world space (screen space). You want to set you objects focal point to the tip then rotate. Or you can rotate about the x 180 degrees, then translate it down by how ever far you need to; but when you get into doing affine transformations order is important depending on the handedness of the coordinate system. Order by means of (translating, rotation & scaling) the order does matter! – Francis Cugler Mar 05 '18 at 13:28
0

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.

corsel
  • 315
  • 2
  • 12
  • 'symmetryLine - my vertex.y ' will result with negative numbers which won't make vertices appear on the screen. – MKH Mar 05 '18 at 18:20
  • Nope, that depends on your choice of value. The downmost diamond vertex's y coordinate should be chosen as symmetryLine value to obtain this mirror image. – corsel Mar 05 '18 at 22:46