[SOLVED] picking accurate in openGL

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
troopa
Posts: 28
Joined: Thu Mar 23, 2006 11:00 am
Location: Toulouse (France)
Contact:

[SOLVED] picking accurate in openGL

Post by troopa »

For my application, I need a picking which is pixel accurate, so i wrote one.
I take in count all the object whose id is geater than Zero.

But I have one problem when I have Gui node. Indeed it seems the gui drawing change many parameters. Is someone have an idea or an advice onto the code I wrote.

Code: Select all

void	C3DInteractions::Picking(	unsigned int		X, 
						unsigned int		Y, 
						unsigned int		largeur,
						unsigned int		hauteur,
						std::vector< int >&	selected )
{
	GLint viewport[4];
	GLuint selectBuf[BUFFER_PICKING_SIZE] ;
	GLdouble projection[16];
	GLdouble testProj[16] ; 

	for ( int i = 0 ; i < BUFFER_PICKING_SIZE; i++ )
		selectBuf[i] = 0 ;

	if ( largeur < 1 ) largeur = 1 ; 
	if ( hauteur < 1 ) hauteur = 1 ; 

	// we get the current projection matrix and the current wiewport.
	glGetDoublev(GL_PROJECTION_MATRIX, projection);
	glGetIntegerv(GL_VIEWPORT,viewport);

	// init picking
	glSelectBuffer(BUFFER_PICKING_SIZE,selectBuf);
	glInitNames();
	glRenderMode(GL_SELECT);

	// we change the matrix projection to put the same one multiplied
	// by the PickMatrix	
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();

	gluPickMatrix( ( GLdouble ) X, viewport[3] - ( GLdouble ) Y,
			( GLdouble ) largeur, ( GLdouble ) hauteur, viewport);

	glMultMatrixd(projection);

	// we set in modelview mode and we do the render 
	glMatrixMode(GL_MODELVIEW);
	RendreNoeud( m_pSmgr->getRootSceneNode() );

	we restore the old matrix
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glFlush();
	
	GLint hits = glRenderMode(GL_RENDER);

	if ( hits > 0 ){
		GLuint *ptr ;

		selected.clear();
		selected.resize(hits);
		ptr = (GLuint *) selectBuf;
		for ( int i = 0; i < hits; i++) 
		{  
			selected[i] = ptr[i*4+3] ; 
		}
	}
}

void	C3DInteractions::RendreNoeud( scene::ISceneNode * node )
{
	
	const core::list<scene::ISceneNode*>& children = node->getChildren();
	core::list<scene::ISceneNode*>::Iterator it = children.begin();

	for (; it != children.end(); ++it)
	{
		scene::ISceneNode* current = *it;

		if ( current->getID() > 0 ) {

			// we draw the name after giving it a name which is it's id.
			glPushName( ( GLuint ) current->getID() );

			// we set the material in EMT_SOLID temporarily.
			video::E_MATERIAL_TYPE material = current->getMaterial(0).MaterialType ; 
			current->setMaterialType(video::EMT_SOLID);

			current->OnPreRender(); 

			current->render(); 

			current->setMaterialType(material);

			current->OnPostRender(0);

			glPopName(); 

		}

		RendreNoeud( current );
		
	}
}
Last edited by troopa on Mon Jun 05, 2006 10:56 am, edited 1 time in total.
troopa
Posts: 28
Joined: Thu Mar 23, 2006 11:00 am
Location: Toulouse (France)
Contact:

Post by troopa »

up
troopa
Posts: 28
Joined: Thu Mar 23, 2006 11:00 am
Location: Toulouse (France)
Contact:

Post by troopa »

up !!

help me !!
troopa
Posts: 28
Joined: Thu Mar 23, 2006 11:00 am
Location: Toulouse (France)
Contact:

Post by troopa »

I solve my problem. I just have to put these lines at the top of the first method :

m_pDriver->beginScene(true, true, 0);
m_pSmgr->drawAll();


... and these lines at the end :

m_pGui->drawAll();
m_pDriver->endScene();

and It perfectly works !!!
Post Reply