cube: rotation bug(s), brain f***, spend hours...

hi guys,

hope somebody could help.

i want to write a rubik’s cube and im struggling at the very beginning: rotation of the whole cube.

i’ve also had a version that contained the “whole” cube with all surfaces, but for debugging i deleted them and inserted a coordinate system.

if i rotate the cube always in one direction or if i bring him to his initial position everything works fine but if i “shuffle” my key presses a bit the red surface “jumps” to sides where it has not been within the last animation.
in addition: if i rotate the coordinate system and rotate again around the x axis the cube seems to “roll” to the right or left.

i don’t want to have these side effects/bugs. can anyone help me? i think it could be done with some well known placements of glPush/PopMatrix but i’ve already spend hours without success…

thanks!

the attachment doesn’t seem to work, i’ve posted the code within a new post.

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <gl\GL.h>
#include <gl\GLU.h>
#include <gl\glut.h>

// Colors.
#define COLOR_RED        1
#define COLOR_GREEN        2
#define COLOR_BLUE        3
#define COLOR_ORANGE    4
#define COLOR_WHITE        5
#define COLOR_YELLOW    6

static int yRotNew = 0;
static int yRotOld = 0;

static int xRotNew = 0;
static int xRotOld = 0;

// Light values and coordinates.
GLfloat  ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f };
GLfloat  diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f };
GLfloat  specular[] = { 1.0f, 1.0f, 1.0f, 1.0f};
GLfloat  specref[] =  { 1.0f, 1.0f, 1.0f, 1.0f };

void DrawColor(int color)
{
    switch (color)
    {
        case 1:    glColor3ub(255, 0, 0);
            break;
        case 2: glColor3ub(0, 255, 0);
            break;
        case 3: glColor3ub(0, 0, 255);
            break;
        case 4: glColor3ub(255, 128, 0);
            break;
        case 5: glColor3ub(255, 255, 255);
            break;
        case 6: glColor3ub(255, 255, 0);
            break;
    }
}

void DrawCoordSystem(void)
{
    glBegin(GL_LINES);

        DrawColor(1); // Rot
        glVertex3f(0, 0, 0);
        glVertex3f(1.5, 0, 0);

        DrawColor(2); // Grün 
        glVertex3f(0, 0, 0);
        glVertex3f(0, 1.5, 0);

        DrawColor(3); // Blau
        glVertex3f(0, 0, 0);
        glVertex3f(0, 0, 1.5);

    glEnd();
}

// Cube neigen, sodass 3 Seiten sichtbar werden.
void DipCube()
{
    glRotatef(25, 1, 0, 0);
    glRotatef(65, 0, 1, 0);
}









//////////////////////////////////////////////



