Problem with MFC and 3D picking

Problems building or running the engine, queries about how to use features etc.
Post Reply
User avatar
stoneCold
OGRE Expert User
OGRE Expert User
Posts: 867
Joined: Fri Oct 01, 2004 9:13 pm
Location: Carinthia, Austria
x 1

Problem with MFC and 3D picking

Post 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
User avatar
stoneCold
OGRE Expert User
OGRE Expert User
Posts: 867
Joined: Fri Oct 01, 2004 9:13 pm
Location: Carinthia, Austria
x 1

Post by stoneCold »

No one out there who can help me?
:cry: :cry: :cry:
User avatar
monster
OGRE Community Helper
OGRE Community Helper
Posts: 1098
Joined: Mon Sep 22, 2003 2:40 am
Location: Melbourne, Australia
Contact:

Post 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.
User avatar
Clay
OGRE Community Helper
OGRE Community Helper
Posts: 518
Joined: Wed Mar 17, 2004 4:14 am
x 1
Contact:

Post 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.
User avatar
stoneCold
OGRE Expert User
OGRE Expert User
Posts: 867
Joined: Fri Oct 01, 2004 9:13 pm
Location: Carinthia, Austria
x 1

Post 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
Post Reply