Search code examples
c++openglgraphicscoordinate-transformation

movement of rendered objects in opengl


I'm having trouble moving these objects in an orderly fashion with openGL.

What I want to do is have each object in each row slowly spin and move the right of the screen, and as it disappears from view it should reappear on the other side as if in a loop.

The idle function worked fine for a single object, but it's not working with the group of objects.

#include <stdlib.h>
#include <GL/glut.h>

GLuint objectList;

GLfloat xRotated, yRotated, zRotated;
GLdouble size = 0.5;

float xpos = 0.0;
float ypos = 0.0;
float zpos = 0.0;

int x = 1;
float r, g, b;

/*
* Initialize depth buffer, projection matrix, light source, and lighting
* model.  Do not specify a material property here.
*/
void init(void)
{
    GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 };
    GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat specular[] = { 1.0, 1.0, 1.0, 1.0 };
    GLfloat position[] = { 0.0, 3.0, 3.0, 0.0 };

    GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
    GLfloat local_view[] = { 0.0 };

    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    glLightfv(GL_LIGHT0, GL_POSITION, position);
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
    glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local_view);

    glFrontFace(GL_CW);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_AUTO_NORMAL);
    glEnable(GL_NORMALIZE);
    glEnable(GL_DEPTH_TEST);


    objectList = glGenLists(1);
    glNewList(objectList, GL_COMPILE);
    glutSolidTeapot(0.5);
    glEndList();
}

/*
* Move object into position.  Use 3rd through 12th
* parameters to specify the material property.  Draw a teapot.
*/
void renderObject(GLfloat x, GLfloat y,
    GLfloat ambr, GLfloat ambg, GLfloat ambb,
    GLfloat difr, GLfloat difg, GLfloat difb,
    GLfloat specr, GLfloat specg, GLfloat specb, GLfloat shine)
{
    GLfloat mat[4];

    glPushMatrix();
    glTranslatef(x, y, 0.0);
    mat[0] = ambr; mat[1] = ambg; mat[2] = ambb; mat[3] = 1.0;
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat);
    mat[0] = difr; mat[1] = difg; mat[2] = difb;
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat);
    mat[0] = specr; mat[1] = specg; mat[2] = specb;
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat);
    glMaterialf(GL_FRONT, GL_SHININESS, shine * 128.0);
    glCallList(objectList);
    glPopMatrix();
}

void idle(void) {

    //xRotated += 0.01;
    yRotated += 0.01;
    //zRotated += 0.01;

    if (xpos > -1 && x == 1) {

        xpos = -15;
        ypos = 0;

    }
    else {
        x = 0;

        if (xpos <= 15) {
            xpos += 0.001;
            //ypos += 0.001;
        }
        else {
            xpos = 1;
            ypos = 1;
            x = 1;
        }
    }

    glutPostRedisplay();
}


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

    // glRotatef(xRotated, 1.0, 0.0, 0.0);
    // rotation about Y axis
    glRotatef(xRotated, 1.0, 0.0, 0.0);
    // rotation about the Z axis
    glRotatef(yRotated, 0.0, 1.0, 0.0);
    // scale transformation
    glScalef(1.0, 1.0, 1.0);
    // glut spheres

    renderObject(2.0, 11.0, 0.05375, 0.05, 0.06625,
        0.18275, 0.17, 0.22525, 0.332741, 0.328634, 0.346435, 0.3);
    renderObject(2.0, 8.0, 0.25, 0.20725, 0.20725,
        1, 0.829, 0.829, 0.296648, 0.296648, 0.296648, 0.088);
    renderObject(2.0, 5.0, 0.1745, 0.01175, 0.01175,
        0.61424, 0.04136, 0.04136, 0.727811, 0.626959, 0.626959, 0.6);

    renderObject(6.0, 11.0, 0.25, 0.25, 0.25,
        0.4, 0.4, 0.4, 0.774597, 0.774597, 0.774597, 0.6);
    renderObject(6.0, 8.0, 0.19125, 0.0735, 0.0225,
        0.7038, 0.27048, 0.0828, 0.256777, 0.137622, 0.086014, 0.1);
    renderObject(6.0, 5.0, 0.24725, 0.1995, 0.0745,
        0.75164, 0.60648, 0.22648, 0.628281, 0.555802, 0.366065, 0.4);


    renderObject(10.0, 11.0, 0.0, 0.0, 0.0,
        0.1, 0.35, 0.1, 0.45, 0.55, 0.45, .25);
    renderObject(10.0, 8.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0,
        0.7, 0.6, 0.6, .25);
    renderObject(10.0, 5.0, 0.0, 0.0, 0.0, 0.55, 0.55, 0.55,
        0.70, 0.70, 0.70, .25);

    renderObject(14.0, 11.0, 0.0, 0.05, 0.0, 0.4, 0.5, 0.4,
        0.04, 0.7, 0.04, .078125);
    renderObject(14.0, 8.0, 0.05, 0.0, 0.0, 0.5, 0.4, 0.4,
        0.7, 0.04, 0.04, .078125);
    renderObject(14.0, 5.0, 0.05, 0.05, 0.05, 0.5, 0.5, 0.5,
        0.7, 0.7, 0.7, .078125);

    renderObject(18.0, 11.0, 0.0, 0.05, 0.0, 0.4, 0.5, 0.4,
        0.04, 0.7, 0.04, .078125);
    renderObject(18.0, 8.0, 0.05, 0.0, 0.0, 0.5, 0.4, 0.4,
        0.7, 0.04, 0.04, .078125);
    renderObject(18.0, 5.0, 0.05, 0.05, 0.05, 0.5, 0.5, 0.5,
        0.7, 0.7, 0.7, .078125);


    glutSwapBuffers();
}


void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho(0.0, 16.0, 0.0, 16.0*(GLfloat)h / (GLfloat)w,
            -10.0, 10.0);

    glMatrixMode(GL_MODELVIEW);
}



/*
* Main Loop
*/
int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(750, 750);
    glutInitWindowPosition(50, 50);
    glutCreateWindow(argv[0]);
    init();
    glutReshapeFunc(reshape);
    glutDisplayFunc(display);
    glutIdleFunc(idle);

    glutMainLoop();
    return 0;
}

Solution

  • You have to change the order of the instructions. A rotation around the axis of the object is performed, by multiplying the translation matrix by the rotation matrix.

    object-matrix = translation-matrix * rotation-matrix
    

    enter image description here

    See the documentation of glRotate which clearly says:

    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.


    Adapt your code like this:

    void renderObject(GLfloat x, GLfloat y,
        GLfloat ambr, GLfloat ambg, GLfloat ambb,
        GLfloat difr, GLfloat difg, GLfloat difb,
        GLfloat specr, GLfloat specg, GLfloat specb, GLfloat shine)
    {
        glPushMatrix();
    
        glTranslatef(x, y, 0.0);            // translation-matrix
        glRotatef(yRotated, 0.0, 1.0, 0.0); // multiply by rotation-matrix
        glRotatef(xRotated, 1.0, 0.0, 0.0);
    
        .....
    }
    

    Note, your rotation is very slightly. Change yRotated += 0.01; to yRotated += 1.0;, for debug reasons (the angle is specified in degrees).

    enter image description here