jmac
jmac

Reputation: 79

Performing multiple reflections in OpenGL

My assignment is to perform transformations (reflections) on a 2D object.

Lets say my original object is a circle: o

I want to reflect it across a line y = 5 for example. o | o

Then I want to reflect the two objects across a line x = 5 for example.

o o

__

o o

Then finally I want to reflect the four objects across a line y = 10 for example.

o o | o o

o o | o o

So ultimately I want the end result to include 8 circles.

My question is, how would I go about implementing that into my code?

This is the code for my project:

#include <glut.h>

GLfloat square[4][3] = {{5, 0,0}, {5,20,0},{-5,20,0}, {-5,0,0}};
GLfloat square2[4][3] = { { 10, -5,0 },{ 10,25,0 },{ 0,25,0 },{ 0,-5,0 } };
GLfloat square3[4][3] = { { 0, -5,0 },{ 0,25,0 },{ -10,25,0 },{ -10,-5,0 } };
GLfloat colors[3][3] = {{0,0,1},{1,1,1},{0,0,0}};

void draw_square(void){
     glBegin(GL_POLYGON);
         for(int i = 0; i < 4; i++){
                 glVertex3fv(square[i]);
         }
     glEnd();
}

void draw_square2(void) {
    glBegin(GL_POLYGON);
    for (int i = 0; i < 4; i++) {
        glVertex3fv(square2[i]);
    }
    glEnd();
}

void draw_square3(void) {
    glBegin(GL_POLYGON);
    for (int i = 0; i < 4; i++) {
        glVertex3fv(square3[i]);
    }
    glEnd();
}

void draw_ring(void){
     for(int r =0; r < 360;r+=45){
             glPushMatrix();
             glRotated(r, 0,0,1);
             glTranslated(0,50,0);
             draw_square();
             glPopMatrix();
     }
}

void draw_ring2(void) {
    for (int r = 0; r < 360; r += 45) {
        glPushMatrix();
        glRotated(r, 0, 0, 1);
        glTranslated(0, 50, 0);
        draw_square2();
        glPopMatrix();
    }
}

void draw_ring3(void) {
    for (int r = 0; r < 360; r += 45) {
        glPushMatrix();
        glRotated(r, 0, 0, 1);
        glTranslated(0, 50, 0);
        draw_square3();
        glPopMatrix();
    }
}

The display function below creates the set of overlapping rings that I want to reflect. The way it is now, I only get one set of overlapping rings at the bottom left corner. I want the output to be 8 sets of overlapping rings. Ive been trying to find a way to create the reflections I need, but i cant seem to figure it out.

void display(void){
     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);


         glPushMatrix();
         glColor3fv(colors[0]);
         draw_ring();
         glColor3fv(colors[1]);
         draw_ring2();
         glColor3fv(colors[2]);
         draw_ring3();

         glPopMatrix();


     glFlush();
}

void main(int argc, char** argv){
     glutInit(&argc, argv);
     glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
     glutInitWindowSize(1000,600);
     glutInitWindowPosition(200,100);
     glutCreateWindow("Project 2");
     glClearColor(1.0,1.0,0.0,1.0);
     glEnable(GL_DEPTH_TEST);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
     gluOrtho2D(-100.0, 1000.0, -100.0,600.0);
     glMatrixMode(GL_MODELVIEW);
     glLoadIdentity();
     glutDisplayFunc(display);
     glutMainLoop();
}

Any help would be greatly appreciated.

Upvotes: 1

Views: 870

Answers (1)

Rabbid76
Rabbid76

Reputation: 210877

Note, that drawing by glBegin/glEnd sequences and the fixed function pipeline matrix stack is deprecated since decades. Read about Fixed Function Pipeline and see Vertex Specification and Shader for a state of the art way of rendering.


Anyway, if you want to tile the objects, then you can do this by nested loops:

void draw_object( void )
{
    glPushMatrix();

    glColor3fv(colors[0]);
    draw_ring();
    glColor3fv(colors[1]);
    draw_ring2();
    glColor3fv(colors[2]);
    draw_ring3();

    glPopMatrix();
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    int   tile_x = 4;
    int   tile_y = 2;
    float tile_dist = 200.0f;

    for ( int x = 0; x < tile_x; ++ x )
    {
          for (int y = 0; y < tile_y; ++ y )
          {
              glPushMatrix();
              glTranslatef( (float)x * tile_dist, (float)y * tile_dist, 0.0f );
              draw_object();
              glPopMatrix();
          }
    }

    glFlush();
}

The same tile effect can be achieved by a recursive function:

void display_tiles_recursive( int level, float dist )
{
    if ( level == 0 )
    {
        draw_object();
        return;
    }

    int   tile     = level / 2;
    bool  tile_x   = level % 2 != 0;
    float offset_x = tile_x ? pow(2.0f, (float)tile) * dist : 0.0f;
    float offset_y = tile_x ? 0.0f : pow(2.0f, (float)(tile-1)) * dist;

    glPushMatrix();

    display_tiles_recursive( level - 1, dist );
    glTranslatef( offset_x, offset_y, 0.0f );
    display_tiles_recursive( level - 1, dist );

    glPopMatrix();
}

void display_mirror(void)
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    display_tiles_recursive( 3, 200.0f );
    glFlush();
}

If you want to achieve a repeated mirror effect, then have to mirror the even tiles along the x and y axis. The mirroring can be achieved by glScale. glScalef( -1.0f, 1.0f, 1.0f ); to mirror along the x-axis and glScalef( 1.0f, -1.0f, 1.0f ); to mirror along the y axis. You can extend the recursive tiling function to get this effect:

void display_mirror_recursive( int level, float dist, bool even_x, bool even_y )
{
    if ( level == 0 )
    {
        glPushMatrix();
        if ( even_x )
            glScalef( -1.0f, 1.0f, 1.0f );
        if ( even_y )
            glScalef(  1.0f, -1.0f, 1.0f );
        draw_object();
        glPopMatrix();
        return;
    }

    int   tile     = level / 2;
    bool  tile_x   = level % 2 != 0;
    float offset_x = tile_x ? pow(2.0f, (float)tile) * dist : 0.0f;
    float offset_y = tile_x ? 0.0f : pow(2.0f, (float)(tile-1)) * dist;

    glPushMatrix();
    display_mirror_recursive( level - 1, dist, even_x, even_y );
    glTranslatef( offset_x, offset_y, 0.0f );
    if ( level == 1 )
      even_y = !even_y;
    if ( level == 2)
      even_x = !even_x;
    display_mirror_recursive( level - 1, dist, even_x, even_y );
    glPopMatrix();
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    display_mirror_recursive( 3, 200.0f, false, false );
    glFlush();
}

Upvotes: 1

Related Questions