void DrawSurface1(void)
{
    glBegin(GL_QUADS);
        
        // Oben links.
        DrawColor(1);
        glNormal3f(0.0f, 0.0f, 1.0f);
        glVertex3f( -0.8f,  0.8f,  0.8f);
        glVertex3f( -0.3f,  0.8f,  0.8f);
        glVertex3f( -0.3f,  0.3f,  0.8f);
        glVertex3f( -0.8f,  0.3f,  0.8f);

        // Oben mitte.
        glNormal3f(0.0f, 0.0f, 1.0f);
        glVertex3f( -0.25f,  0.8f,  0.8f);
        glVertex3f(  0.25f,  0.8f,  0.8f);
        glVertex3f(  0.25f,  0.3f,  0.8f);
        glVertex3f( -0.25f,  0.3f,  0.8f);

        // Oben rechts.
        glNormal3f(0.0f, 0.0f, 1.0f);
        glVertex3f(  0.8f,  0.8f,  0.8f);
        glVertex3f(  0.3f,  0.8f,  0.8f);
        glVertex3f(  0.3f,  0.3f,  0.8f);
        glVertex3f(  0.8f,  0.3f,  0.8f);

        // Mitte links.
        glNormal3f(0.0f, 0.0f, 1.0f);
        glVertex3f( -0.8f,  0.25f,  0.8f);
        glVertex3f( -0.3f,  0.25f,  0.8f);
        glVertex3f( -0.3f, -0.25f,  0.8f);
        glVertex3f( -0.8f, -0.25f,  0.8f);

        // Mitte mitte.
        glNormal3f(0.0f, 0.0f, 1.0f);
        glVertex3f( -0.25f,  0.25f,  0.8f);
        glVertex3f(  0.25f,  0.25f,  0.8f);
        glVertex3f(  0.25f, -0.25f,  0.8f);
        glVertex3f( -0.25f, -0.25f,  0.8f);

        // Mitte rechts.
        glNormal3f(0.0f, 0.0f, 1.0f);
        glVertex3f(  0.8f,  0.25f,  0.8f);
        glVertex3f(  0.3f,  0.25f,  0.8f);
        glVertex3f(  0.3f, -0.25f,  0.8f);
        glVertex3f(  0.8f, -0.25f,  0.8f);

        // Unten links.
        glNormal3f(0.0f, 0.0f, 1.0f);
        glVertex3f( -0.8f, -0.3f,  0.8f);
        glVertex3f( -0.3f, -0.3f,  0.8f);
        glVertex3f( -0.3f, -0.8f,  0.8f);
        glVertex3f( -0.8f, -0.8f,  0.8f);

        // Unten mitte.
        glNormal3f(0.0f, 0.0f, 1.0f);
        glVertex3f( -0.25f, -0.3f,  0.8f);
        glVertex3f(  0.25f, -0.3f,  0.8f);
        glVertex3f(  0.25f, -0.8f,  0.8f);
        glVertex3f( -0.25f, -0.8f,  0.8f);

        // Unten rechts.
        glNormal3f(0.0f, 0.0f, 1.0f);
        glVertex3f(  0.8f, -0.3f,  0.8f);
        glVertex3f(  0.3f, -0.3f,  0.8f);
        glVertex3f(  0.3f, -0.8f,  0.8f);
        glVertex3f(  0.8f, -0.8f,  0.8f);

    glEnd();
}

void DrawSurface2(void)
{

}

void DrawSurface3(void)
{

}

void DrawSurface4(void)
{

}

void DrawSurface5(void)
{

}

void DrawSurface6(void)
{

}










void DrawCube(void)
{
    DrawSurface1();
    DrawSurface2();
    DrawSurface3();
    DrawSurface4();
    DrawSurface5();
    DrawSurface6();
}

// This function does any needed initialization on the rendering context.
void SetupRC()
{
    // Black background
    glClearColor(0.5f, 0.5f, 0.5f, 0.5f );

    // Enable Depth Testing
    glEnable(GL_DEPTH_TEST);

    // Enable lighting
    glEnable(GL_LIGHTING);

    // Setup and enable light 0
    glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
    glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
    glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
    glEnable(GL_LIGHT0);

    // Enable color tracking
    glEnable(GL_COLOR_MATERIAL);

    // Set Material properties to follow glColor values
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

    // All materials hereafter have full specular reflectivity
    // with a high shine
    glMaterialfv(GL_FRONT, GL_SPECULAR,specref);
    glMateriali(GL_FRONT,GL_SHININESS,128);
}

void ChangeSize(int w, int h)
{
    GLfloat  lightPos[] = { -50.f, 50.0f, 100.0f, 1.0f };
    GLfloat nRange = 1.9f;

    // Prevent a divide by zero
    if(h == 0)
        h = 1;

    // Set Viewport to window dimensions
    glViewport(0, 0, w, h);

    // Reset projection matrix stack
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // Establish clipping volume (left, right, bottom, top, near, far)
    if (w <= h)
        glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange, nRange);
    else
        glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange, nRange);

    // Reset Model view matrix stack
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
}

