Alternative to getRayFromScreenCoordinates

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
drac_gd
Posts: 132
Joined: Sun Apr 09, 2006 8:43 pm

Alternative to getRayFromScreenCoordinates

Post by drac_gd »

When using third person camera and newton I could not get the mouse picking/moving to work right. Here is my alternative..
RCODE is a s32 value. substitue your own names for camera etc as needed

Code: Select all

//------------------------------------------------------------------------------
//! unproject screen coordinates into a world position.. return 0 if no error
RCODE VxGameMgr::ScreenToWorld( int screenx, int screeny, int screenz, core::vector3df & v3fRetPos )
{
	core::matrix4 trans = m_pgCam->m_pgCamNode->getProjectionMatrix();
	trans *= m_pgCam->m_pgCamNode->getViewMatrix();
	trans.makeInverse();

	core::dimension2d<s32> dim = m_pgDriver->getScreenSize();
	// irrlich y coords increase upward whereas windows increase downward so invert
	screeny = dim.Height - screeny;

	dim.Width /= 2;
	dim.Height /= 2;

	// irrlicht uses screen range -0.5 to 0.5
    // Map x and y from window coordinates 
    f32 f32X = (f32)screenx / dim.Width;
    f32 f32Y = (f32)screeny / dim.Height;

    // Map to range -1 to 1 
    f32X = f32X  - 1;
    f32Y =  f32Y - 1;

	f32 transformedPos[4];

	transformedPos[0] = f32X;
	transformedPos[1] = f32Y;
	transformedPos[2] = (f32)screenz;
	transformedPos[3] = 1.0f;

	trans.multiplyWith1x4Matrix(transformedPos);

	if (transformedPos[3] < 0)
	{
		v3fRetPos.X = -10000;
		v3fRetPos.Y = -10000;
		v3fRetPos.Z = -10000;
		return -1;
	}

	v3fRetPos.X = transformedPos[0] / transformedPos[3];
	v3fRetPos.Y = transformedPos[1] / transformedPos[3];
	v3fRetPos.Z = transformedPos[2] / transformedPos[3];

	return 0;
}
//------------------------------------------------------------------------------
//! project world position onto screen coordinates
void VxGameMgr::WorldToScreen( core::vector3df v3fObjPos, 
							   core::position2d<s32> & v2dRetPos )
{
	v2dRetPos = m_pgSceneMgr->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition( v3fObjPos );
}

//------------------------------------------------------------------------------
//!Get ray from cursor into the world
line3d<f32> VxGameMgr::GetMousePickRay( void )
{
	core::position2d<s32> v2dPos;
	line3d<f32> Ray;
	core::position2d <s32> mouse1 = m_pgDevice->getCursorControl()->getPosition();
	
	// using normal irrlich methods
#if 0	
	//printf( "start cursor pos %d %d\n", mouse1.X, mouse1.Y );

	Ray = m_pgSceneMgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
					mouse1,
					(scene::ICameraSceneNode *)m_pgCam->m_pgSceneNode);
				
	//WorldToScreen( Ray.start, v2dPos );
	//printf( "Ray start %3.3f %3.3f %3.3f pos %d %d\n", 
	//	Ray.start.X,
	//	Ray.start.Y,
	//	Ray.start.Z,
	//	v2dPos.X,
	//	v2dPos.Y ); 
	//WorldToScreen( Ray.end, v2dPos );
	//printf( "Ray end %3.3f %3.3f %3.3f pos %d %d\n", 
	//	Ray.end.X,
	//	Ray.end.Y,
	//	Ray.end.Z,
	//	v2dPos.X,
	//	v2dPos.Y ); */
#else
	// using opengl style unproject methods
	ScreenToWorld( mouse1.X, mouse1.Y, 0, Ray.start );
	
	//WorldToScreen( Ray.start, v2dPos );
	//printf( "Ray2 start %3.3f %3.3f %3.3f pos %d %d\n", 
	//	Ray.start.X,
	//	Ray.start.Y,
	//	Ray.start.Z,
	//	v2dPos.X,
	//	v2dPos.Y ); 

	ScreenToWorld( mouse1.X, mouse1.Y, 1, Ray.end );
	
	//WorldToScreen( Ray.end, v2dPos );
	//printf( "Ray2 end %3.3f %3.3f %3.3f pos %d %d\n", 
	//	Ray.end.X,
	//	Ray.end.Y,
	//	Ray.end.Z,
	//	v2dPos.X,
	//	v2dPos.Y ); 
#endif


	return Ray;
}
sgt_pinky
Posts: 149
Joined: Sat Oct 14, 2006 11:20 am
Location: Melbourne, Australia

Post by sgt_pinky »

Not sure why you would say that the default Irrlicht version doesn't work for you. It works fine for me - I am using 3rd person camera, FPS and free view cameras, and it works in all of them.

Can you post exactly where you had the problem?
Intellectuals solve problems - geniuses prevent them. -- Einstein
#irrlicht on irc.freenode.net
Post Reply