Picking & Independant Rotation

Started by
8 comments, last by tiefighter101 17 years, 1 month ago
I'm having some trouble with picking an object then just having that object be rotated. Currently my code allows me to pick one object and have it rotate, but the other object no longer responses to being picked after putting in push and pop matrix commands. If I remove the pushMatrix and popMatrix commands I can click on either object, but they are both rotated. Any ideas on making the other object pickable again?

#include <stdio.h>
#include <stdlib.h>
#include <GLUT/glut.h>

   const GLint pickBuffSize = 32;
   
   GLfloat rotate;
   GLfloat rotate2;
   bool leftClick = false;
   bool rightClick = false;
   bool rotate30 = false;
   bool rotate20 = false;

   GLsizei winWidth = 400, winHeight = 400;


   void init (void)
   {
      glClearColor (0.0, 0.0, 0.0, 0.0);
	  glShadeModel(GL_SMOOTH);
	  glClearDepth(1.0f);
	  glEnable(GL_DEPTH_TEST);
	  glEnable(GL_CULL_FACE);
	  glDepthFunc(GL_LEQUAL);

   }
   
   void pyramid()
   {
	 
     glBegin(GL_TRIANGLES);
	    //initial front face
	   
		glColor3f(.79, .20, 0.10);
		glVertex3f(0.0, 6.0, 0.0);
		glVertex3f(-3.0, 0.0, 3.0);
		glVertex3f(3.0, 0.0, 3.0);
		
		//right side
		glColor3f(.30, .51, 0.20);
		glVertex3f(0.0, 6.0, 0.0);
		glVertex3f(3.0, 0.0, 3.0);
        glVertex3f(3.0, 0.0, -3.0);
		
		//back side
		glColor3f(0.0, 0.80, .68);
		glVertex3f(0.0, 6.0, 0.0);
		glVertex3f(3.0, 0.0, -3.0);
		glVertex3f(-3.0, 0.0, -3.0);
		
		//left side
		glColor3f(.50, 0.60, 0.10);
		glVertex3f(0.0, 6.0, 0.0);
		glVertex3f(-3.0, 0.0, -3.0);
		glVertex3f(-3.0, 0.0, 3.0);
		
	glEnd();

	}

   void draw (GLenum mode)
   {
   	  glClear (GL_COLOR_BUFFER_BIT |  GL_DEPTH_BUFFER_BIT);
	  
	  glPushMatrix();
	  glPushName (30);
      if(mode != GL_SELECT)
			glRotatef(rotate,0.0f,1.0f,0.0f);
	  pyramid();
	  glPopMatrix();
	 	  
	  glPushMatrix();

	  glPushName(20);
	  if(mode != GL_SELECT)
			glRotatef(rotate2,0.0f,1.0f,0.0f);
	  glTranslatef(8,0.0,0.0);
	  pyramid();
	
	  glPopMatrix();
	 
	 if(leftClick == true && rotate30 == true)
			rotate+=0.1f;
	 if(rightClick == true && rotate30 == true)
			rotate-=0.1f;
     if(leftClick == true && rotate20 == true)
			rotate2+=0.1f;
	 if(rightClick == true && rotate20 == true)
			rotate2-=0.1f;
	
	}

   /*  Print the contents of the pick buffer for each mouse selection.  */
   void processPicks (GLint nPicks, GLuint pickBuffer [ ], int button)
   {
      GLint j, k;
      GLuint objID, *ptr;

      printf (" Number of objects picked = %d\n", nPicks);
      printf ("\n");
      ptr = pickBuffer;

      /*  Output all items in each pick record.  */
      for (j = 0; j < nPicks; j++) {
         objID = *ptr;

         printf ("   Stack position = %d\n", objID);
         ptr++;

         printf ("   Min depth = %g,", float (*ptr/0x7fffffff));
         ptr++;

         printf ("   Max = %g\n", float (*ptr/0x7fffffff));
         ptr++;

         printf ("   Stack IDs are: \n");
         for (k = 0; k < objID; k++) {
            printf ("   %d ",*ptr);
			if(*ptr == 30)
			{	
				if(leftClick == false && button == GLUT_LEFT_BUTTON)
				{
					leftClick = true;
					rotate30 = true;
				}
				else if(leftClick == true && button == GLUT_LEFT_BUTTON)
				{
					leftClick = false;
					rotate30 = false;
				}
				if(rightClick == false && button == GLUT_RIGHT_BUTTON)
				{
					rightClick = true;
					rotate30 = true;
				}
				else if(rightClick == true && button == GLUT_RIGHT_BUTTON)
				{
					rightClick = false;
					rotate30 = false;
				}
			}
			
            ptr++;
         }
         printf ("\n\n");
      }
   }

   void pickPyramids (int button, int action, int xMouse, int yMouse)
   {
      GLuint pickBuffer [pickBuffSize];
      GLint nPicks, vpArray [4];

      if (action != GLUT_DOWN) //removed this code: button != GLUT_LEFT_BUTTON || 
         return;

      glSelectBuffer (pickBuffSize, pickBuffer);  //  Designate pick buffer.
      glRenderMode (GL_SELECT);             //  Activate picking operations.
      glInitNames ( );                   //  Initialize the object-ID stack.

      /*  Save current viewing matrix.  */
      glMatrixMode (GL_PROJECTION);
      glPushMatrix ( );
      glLoadIdentity ( );

      glGetIntegerv (GL_VIEWPORT, vpArray);
      gluPickMatrix (GLdouble (xMouse), GLdouble (vpArray [3] - yMouse),
                        5.0, 5.0, vpArray);

      gluPerspective(45.0f, 1.0f, 1.0f, 100.0f);	
      draw (GL_SELECT);       // Process

      /*  Restore original viewing matrix.  */
      glMatrixMode (GL_PROJECTION);
      glPopMatrix ( );
	  glLoadIdentity();
	  gluPerspective(45.0f, 1.0f, 1.0f, 100.0f);	
      glMatrixMode (GL_MODELVIEW);

	  glutSwapBuffers();
	  
      nPicks = glRenderMode (GL_RENDER);

      processPicks (nPicks, pickBuffer, button);  // Process picked objects.

      glutPostRedisplay ( );
   }

   void displayFcn (void)
   {
	  glLoadIdentity();
	  gluLookAt(5,10,-30,0,0,0,0,1,0);
      
      draw (GL_RENDER);      
   
	  glutSwapBuffers();	
   }

   void winReshapeFcn (int newWidth, int newHeight)
   {
      /*  Reset viewport and projection parameters.  */
      glViewport (0, 0, newWidth, newHeight);
      glMatrixMode (GL_PROJECTION);
      glLoadIdentity ( );

      gluPerspective(45.0f, 1.0f, 1.0f, 100.0f);	
      glMatrixMode (GL_MODELVIEW);

      /* Reset display-window size parameters.  */
      winWidth  = newWidth;
      winHeight = newHeight;
   }

   int main (int argc, char** argv)
   {
      glutInit (&argc, argv);
      glutInitDisplayMode (GLUT_DEPTH | GLUT_SINGLE | GLUT_RGB);
      glutInitWindowPosition (100, 100);
      glutInitWindowSize (winWidth, winHeight);
      glutCreateWindow ("Picking Demo");
	  
      glutDisplayFunc (displayFcn);
	  glutIdleFunc(displayFcn);
      glutReshapeFunc (winReshapeFcn);
      glutMouseFunc (pickPyramids);
	  init ( );

      glutMainLoop ( );
}