void Up(void)
{
    for (int i = xRotOld; i >= xRotNew; i--)
    {
        Sleep(5);

        // Clear the window
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Save matrix state and do the rotation
        glPushMatrix();

            DipCube();

                glRotatef(i, 0, 0, 1);

            glRotatef(yRotNew, 0, 1, 0);
            
            DrawCube();
            DrawCoordSystem();

        // Restore transformations
        glPopMatrix();

        // Flush drawing commands
        glutSwapBuffers();
    }

    xRotOld = xRotNew;
}

void Down(void)
{
    for (int i = xRotOld; i <= xRotNew; i++)
    {
        Sleep(5);

        // Clear the window
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Save matrix state and do the rotation
        glPushMatrix();

            DipCube();
                glRotatef(i, 0, 0, 1);
            glRotatef(yRotNew, 0, 1, 0);
            
            DrawCube();
            DrawCoordSystem();

        // Restore transformations
        glPopMatrix();

        // Flush drawing commands
        glutSwapBuffers();
    }

    xRotOld = xRotNew;
}

void Left(void)
{
    for (int i = yRotOld; i >= yRotNew; i--)
    {
        Sleep(5);

        // Clear the window
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Save matrix state and do the rotation
        glPushMatrix();

        DipCube();
        glRotatef(i, 0, 1, 0);
        glRotatef(xRotNew, 0, 0, 1);
        
        DrawCoordSystem();
        DrawCube();

        // Restore transformations
        glPopMatrix();

        // Flush drawing commands
        glutSwapBuffers();
    }

    yRotOld = yRotNew;
}

void Right(void)
{
    for (int i = yRotOld; i <= yRotNew; i++)
    {
        Sleep(5);

        // Clear the window
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Save matrix state and do the rotation
        glPushMatrix();
        
        DipCube();
        glRotatef(i, 0, 1, 0);
        glRotatef(xRotNew, 0, 0, 1);
        
        DrawCoordSystem();        
        DrawCube();

        // Restore transformations
        glPopMatrix();

        // Flush drawing commands
        glutSwapBuffers();
    }

    yRotOld = yRotNew;
}

void SpecialKeys(int key, int x, int y)
{
    if (key == GLUT_KEY_UP)
    {
        xRotNew -= 90;
        Up();
    }

    else if (key == GLUT_KEY_DOWN)
    {
        xRotNew += 90;
        Down();
    }

    else if (key == GLUT_KEY_LEFT)
    {
        yRotNew -= 90;
        Left();
    }

    else if (key == GLUT_KEY_RIGHT)
    {
        yRotNew += 90;
        Right();
    }
}

// Called to draw scene
void RenderScene(void)
{

}

void EnableAntialiasing(bool enable)
{
    if (enable)
    {
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);

        glEnable(GL_POINT_SMOOTH);
        glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
    
        glEnable(GL_LINE_SMOOTH);
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    
        glEnable(GL_POLYGON_SMOOTH);
        glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
    }

    else
    {
        glDisable(GL_BLEND);
        glDisable(GL_LINE_SMOOTH);
        glDisable(GL_POINT_SMOOTH);
        glDisable(GL_POLYGON_SMOOTH);
    }
}

int main(int argc, char* argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutCreateWindow("RubiksCubeGL by Florian Ulitzka & Timm Krause");
    
    glutReshapeFunc(ChangeSize);
    glutSpecialFunc(SpecialKeys);
    glutDisplayFunc(RenderScene);
    
    EnableAntialiasing(true);
    SetupRC();
    glutMainLoop();

    

    return 0;
}

I just compiled and ran your code. The basic problem is that you are trying to do object space rotations using glRotate commands. Maybe it can be done, but it would be awkward. An easier way is to use Multmatrix. I have a demo that does both object and screen space rotations. The source code is at -

http://www.mfwweb.com/OpenGL/Special_Rotations/

wow, i think you saved our lives. we have to get this done until sunday eve, it’s for a project at our university.

you pushed us in the right direction, i thought that we could do it without matrix multiplications/manipulations.

thank you very much!! i hope we could proceed with your example.

have a nice day.