PDA

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



tikra
10-12-2010, 08:08 AM
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.

tikra
10-12-2010, 08:55 AM
#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(&amp;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;
}

MaxH
10-12-2010, 01:03 PM
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/

tikra
10-13-2010, 06:04 AM
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.