Ankomm
Ankomm

Reputation: 563

Glut object's moving without telling

I'm working with Glut and C, my purpose is to screen a 3D Lego and two Kaplas with dynamic width, height and depth. There's a few keyboard listeners that move the camera, and rotate the Kaplas.

My problem is: when I press any touch of the keyboard or the mouse (which are not dealt with in my code) my Lego get its X and Z positions greatly increased!

Here's my code and details:

int main(int argc, char **argv) {

   // init GLUT and create Window
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
   glutInitWindowPosition(100,100);
   glutInitWindowSize(800,800);
   glutCreateWindow("Lighthouse3D- GLUT Tutorial");

   glClearColor(0.5f, 0.5f, 0.5f, 0.5f);

   glutDisplayFunc(renderScene); //my display function
   glutReshapeFunc(resize); //my reshape function

   glutKeyboardFunc(key); //basic keyboard listener function
   glutSpecialFunc(specialKey); //special keyboard listener function

   glEnable(GL_DEPTH_TEST);

   glEnable(GL_NORMALIZE);
   glEnable(GL_COLOR_MATERIAL);
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);

   glLightiv(GL_LIGHT0, GL_POSITION, light_position);

   glutMainLoop();

   return 1;
}

The code below is my reshape function:

static void resize(int width, int height) {
   if(height == 0)
       height = 1;

   const float ar = (float) width / (float) height;

   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glViewport(0, 0, width, height);
   gluPerspective(90, ar, 1, 10000);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}

Next functions are creating a Kapla and a Lego:

void setKapla() {

   glColor3f(0.76f, 0.42f, 0.0f);

   float rX = xRot; //moved by keyboard's 'x' key
   float rY = yRot; //moved by keyboard's 'y' key
   float rZ = zRot; //moved by keyboard's 'z' key

   float pX = xPos; //not dynamic, equal to 0.0f
   float pY = yPos; //not dynamic, equal to 0.0f
   float pZ = zPos; //not dynamic, equal to -30.0f

   glPushMatrix();
       glTranslatef(pX, pY, pZ); //place origin point to static coords
       glRotatef(angleRot, rX, rY, rZ); //rotate the object following 
                                        //dynamic coords
       glScalef(1.0f, 3.0f, 15.0f); //multiplying the following cube by this 
                                    //proportions
       glutSolidCube(2.0f); //base cube
   glPopMatrix();
}

Now the Lego:

void setLego(int zHeight) {

   GLUquadricObj* quadric = gluNewQuadric(); //creatin my quadric object

   gluQuadricDrawStyle(quadric, GLU_FILL); 

   glColor3f(0.72f, 0.72f, 0.05f);

   glPushMatrix();

       glTranslatef(posLegoX, posLegoY, posLegoZ); //setting lego
                                                   //position to 
                                                   //dynamic coords, set 
                                                   //in the function in the 
                                                   //next bloc of code
       glRotatef(-90, 1, 0, 0); //rotation for the next cylinder
       gluCylinder(quadric, 2.4, 2.4, 1.7, 10, 10); //cylinder in the top of 
                                                    //the cube
       gluDisk(quadric, 0.0, 2.4, 10, 10); //closing the bottom of the 
                                           //cylinder
       glTranslatef(0.0f, 0.0f, 1.7f); //translated to the top of the 
                                       //cylinder
       gluDisk(quadric, 0.0, 2.4, 10, 10); //closing the top of the cylinder

       glTranslatef(0.0f, 0.0f, ((-3.2f * zHeight) / 2.0f) - 1.7f); 
       //setting Lego's basic cube position
       glScalef(7.8f, 7.8f, 3.2f * zHeight); //setting Lego's basic cube 
                                             //size to the function param
       glutSolidCube(1.0f); //creating the cube

   glPopMatrix();

   gluDeleteQuadric(quadric);
}

Instead of the Kapla, the lego is not immediately created in the display function, before that the following function is called to multiply basic Lego's to make a complete Lego (following params):

void addLego(int depth, int height, int width) {

   int i = 0;
   int j = 0;

   for(i=0 ; i<depth ; i++) { //multiply basic Lego to get the right depth

       posLegoX += 7.8f; //incrementing global variable which change the 
                         //basic position of the current Lego in the above 
                         //function
       setLego(height); //creating the current basic Lego
   }

   for(j=0 ; j<width ; j++) { //multiply basic Lego to get the right depth

       posLegoZ -= 7.8; //decrementing global variable which change the 
                        //basic position of the current Lego in the above 
                        //function
       setLego(height); //creating the current basic Lego
   }
}

And finally my display function:

void renderScene(void) {

   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   printf("   xCam : %f | yCam : %f\n", xCam, yCam);

   glPushMatrix();
       gluLookAt(xCam, yCam, zCam,
                 xCenter, yCenter, zCenter,
                 xVec, yVec, zVec); //move the camera with keyboard's arrow 
                                    //touches

       xPos = -10.0f; //x position of the first Kapla
       yPos = -10.0f; //y position of the first Kapla
       setKapla(); //set the first Kapla

       xPos = 10.0f; //x position of the second Kapla
       yPos = 10.0f; //y position of the second Kapla
       setKapla(); //set the second Kapla

       addLego(2, 5, 3); //creating a complete Lego with 2 basic Legos in 
                         //depth, 5 Legos in height and 3 Legos in width

   glPopMatrix();

   glutSwapBuffers();
}

My basic and special keyboard functions are only using the keys : q, a, z, x, y, space, +, -, GLUT_KEY_LEFT, GLUT_KEY_RIGHT, GLUT_KEY_UP, GLUT_KEY_DOWN.

When I pressed ANY key of my mouse or my keyboard, posLegoX and posLegoZ are each incrementing and decrementing following the code in the addLego() function, but there's no event in my code which controls it.

The result is my complete Lego run away from the camera when I press any key, but NOT the Kapla!

IMPORTANT! I made a lot of tests, and the problem is located in my addLego() function, i tried to put in it glPushMatrix() and glPopMatrix() in different lines, tried also to put a glFlush() and a glLoadIdentity() but nothing worked...

How can I stop this?

Upvotes: 0

Views: 76

Answers (1)

Jason Aller
Jason Aller

Reputation: 3652

This is the solution posted by Ankomm in an edit to their question:

I found the problem with one of my teachers. The functions which are listening for Keyboard and Mouse events are listening ALL keys and buttons even they're not set in the functions, and refresh with the redisplay (which call the display function [here : renderscene()]). The renderscene() calls the function which increments and decrements global variables which have been set when the program was compiled. The solution is to set the variables values at the beginning of the function like this:


void addLego(int depth, int height, int width) {

   posLegoX = 0.0f; 
   posLegoZ = -50.0f;//set the values here so when the function will be 
                    //called, the position of the first Lego will be always 
                    //the same

   int i = 0;
   int j = 0;

   for(i=0 ; i<depth ; i++) { //multiply basic Lego to get the right depth

       posLegoX += 7.8f; //incrementing global variable which changes the 
                         //basic position of the current Lego in the above 
                         //function
       setLego(height); //creating the current basic Lego
   }

    for(j=0 ; j<width ; j++) { //multiply basic Lego to get the right depth

       posLegoZ -= 7.8; //decrementing global variable which change the 
                         //basic position of the current Lego in the above 
                        //function
        setLego(height); //creating the current basic Lego
    }
}

And it works!

Upvotes: 1

Related Questions