Advertisement
Rather than have us try reading code.
Why dont you tell us, on a conceptual level, exactly what you are doing, and why it doesnt work.
Conceptual- that is, dont tell us, 'but if i remove this line... then'; actually say what the line does in terms of the program flow


I'd bet that the process of putting that into words, will probably end up conceptualizing the whole thing for you and ending up self-solving...
Anyhow

It sounds to me like you took some glpicking tutorial, which contains a single object that you can rotate
and are trying to add a second object

and your problem most likely stems from adding a second object, but not adding the associated transforms (glrotate, etc) to let it move independantly from the first one

additionally, the picking id stuff is probably intertwined in a similar manner
(since picking is usually done as a second rendering pass)

so your approach should be, identify the picking id related functions and duplicate for object2
identify the meaning of each transform (this includes the popmatrix stuff) and reorganize them to handle two objects (generally a set of push/pop for each separate object)

this will involve figuring out what each part of the tutorial actually means
hmmh, Actually

now that I look at the code, the render stuff seems ok

I think you just need to fix the logic that decides which object is currently picked. your processPicks function has a branch to check for id30, but not 20
so... that probably causes issue with trying to select the one who is 20...
Sorry, the code that processed a pick for object was originally there. That bit of code must've been deleted when trying to get the program to work correctly.

