Getting Collision Node/Triangle/Position from a mouse click

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
bigbman
Posts: 23
Joined: Thu Nov 04, 2010 6:35 am

Getting Collision Node/Triangle/Position from a mouse click

Post by bigbman »

I've found a number of posts on the Irrlicht forum on how to do this (i.e. http://irrlicht.sourceforge.net/phpBB2/ ... intfromray), but it doesn't seem to be working correctly.

Here's my signal handler for a click:

Code: Select all

	// convert to Irrlicht friendly struct
	irr::core::position2di mousePos(v2fPos.x, v2fPos.y);

	// get our scene manager
	scene::ISceneManager* pSceneMgr = GetIrrlichtManager()->GetScene();
	scene::ISceneCollisionManager* pCollMgr = pSceneMgr->getSceneCollisionManager();

	// get the ray from the screen point
    irr::core::line3df collRay;

	collRay = pCollMgr->getRayFromScreenCoordinates(mousePos, pSceneMgr->getActiveCamera()); // this appears to be getting unique values
	
	// get the collision 
	core::vector3df collPoint; 
	core::triangle3df collTriangle; 
	scene::ISceneNode* pNode = 0; 
	
	pNode = pCollMgr->getSceneNodeAndCollisionPointFromRay(collRay, collPoint, collTriangle); // I'm always getting null here

	if( pNode )
		LogMsg("	Selected Node: %s", pNode->getName());
	else
	{
		pNode = pCollMgr->getSceneNodeFromScreenCoordinatesBB(mousePos,0,true);	// but this is returning a node... wtf
		if( pNode )
			LogMsg("	Selected Node: %s", pNode->getName());
	}

	LogMsg("	Selected Point: %f, %f, %f", collPoint.X, collPoint.Y, collPoint.Z);
[/code]
Mag-got
Posts: 42
Joined: Tue Dec 04, 2007 5:53 pm

Post by Mag-got »

Check the ray's length
bigbman
Posts: 23
Joined: Thu Nov 04, 2010 6:35 am

Post by bigbman »

Got Ray of length: 10187.501953
Start Point: 1775.391357, 221.420609, 1066.849121
End Point: 394.590485, 1102.506836, 11121.811523
Derr, it's hitting my Camera node. I have an FPS camera set up with collision to the ground. How can I avoid this? I'm using the collision example picking only nodes marked for selection.

Here's updated click code:

Code: Select all

	// convert to Irrlicht friendly struct
	irr::core::position2di mousePos(v2fPos.x, v2fPos.y);

	// get our scene manager
	scene::ISceneManager* pSceneMgr = GetIrrlichtManager()->GetScene();
	scene::ISceneCollisionManager* pCollMgr = pSceneMgr->getSceneCollisionManager();

	// get the ray from the screen point
    irr::core::line3df collRay;

	collRay = pCollMgr->getRayFromScreenCoordinates(mousePos, pSceneMgr->getActiveCamera()); // this appears to be getting unique values

	LogMsg("	Got Ray of length: %f", collRay.getLength());
	LogMsg("		Start Point: %f, %f, %f", collRay.start.X, collRay.start.Y, collRay.start.Z);
	LogMsg("		End Point: %f, %f, %f", collRay.end.X, collRay.end.Y, collRay.end.Z);

	// get the collision 
	core::vector3df collPoint; 
	core::triangle3df collTriangle; 
	scene::ISceneNode* pNode = 0; 
	
	pNode = pCollMgr->getSceneNodeAndCollisionPointFromRay(collRay, collPoint, collTriangle, IDFlag_IsPickable); // I'm always getting null here

	if( !pNode )
	{
		pNode = pCollMgr->getSceneNodeFromScreenCoordinatesBB(mousePos,0,true);	// but this is returning a node... wtf
	}

	// Unlight any currently highlighted scene node
    if (m_pHilighted)
    {
            m_pHilighted->setMaterialFlag(video::EMF_LIGHTING, true);
            m_pHilighted = 0;
    }

	if( pNode )
	{
		LogMsg("	Selected Node: %s", pNode->getName());
		LogMsg("	Selected Point: %f, %f, %f", collPoint.X, collPoint.Y, collPoint.Z);

		if((pNode->getID() & IDFlag_IsHighlightable) == IDFlag_IsHighlightable)
        {
                m_pHilighted = pNode;

                // Highlighting in this case means turning lighting OFF for this node,
                // which means that it will be drawn with full brightness.
                m_pHilighted->setMaterialFlag(video::EMF_LIGHTING, false);
        }
}
Here's the setup code:

Code: Select all

	if (!GetIrrlichtManager()->GetDevice())
	{
		LogError("Error initializing Irrlicht");
		return;
	}
	
	IrrlichtDevice * device = GetIrrlichtManager()->GetDevice();
	video::IVideoDriver* driver = GetIrrlichtManager()->GetDriver();
	scene::ISceneManager* smgr = GetIrrlichtManager()->GetScene();
	
	device->getTimer()->setTime(0);
	
	// load the .irr scene
	std::string strBasePath = GetBaseAppPath();
	device->getFileSystem()->changeWorkingDirectoryTo( (strBasePath).c_str());
	smgr->loadScene((strBasePath+"game/scenes/jmvd1/jmvd1.irr").c_str());
	
	scene::ICameraSceneNode * camera;
	
	// Create a meta triangle selector to hold several triangle selectors.
	scene::IMetaTriangleSelector * meta = smgr->createMetaTriangleSelector();
	
	core::array<scene::ISceneNode *> nodes;
	smgr->getSceneNodesFromType(scene::ESNT_ANY, nodes); // Find all nodes
	
	for (u32 i=0; i < nodes.size(); ++i)
	{
		scene::ISceneNode * node = nodes[i];
		scene::ITriangleSelector * selector = 0;
		
		node->getID();
		
		switch(node->getType())
		{
			case scene::ESNT_CUBE:
			case scene::ESNT_ANIMATED_MESH:
				// Because the selector won't animate with the mesh,
				// and is only being used for camera collision, we'll just use an approximate
				// bounding box instead of ((scene::IAnimatedMeshSceneNode*)node)->getMesh(0)
				node->setID(IDFlag_IsPickable | IDFlag_IsHighlightable);
				selector = smgr->createTriangleSelectorFromBoundingBox(node);
                break;
				
			case scene::ESNT_MESH:
			case scene::ESNT_SPHERE: // Derived from IMeshSceneNode
				node->setID(IDFlag_IsPickable | IDFlag_IsHighlightable);
				selector = smgr->createTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node);
				break;
				
			case scene::ESNT_TERRAIN:
				node->setID(IDFlag_IsPickable | IDFlag_IsHighlightable);
				selector = smgr->createTerrainTriangleSelector((scene::ITerrainSceneNode*)node);
				break;
			case scene::ESNT_OCTREE:
				node->setID(IDFlag_IsPickable | IDFlag_IsHighlightable);
				selector = smgr->createOctreeTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node, 32);
				break;
				
			case scene::ESNT_CAMERA_FPS:
			case scene::ESNT_CAMERA_MAYA:
			case scene::ESNT_CAMERA:
				// set up  the camera
				//smgr->addCameraSceneNode(0,core::vector3df(), core::vector3df(0, 0, 100), 0,true);
				node->setID(ID_IsNotPickable);
				smgr->setActiveCamera((scene::ICameraSceneNode*)node);
				break;
			default:
				// Don't create a selector for this node type
				break;
		}
		
		if(selector)
		{
			// Add it to the meta selector, which will take a reference to it
			meta->addTriangleSelector(selector);
			// And drop my reference to it, so that the meta selector owns it.
			selector->drop();
		}
	}
	
	// create the camera
	if(camera = smgr->getActiveCamera())
	{		
		//smgr->addCameraSceneNodeFPS(camera, 50.f, 0.1f);
		// TODO: there's got to be a better way to do this
		ICameraSceneNode* cameraFPS = smgr->addCameraSceneNodeFPS(0, 50.f, 0.1f, ID_IsNotPickable);//(0,100.0f,0.5,-1,0,0,true,0.1f,false,true); 
		cameraFPS->setPosition(camera->getPosition()); 
		cameraFPS->setRotation(camera->getRotation()); 
		cameraFPS->setTarget(camera->getTarget()); 
		cameraFPS->setAspectRatio(camera->getAspectRatio()); 
		cameraFPS->setFarValue(camera->getFarValue()); 
		cameraFPS->setFOV(camera->getFOV());

		camera = cameraFPS; // what a waste
	}
	else
	{	
		camera = smgr->addCameraSceneNodeFPS(0, 50.f, 0.1f);

		// Point the camera at the cube node, by finding the first node of type ESNT_CUBE
		scene::ISceneNode * cube = smgr->getSceneNodeFromType(scene::ESNT_CUBE);
	
		if(cube)
			camera->setTarget(cube->getAbsolutePosition());
	
		camera->setAspectRatio(GetScreenSizeXf()/GetScreenSizeYf());
		camera->setFOV((120 * M_PI / 360.0f));    
		camera->setFarValue(1000.0f);
	}
	
	// add collision
	scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(meta, camera, core::vector3df(5,5,5), core::vector3df(0,0,0));
	meta->drop(); // I'm done with the meta selector now
	
	camera->addAnimator(anim);
	anim->drop(); // I'm done with the animator now
	
	// create mipmaps	
	driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
Post Reply