Page 1 of 1

3D Picking and the Various Scene Managers

Posted: Tue Jan 11, 2005 12:42 pm
by Mdobele
I am attempting to do 3D picking of a Mesh Entity and have run into some problems.

First. Am I able to even use the RaySceneQuery method using the generic ST_GENERIC scene manager.

This is my picking method which was found from another forum post.

Code: Select all

// Start a new ray query 
	Ogre::Ray cameraRay = PrimedEngine::Instance().GetCamera()->getCameraToViewportRay( m_mouseX, m_mouseY ); 
	Ogre::RaySceneQuery *raySceneQuery = PrimedEngine::Instance().GetSceneManager()->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 ) 
		{ 
			closestObject = ( *rayIterator ).movable; 
			closestDistance = ( *rayIterator ).distance; 
		} 

	} 
	// No object clicked 
	if ( closestObject == NULL ) 
	{    
		PrimedEngine::Instance().GetRenderWindow()->setDebugText( "Nothing" );
	}
	else
	{ 
		Ogre::Entity *TestEntity = NULL;

		PrimedEngine::Instance().GetRenderWindow()->setDebugText( closestObject->getMovableType() );


		if(closestObject->getMovableType()=="Entity") 
		{ 
			TestEntity = (Entity *)closestObject; 
		}

	} 

	raySceneQuery->clearResults( ); 
	PrimedEngine::Instance().GetSceneManager( )->destroyQuery( raySceneQuery ); 
Problem is this ONLY ever returns a "SimpleRenderable" text no matter where i am looking.

When using ST_EXTERIOR_FAR or ST_EXTERIOR_REAL_FAR the picking method works and detects the entity but then I get a second problem where my CEGUI mouse pointer dissapers from the screen LOL.

I read that RaySceneQuery will only work with certain Scene Managers but Which Ones? I want to use the Generic one as it appears thats the best for the default Octree occlusion I want for all my meshes.

I am using 0.15.1 version of OGER. All i have in my scene is 1 ninja.mesh and thats it.

Posted: Tue Jan 11, 2005 2:01 pm
by Mdobele
Hmmm i feel like an Idiot :D

My ray was too close and I was picking up the Mouse Cursor. LOL
Its all good now. Thanks to Kojack for his help finding that out.

So for anyone interested I just ignore the close stuff.

Code: Select all

if ( ( *rayIterator ).distance < closestDistance && ( rayIterator ).distance > 0.1f )

Posted: Sat Jan 22, 2005 6:25 am
by McSwan
Hi,

Your code works fine - but I'm having issues with particle effects. It can select the particle effects, but it crashes on occassion when I click the mouse.

The reason I believe is that I'm deleting the particle effects. Or could it be onCreation of the effects?
I think aabb aren;t made until a scenemanager render?

I'm using ogre 15.0.

It crashes on an assert Here.

Code: Select all

inline const Vector3* getAllCorners(void) const
	    {
		    assert( !mNull && "Can't get corners of a null AAB" );
		    return (const Vector3*)mCorners;
	    }
I fairly sure I'm deleing my particle effects properly:

Code: Select all

// Creates a particle effect
// Todo - move to the init function.
bool ParticleEffect::Init(String aEffectName, String aIdentifier, Ogre::String aLuaClassName,
                          ObjectBase *aParent)
{
	 m_pSys = ParticleSystemManager::getSingleton().createSystem(
		aIdentifier, aEffectName);

   //Hack to fix a selection bug ?
  m_pSys->setQueryFlags(0);


  if (aParent == NULL)
  {
  	SetSceneNode(Application::Instance().GetSceneManager()->getRootSceneNode()->createChildSceneNode());
  }
  else
  {

    SetSceneNode(aParent->GetSceneNode()->createChildSceneNode());
  }
	GetSceneNode()->attachObject(m_pSys);

   return true;
}



// Called just before objects deletion
bool ParticleEffect::Done()
{

  // this isn;t necessary, but I'm paranoid - GetSceneNode()->detachAllObjects()
  // in objectbase::Done() removes it anyway
  GetSceneNode()->detachObject(m_pSys->getName()); 
 
  if (m_pSys)
  {

    ParticleSystemManager::getSingleton().destroySystem(m_pSys);
    m_pSys = NULL;
  }
   ObjectBase::Done();
  return true;
}


