0

Im working on a 3D platformer where theres a large platform and a character made up of multiple cubes.

However when I try rotating the Y axis of the characters cubes it doesn't rotate them at their centerpoint. They just orbit as a whole around the platform in a huge circle. I'm guessing my glRotatef's are in the wrong order but I cant seem to figure out what order they should be to make the group of cubes rotate only around their center point.

My code for drawing them is:

for (int i = 0; i < Models.size(); i++){ // theres only one model this has to go through that stores the group of cubes for the character
    glPushMatrix(); // set rotation for the whole group (I would expect...)
    glRotatef(Models.at(i)->ModelRotation.X,1,0,0);
    glRotatef(Models.at(i)->ModelRotation.Y,0,1,0);
    glRotatef(Models.at(i)->ModelRotation.Z,0,0,1);
    for (int j = 0; j < Models.at(i)->Parts.size(); j++) // For each cube in the character,
        Models.at(i)->Parts.at(j)->Render(); // draw the cube
    glPopMatrix();
}

Model is a struct that just has a vector3 called "ModelRotation" and a normal vector called "Parts" which stores all the cubes for the character.

My function for rendering the cube in the cube class is:

void Render(){
    glPushMatrix();
    glTranslatef(   Position.X,
                    Position.Y,
                    Position.Z
    );
    glColor3f(      Color.R,
                    Color.G,
                    Color.B
    );
    glScalef(       Size.X,
                    Size.Y,
                    Size.Z
    );

    // Render the front quad
    //glBindTexture(GL_TEXTURE_2D, Faces[0]);
    glBegin(GL_QUADS);
        glTexCoord2f(0, 0); glVertex3f(  1.0f, -1.0f, -1.0f );
        glTexCoord2f(1, 0); glVertex3f( -1.0f, -1.0f, -1.0f );
        glTexCoord2f(1, 1); glVertex3f( -1.0f,  1.0f, -1.0f );
        glTexCoord2f(0, 1); glVertex3f(  1.0f,  1.0f, -1.0f );
    glEnd();

    // Render the left quad
    //glBindTexture(GL_TEXTURE_2D, Faces[1]);
    glBegin(GL_QUADS);
        glTexCoord2f(0, 0); glVertex3f(  1.0f, -1.0f,  1.0f );
        glTexCoord2f(1, 0); glVertex3f(  1.0f, -1.0f, -1.0f );
        glTexCoord2f(1, 1); glVertex3f(  1.0f,  1.0f, -1.0f );
        glTexCoord2f(0, 1); glVertex3f(  1.0f,  1.0f,  1.0f );
    glEnd();

    // Render the back quad
    //glBindTexture(GL_TEXTURE_2D, Faces[2]);
    glBegin(GL_QUADS);
        glTexCoord2f(0, 0); glVertex3f( -1.0f, -1.0f,  1.0f );
        glTexCoord2f(1, 0); glVertex3f(  1.0f, -1.0f,  1.0f );
        glTexCoord2f(1, 1); glVertex3f(  1.0f,  1.0f,  1.0f );
        glTexCoord2f(0, 1); glVertex3f( -1.0f,  1.0f,  1.0f );
    glEnd();

    // Render the right quad
    //glBindTexture(GL_TEXTURE_2D, Faces[3]);
    glBegin(GL_QUADS);
        glTexCoord2f(0, 0); glVertex3f( -1.0f, -1.0f, -1.0f );
        glTexCoord2f(1, 0); glVertex3f( -1.0f, -1.0f,  1.0f );
        glTexCoord2f(1, 1); glVertex3f( -1.0f,  1.0f,  1.0f );
        glTexCoord2f(0, 1); glVertex3f( -1.0f,  1.0f, -1.0f );
    glEnd();

    // Render the top quad
    //glBindTexture(GL_TEXTURE_2D, Faces[4]);
    glBegin(GL_QUADS);
        glTexCoord2f(0, 1); glVertex3f( -1.0f,  1.0f, -1.0f );
        glTexCoord2f(0, 0); glVertex3f( -1.0f,  1.0f,  1.0f );
        glTexCoord2f(1, 0); glVertex3f(  1.0f,  1.0f,  1.0f );
        glTexCoord2f(1, 1); glVertex3f(  1.0f,  1.0f, -1.0f );
    glEnd();

    // Render the bottom quad
    //glBindTexture(GL_TEXTURE_2D, Faces[5]);
    glBegin(GL_QUADS);
        glTexCoord2f(0, 0); glVertex3f( -1.0f, -1.0f, -1.0f );
        glTexCoord2f(0, 1); glVertex3f( -1.0f, -1.0f,  1.0f );
        glTexCoord2f(1, 1); glVertex3f(  1.0f, -1.0f,  1.0f );
        glTexCoord2f(1, 0); glVertex3f(  1.0f, -1.0f, -1.0f );
    glEnd();
    glPopMatrix();
};

Any help would be very much appreciated. I'm guessing it's just a simple mistake I can't put together. I'll show more code if it's needed.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
jayrhino
  • 1
  • 3
  • 3
    Possible duplicate of [Rotating a multipart object](https://stackoverflow.com/questions/46720166/rotating-a-multipart-object) – Rabbid76 Nov 19 '17 at 19:04
  • Possible duplicate of [OpenGL translation before and after a rotation](https://stackoverflow.com/questions/49236745/opengl-translation-before-and-after-a-rotation) – Rabbid76 Nov 17 '18 at 08:49

1 Answers1

0

The way OpenGL applies the transformations is from bottom to top between PopMatrix() and PushMatrix(), that is the inverse from the way you are actually coding them.

In your code, the order in which you are calling is flipped like this:

Rotatef(); 
Translatef();
Scalef();

It should be:

Translatef();
Rotatef();
Scalef();

In other words, you want to translate always as last (meaning putting it into your code as the very first line after the PopMatrix()) unless you have a good reason (a particular graphic effect or scene rendering), so that you first apply scaling and rotation transformations and then you translate the object in world coordinates.

For rotating multipart objects (as your case) you should probably translate twice, as explained here: Rotating a multipart object

So your code outside the cube class could be something like:

for (int i = 0; i < Models.size(); i++){ 
    glPushMatrix(); 
    glTranslatef( 
        Models.at(i)->WorldPosition.X,
        Models.at(i)->WorldPosition.Y,
        Models.at(i)->WorldPosition.Z,
    );
    glRotatef(Models.at(i)->ModelRotation.X,1,0,0);
    glRotatef(Models.at(i)->ModelRotation.Y,0,1,0);
    glRotatef(Models.at(i)->ModelRotation.Z,0,0,1);
    for (int j = 0; j < Models.at(i)->Parts.size(); j++) 
        Models.at(i)->Parts.at(j)->Render(); // draw the cube
    glPopMatrix();
}
Habardeen
  • 321
  • 2
  • 11