Thanks for your help so far. I'm pushing and popping for each object and the picking is set up to recognize the picking of either object. When I'm pushing and popping matrices for objects I can't get any hit recognition on the second object (the object named 20), but if I remove those pushes and pops surrounding the objects I can recognize the hits on either object, but then they both rotate together.

Here is the updated code:

#include <stdio.h>#include <stdlib.h>#include <GLUT/glut.h>   const GLint pickBuffSize = 32;      GLfloat rotate;   GLfloat rotate2;   bool leftClick = false;   bool rightClick = false;   bool rotate30 = false;   bool rotate20 = false;   GLsizei winWidth = 400, winHeight = 400;   void init (void)   {      glClearColor (0.0, 0.0, 0.0, 0.0);	  glShadeModel(GL_SMOOTH);	  glClearDepth(1.0f);	  glEnable(GL_DEPTH_TEST);	  glEnable(GL_CULL_FACE);	  glDepthFunc(GL_LEQUAL);   }      void pyramid()   {	      glBegin(GL_TRIANGLES);	    //initial front face	   		glColor3f(.79, .20, 0.10);		glVertex3f(0.0, 6.0, 0.0);		glVertex3f(-3.0, 0.0, 3.0);		glVertex3f(3.0, 0.0, 3.0);				//right side		glColor3f(.30, .51, 0.20);		glVertex3f(0.0, 6.0, 0.0);		glVertex3f(3.0, 0.0, 3.0);        glVertex3f(3.0, 0.0, -3.0);				//back side		glColor3f(0.0, 0.80, .68);		glVertex3f(0.0, 6.0, 0.0);		glVertex3f(3.0, 0.0, -3.0);		glVertex3f(-3.0, 0.0, -3.0);				//left side		glColor3f(.50, 0.60, 0.10);		glVertex3f(0.0, 6.0, 0.0);		glVertex3f(-3.0, 0.0, -3.0);		glVertex3f(-3.0, 0.0, 3.0);			glEnd();	}   void draw (GLenum mode)   {   	  glClear (GL_COLOR_BUFFER_BIT |  GL_DEPTH_BUFFER_BIT);	  	  glPushMatrix();	  glPushName (30);      if(mode != GL_SELECT)			glRotatef(rotate,0.0f,1.0f,0.0f);	  pyramid();	  glPopMatrix();	 	  	  glPushMatrix();	  glPushName(20);	  if(mode != GL_SELECT)			glRotatef(rotate2,0.0f,1.0f,0.0f);	  glTranslatef(8,0.0,0.0);	  pyramid();		  glPopMatrix();	 	 if(leftClick == true && rotate30 == true)			rotate+=0.1f;	 if(rightClick == true && rotate30 == true)			rotate-=0.1f;     if(leftClick == true && rotate20 == true)			rotate2+=0.1f;	 if(rightClick == true && rotate20 == true)			rotate2-=0.1f;		}   /*  Print the contents of the pick buffer for each mouse selection.  */   void processPicks (GLint nPicks, GLuint pickBuffer [ ], int button)   {      GLint j, k;      GLuint objID, *ptr;      printf (" Number of objects picked = %d\n", nPicks);      printf ("\n");      ptr = pickBuffer;      /*  Output all items in each pick record.  */      for (j = 0; j < nPicks; j++) {         objID = *ptr;         printf ("   Stack position = %d\n", objID);         ptr++;         printf ("   Min depth = %g,", float (*ptr/0x7fffffff));         ptr++;         printf ("   Max = %g\n", float (*ptr/0x7fffffff));         ptr++;         printf ("   Stack IDs are: \n");         for (k = 0; k < objID; k++) {            printf ("   %d ",*ptr);			if(*ptr == 20)			{					if(leftClick == false && button == GLUT_LEFT_BUTTON)				{					leftClick = true;					rotate20 = true;				}				else if(leftClick == true && button == GLUT_LEFT_BUTTON)				{					leftClick = false;					rotate20 = false;				}				if(rightClick == false && button == GLUT_RIGHT_BUTTON)				{					rightClick = true;					rotate20 = true;				}				else if(rightClick == true && button == GLUT_RIGHT_BUTTON)				{					rightClick = false;					rotate20 = false;				}			}			if(*ptr == 30)			{					if(leftClick == false && button == GLUT_LEFT_BUTTON)				{					leftClick = true;					rotate30 = true;				}				else if(leftClick == true && button == GLUT_LEFT_BUTTON)				{					leftClick = false;					rotate30 = false;				}				if(rightClick == false && button == GLUT_RIGHT_BUTTON)				{					rightClick = true;					rotate30 = true;				}				else if(rightClick == true && button == GLUT_RIGHT_BUTTON)				{					rightClick = false;					rotate30 = false;				}			}			            ptr++;         }         printf ("\n\n");      }   }   void pickPyramids (int button, int action, int xMouse, int yMouse)   {      GLuint pickBuffer [pickBuffSize];      GLint nPicks, vpArray [4];      if (action != GLUT_DOWN) //removed this code: button != GLUT_LEFT_BUTTON ||          return;      glSelectBuffer (pickBuffSize, pickBuffer);  //  Designate pick buffer.      glRenderMode (GL_SELECT);             //  Activate picking operations.      glInitNames ( );                   //  Initialize the object-ID stack.      /*  Save current viewing matrix.  */      glMatrixMode (GL_PROJECTION);      glPushMatrix ( );      glLoadIdentity ( );      glGetIntegerv (GL_VIEWPORT, vpArray);      gluPickMatrix (GLdouble (xMouse), GLdouble (vpArray [3] - yMouse),                        5.0, 5.0, vpArray);      gluPerspective(45.0f, 1.0f, 1.0f, 100.0f);	      draw (GL_SELECT);       // Process      /*  Restore original viewing matrix.  */      glMatrixMode (GL_PROJECTION);      glPopMatrix ( );	  glLoadIdentity();	  gluPerspective(45.0f, 1.0f, 1.0f, 100.0f);	      glMatrixMode (GL_MODELVIEW);	  glutSwapBuffers();	        nPicks = glRenderMode (GL_RENDER);      processPicks (nPicks, pickBuffer, button);  // Process picked objects.      glutPostRedisplay ( );   }   void displayFcn (void)   {	  glLoadIdentity();	  gluLookAt(5,10,-30,0,0,0,0,1,0);            draw (GL_RENDER);         	  glutSwapBuffers();	   }   void winReshapeFcn (int newWidth, int newHeight)   {      /*  Reset viewport and projection parameters.  */      glViewport (0, 0, newWidth, newHeight);      glMatrixMode (GL_PROJECTION);      glLoadIdentity ( );      gluPerspective(45.0f, 1.0f, 1.0f, 100.0f);	      glMatrixMode (GL_MODELVIEW);      /* Reset display-window size parameters.  */      winWidth  = newWidth;      winHeight = newHeight;   }   int main (int argc, char** argv)   {      glutInit (&argc, argv);      glutInitDisplayMode (GLUT_DEPTH | GLUT_SINGLE | GLUT_RGB);      glutInitWindowPosition (100, 100);      glutInitWindowSize (winWidth, winHeight);      glutCreateWindow ("Pyramids!");	        glutDisplayFunc (displayFcn);	  glutIdleFunc(displayFcn);      glutReshapeFunc (winReshapeFcn);      glutMouseFunc (pickPyramids);	  init ( );      glutMainLoop ( );}
did you remember to set rotate30 to false when rotate20 is true
and vice versa?
looks like with your pick evaluation, each one only consider's itself for activation, but I dont see where you ever UnSet them...
I don't understand what you mean when you say unset them.
the variables rotate20 and rotate30 are global
this means they 'remember' their values from the previous update
make sure to reset them, or their past values might be messing up the new user inputs
They should be getting reset. The thing is that the second pyramid isn't being displayed as being in the Select buffer when I start pushing and popping matrices between objects.

This topic is closed to new replies.

Advertisement