// Called just before objects deletion
bool ObjectBase::Done()
{

  // destroy the associated Action
  ActionManager::Instance().DestroyAction(GetClientObjectId());

  if(GetEntity())
  {
    Application::Instance().GetSceneManager()->removeEntity(GetEntity());
    SetEntity(NULL);
  }

  // TODO: fix Node deleteion
  // from Sinbad
  // If you actually want to destroy a node, the API only provides functions to do that
  // for a single node (SceneManager::destroySceneNode), or for all nodes in the scene 
  // (SceneManager::clearScene). If you use the former you have to make sure you 
  // remove the node from it's parent first. 
  if (GetSceneNode())
  {
    GetSceneNode()->detachAllObjects();
    GetSceneNode()->removeAllChildren();
    GetSceneNode()->getParent()->removeChild(GetSceneNode()->getName());
    Application::Instance().GetSceneManager()->destroySceneNode(GetSceneNode()->getName());
    SetSceneNode(NULL);
  }

}

Posted: Mon Jan 24, 2005 4:36 am
by McSwan
I've cludge fixed it for now. It's something about the effects not being properly dead when I pick them, maybe they kill themselves on the next update or something. I'll look into it soon.

Code: Select all

inline const Vector3* getAllCorners(void) const
	    {
        static const Vector3 dummy(0,0,0);
        if (mNull == true)
          return &dummy;
		      //assert( !mNull && "Can't get corners of a null AAB" );
		    return (const Vector3*)mCorners;
	    }

Posted: Mon Jan 24, 2005 2:14 pm
by sinbad
I believe this is fixed in 0.15.2 anyway.

Posted: Fri Feb 04, 2005 2:21 pm
by MadLion
Can someone confirm or maybe correct me, that RaySceneQuery doesn't work with TSM?
I'm not able to select meshes.

Posted: Fri Feb 04, 2005 4:53 pm
by Emmeran
it works fine for me.
about particle systems: i submitted a patch weeks ago, but i don't know if it has been aligned

Posted: Fri Feb 04, 2005 6:19 pm
by MadLion
Emmeran wrote:it works fine for me.
Do you use 0.15.2 or CVS?

Posted: Fri Feb 04, 2005 8:23 pm
by Emmeran
0.15.2 ... but it worked eralier too

Posted: Fri Feb 04, 2005 10:40 pm
by MadLion
I'm using the CVS and have the problem.

Maybe i did a mistake. I'm doing somethink like:

Code: Select all

Ogre::MovableObject *mCurrMO;
	    
	Ogre::Ray ray = mCamera->getCameraToViewportRay(e->getX(), e->getY());
	// Set up the ray query
	Ogre::RaySceneQuery *mRaySceneQuery2 = mSceneMgr->createRayQuery(ray);
	// Sort by distance, and say we're only interested in the first hit
	mRaySceneQuery2->setSortByDistance(true, 1);
	// Execute
	RaySceneQueryResult res = mRaySceneQuery2->execute();
	RaySceneQueryResult::iterator it = res.begin();
	if (it != res.end())
	{
		mCurrMO = it->movable;
		mWindow->setDebugText("mouse : " + mCurrMO->getName());
	}
	else
	{
		mWindow->setDebugText("mouse : x " + StringConverter::toString(e->getX()) + " y " + StringConverter::toString(e->getY()));
		mCurrMO = NULL;
	}
	mRaySceneQuery2->clearResults();

Posted: Sat Feb 05, 2005 1:13 am
by Emmeran
hm I don't see any mistake... I pick this way:

Code: Select all

	Object::ObjectType Listener::_pick3D(Real relX, Real relY)
	{
		Ray pickRay = System::getSingleton().mCamera->getCameraToViewportRay(relX, relY); 
		RaySceneQuery* query = System::getSingleton().mSceneMgr->createRayQuery(pickRay); 
		query->setQueryMask( Unit::MASK | Building::MASK );

		RaySceneQueryResult& result = query->execute(); 

		MovableObject *closestObject = NULL; 
		Real closestDistance = -1; 

		RaySceneQueryResult::iterator rayIterator; 
		mLastPicked = NULL;

		for ( rayIterator = result.begin( ); rayIterator != result.end( ); rayIterator++ ) 
		{
			if ( ( *rayIterator ).movable != NULL ) 
			{ 
				if ( ( *rayIterator ).distance < closestDistance || closestDistance < 0 ) 
				{ 
					closestObject   = ( *rayIterator ).movable; 
					closestDistance = ( *rayIterator ).distance; 
				}
			} 
		} 


		// No object clicked 
		if ( closestObject != NULL )   
			mLastPicked = (Object*)closestObject->getUserObject();

		else
			mLastPicked = NULL;

		query->clearResults( ); 
		System::getSingleton().mSceneMgr->destroyQuery( query ); 
		return (mLastPicked == NULL) ? Object::NOTHING : mLastPicked->getObjectType();
	}

what output do you get, if u try to pick?

Posted: Sat Feb 05, 2005 2:13 pm
by MadLion
I found my misstake, i didn't set the query flags/mask right.
Now it works fine. ^^

Thanks