2d screen -> 3d world coordinate

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
cyberbobjr
Posts: 64
Joined: Mon Sep 08, 2003 8:21 am
Location: Paris, France

2d screen -> 3d world coordinate

Post by cyberbobjr »

Hi all,
i have a little question about 2D projection :
I'm working with event.MouseInput, but the X and Y parameter of event.MouseInput is in screen coordinate... how can i cast a ray from camera for finding the projection of event.MouseInput.X and event.MouseInput.Y in the world coordinate (vector3df) of a BSP level ?

Thanks for your help and sorry for my bad english...
Regards.
cyb

PS : i don't want to use Camera->getTarget() because it's a customized camera ;)
saigumi
Posts: 921
Joined: Fri Aug 22, 2003 11:31 am
Location: St. Louis, MO USA
Contact:

Post by saigumi »

You would most likely want to use the ISceneCollisionManager for picking.

There is a function called getSceneNodeFromScreenCoordinatesBB.
Crud, how do I do this again?
cyberbobjr
Posts: 64
Joined: Mon Sep 08, 2003 8:21 am
Location: Paris, France

Post by cyberbobjr »

Hi,
Thanks for your response, but i can't use this function, why ?
Because i want to select more than one node with a dragging box (the dragging box is Draw2DRectangle), one the dragging box is choosed i want to check all node's coordinates to see if UpperLeft.X and LowerRight.X (UpperLeft.Y and LowerRight.Y too) is in my dragging box...

The only solution is to projectate the coordinates of my 2D dragging box in the 3D world... (or maybe inverse... project the 3D Coordinate of the nodes in my 2D screen coordinate.... someone have a better solution ?)

The main idea is :in the future, instead of having a 2DRectangle on the screen, i'll made a 3DBox for selecting node.

if i use getSceneNodeFromScreenCoordinatesBB and my dragging box is 150x150 pixels, i must call 22500 getSceneNodeFromScreenCoordinatesBB !
niko
Site Admin
Posts: 1759
Joined: Fri Aug 22, 2003 4:44 am
Location: Vienna, Austria
Contact:

Post by niko »

Take a look at the source code of getSceneNodeFromScreenCoordinatesBB(), in there a ray is created exaclty as you need it. I'll add a getRayFromScreenCoordinates in the next release. But until then, simply create the ray manually, like it is done in getSceneNodeFromScreenCoordinatesBB().
cyberbobjr
Posts: 64
Joined: Mon Sep 08, 2003 8:21 am
Location: Paris, France

Post by cyberbobjr »

Hurrah ! it's working :)

This is the code :

Code: Select all

vector3df cameraMoving::getSceneNodeFromScreenCoordinatesBB(core::position2d<s32> pos, s32 idBitMask)
{
	const scene::SViewFrustrum* f = 
		smgr->getActiveCamera()->getViewFrustrum();
	core::vector3df farLeftUp = f->getFarLeftUp();
	core::vector3df lefttoright = f->getFarRightUp() - farLeftUp;
	core::vector3df uptodown = f->getFarLeftDown() - farLeftUp;
	core::dimension2d<s32> screenSize = driver->getScreenSize();
	f32 dx = pos.X / (f32)screenSize.Width;
	f32 dy = pos.Y / (f32)screenSize.Height;
	core::vector3df end = farLeftUp + (lefttoright * dx) + (uptodown * dy);

	core::line3d<f32> line;
	line.start = camera->getPosition();
	line.end = line.start +(end - line.start).normalize() * 1000.0f;

	core::vector3df intersection;
	core::triangle3df tri;
	if (smgr->getSceneCollisionManager()->getCollisionPoint(line, selector_floor, intersection, tri))
		return intersection;
	return end;
};
And this is how i use it (sorry it's a little long) in my OnEvent function :

Code: Select all

	if (event.EventType==EET_MOUSE_INPUT_EVENT && 
			event.MouseInput.Event==EMIE_LMOUSE_LEFT_UP)
	{
		drawSelected=false;
		if (drawRect)
		{
			std::cerr<<"LEFT CLICKED UP"<<std::endl;
			vector3df lowerRightCorner, upperLeftCorner;
			lowerRightCorner = getSceneNodeFromScreenCoordinatesBB(position2d<s32>(event.MouseInput.X,event.MouseInput.Y),0);
			upperLeftCorner = getSceneNodeFromScreenCoordinatesBB(position2d<s32>(selectionRect.UpperLeftCorner.X,selectionRect.UpperLeftCorner.Y),0);
			std::cerr<<"UPPER LEFT X :"<<upperLeftCorner.X<<std::endl;
			std::cerr<<"UPPER LEFT Z :"<<upperLeftCorner.Z<<std::endl;
			std::cerr<<"LOWER RIGHT X :"<<lowerRightCorner.X<<std::endl;
			std::cerr<<"LOWER RIGHT Z :"<<lowerRightCorner.Z<<std::endl;
			std::cerr<<"NODE POSITION X :"<<node->getPosition().X<<std::endl;
			std::cerr<<"NODE POSITION Z :"<<node->getPosition().Z<<std::endl;
			
			if (node->getPosition().X<upperLeftCorner.X && node->getPosition().X>lowerRightCorner.X
				&& node->getPosition().Z>lowerRightCorner.Z && node->getPosition().Z<upperLeftCorner.Z)
			{
				std::cerr<<"SELECTED"<<std::endl;
				drawSelected=true;
			}
		}
		else
		{
			if (smgr->getSceneCollisionManager()->getSceneNodeFromScreenCoordinatesBB(position2d<s32>(event.MouseInput.X,event.MouseInput.Y),0))
			{
				std::cerr<<"SELECTED"<<std::endl;
				drawSelected=true;
			}
		}
		oldMouseInputX=0;
		oldMouseInputY=0;
		stayLClicked=false;
		drawRect=false;
And in the main routine :

Code: Select all

		if (drawSelected)
			driver->draw3DBox(node->getBoundingBox(),SColor(0,250,0,0));
It's just for 1 node, but after i can use this for recursively search the node is the dragging selection box ...

Thanks for your help :)
Post Reply