Page 1 of 1

Problem with MFC and 3D picking

Posted: Sun Feb 13, 2005 4:29 pm
by stoneCold
I've got Ogre to render in a MFC picture control and now I want to do 3D picking in the Ogre view, but there is an very confusing problem. The picking ray of my viewport doesn't come out straight in front of the viewport, it comes out of the right side of the viewport (I assume at 90 degrees). The result is, that if an object is on the right side of the camera/viewport, my "picking" method will return "TRUE".
Here is the picking method (mouse coordinates [int x, int y] are global screen coordinates):

Code: Select all

bool COgreFramework::picking(int x, int y, String &ausgabe)
{
	// Start a new ray query 
	Ogre::Ray cameraRay = mCamera->getCameraToViewportRay( x, y); 
	Ogre::RaySceneQuery *raySceneQuery = mSceneMgr->createRayQuery( cameraRay ); 
	raySceneQuery->execute( ); 
	Ogre::RaySceneQueryResult result = raySceneQuery->getLastResults( ); 

	Ogre::MovableObject *closestObject = NULL; 
	float closestDistance = LONG_MAX; //used to be real 
	
	std::list< Ogre::RaySceneQueryResultEntry >::iterator rayIterator; 

   for ( rayIterator = result.begin( ); rayIterator != result.end( ); rayIterator++ ) 
   { 
      if ( ( *rayIterator ).distance < closestDistance && ( *rayIterator ).distance > 0.1f ) 
      {
		  closestObject = ( *rayIterator ).movable; 
		  closestDistance = ( *rayIterator ).distance; 
      } 
   }

   bool intersects;
   // No object clicked 
   if ( closestObject == NULL ) 
   {
	   intersects = false;
   } 
   else 
   {
	   Ogre::Entity *TestEntity = NULL; 
	   ausgabe = closestObject->getMovableType() + closestObject->getName();

	   if(closestObject->getMovableType()=="Entity") 
	   { 
		   intersects = true;
		   TestEntity = (Entity *)closestObject; 
      }
   }
   raySceneQuery->clearResults( ); 
   mSceneMgr->destroyQuery( raySceneQuery );

   return intersects;
}
Somebody an idea what's going wrong, please help.

Thx, stoneCold

Posted: Mon Feb 14, 2005 2:43 am
by stoneCold
No one out there who can help me?
:cry: :cry: :cry:

Posted: Mon Feb 14, 2005 2:53 am
by monster
I haven't looked at the code in detail, but from the docs for getCameraToViewportRay the parameters should be;
The x and y position at which the ray should intersect the viewport, in normalised screen coordinates [0,1]
i.e. if you want the middle of the screen you need to use (0.5,0.5), so you'll have to convert your global screen coordinates accordingly.

Posted: Mon Feb 14, 2005 5:23 am
by Clay
Ok, several things wrong with the code, but I don't think they are your problem. Lets fix them first:

Code: Select all

   for ( rayIterator = result.begin( ); rayIterator != result.end( ); rayIterator++ )
   {
      if ( ( *rayIterator ).distance < closestDistance && ( *rayIterator ).distance > 0.1f )
      {
        closestObject = ( *rayIterator ).movable;
        closestDistance = ( *rayIterator ).distance;
      }
   } 
This code does not check to see if *rayIterator is a movable object. You could be colliding with world fragments with this code. You should do this:

Code: Select all

   for ( rayIterator = result.begin( ); rayIterator != result.end( ); rayIterator++ )
   {
      if ( (*rayIterator).movable && ( *rayIterator ).distance < closestDistance && ( *rayIterator ).distance > 0.1f )
      {
        closestObject = ( *rayIterator ).movable;
        closestDistance = ( *rayIterator ).distance;
      }
   } 
Second, this code here:

Code: Select all

      if(closestObject->getMovableType()=="Entity")
      {
         intersects = true;
         TestEntity = (Entity *)closestObject;
      } 
You should not be using C style casts for C++ objects. What you want is to use static_cast if you have to do this:

Code: Select all

      if(closestObject->getMovableType()=="Entity")
      {
         intersects = true;
         TestEntity = static_cast<Entity *>(closestObject);
      } 
But you should only be doing this if you absolutely need an entity and not a MovableObject. (Even still I'd suggest you might be able to refactor the code to not need a cast there, but that's beyond this post.)

---

As far as your original problem, chances are the problem is with your x and y coordinates. They need to be normalized (between 0.0f and 1.0f) before passing them into getCameraToViewportRay. Put some debugging hooks in there to see if you can figure out what exactly you are passing in as x and y.

Posted: Mon Feb 14, 2005 12:46 pm
by stoneCold
Great, my code works very well now. Thanks monster.
I haven't looked at the code in detail, but from the docs for getCameraToViewportRay the parameters should be;
Quote:
The x and y position at which the ray should intersect the viewport, in normalised screen coordinates [0,1]

i.e. if you want the middle of the screen you need to use (0.5,0.5), so you'll have to convert your global screen coordinates accordingly.
I found so many threads in the forums and everbody did the same thing wrong, therefore I thought I did everything right :? :lol: .

Thx,
stoneCold