I need a better way to mouse pick.

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
sfncook
Posts: 36
Joined: Sun Jul 01, 2007 6:32 pm

I need a better way to mouse pick.

Post by sfncook »

Hi folks,

I have a scene in which I may zoom far out and wish to still be able to easily determine which game piece the mouse is currently over. Currently I'm using this method:

Code: Select all

irr::scene::ISceneNode* selectedSceneNode = smgr->getSceneCollisionManager()->getSceneNodeFromScreenCoordinatesBB(irr::core::position2di(event.MouseInput.X,event.MouseInput.Y));
Which works pretty well for now. However, when the camera is zoomed out enough the mesh objects are too small to easily pick with the mouse - if not impossible. So how can I do this easier? Ideally, rather than detect when the mouse is over the mesh I would like to detect when the mouse is over a 2D icon image to the game piece's location in the window. But how could I do this without cycling through all gamepieces every time an event fires?

I can only assume the wonderful wonderful Irrlicht library provides some juicy little tidbit that will help me in this.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Re: I need a better way to mouse pick.

Post by rogerborg »

sfncook wrote:But how could I do this without cycling through all gamepieces every time an event fires?
That's what getSceneNodeFromScreenCoordinatesBB() already done. If you need to do it, you need to do it.
sfncook wrote:I would like to detect when the mouse is over a 2D icon image to the game piece's location in the window
A "2D icon image" implemented in what way? If it's a true "2D" image, then you must already know its screen bounds. If it's a 3d object, then you can just use ISceneCollisionManager::getScreenCoordinatesFrom3DPosition() to get its position and then compare that with the cursor position.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
keless
Posts: 805
Joined: Mon Dec 15, 2003 10:37 pm
Location: Los Angeles, California, USA

Post by keless »

How many game pieces do you have on screen at a time anyway? If this is something like a chess game, it may be fine to cycle thru them all.

If however, you have greater than 200 pieces (perhaps a game like Risk) then yes, likely it will be inefficient.
a screen cap is worth 0x100000 DWORDS
sfncook
Posts: 36
Joined: Sun Jul 01, 2007 6:32 pm

Post by sfncook »

Exactly, keless, this an RTS (perhaps I should have mentioned that in the first post, duh). So there will be potentially many hundred if not a couple thousand game pieces. I assume that getSceneNodeFromScreenCoordinatesBB does this in a more efficient manner than just checking every mesh with a for loop. So if I can continue using this function to pick the game pieces with the mouse terrific! I would just need a method to dynamicly 'widen' or 'slim' the bounding box used for this operation based on their proximity to the camera. Pretty steep wish, I suppose. From the sounds of these two initial responses I think I'm fishing for something that does not exist. Maybe I'll keep looking for something that's a little more efficient that the good ol' for loop.

PS: Sorry if this post belongs in the newbie forum!
sfncook
Posts: 36
Joined: Sun Jul 01, 2007 6:32 pm

Post by sfncook »

Forget it and please don't vote me off the island for being stupid. I'm going to continue using getSceneNodeFromScreenCoordinatesBB() for when the meshes are close to the camera then I'll use a GUI element like a button or something similar for when the mesh is far from the camera.
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

sfncook wrote:I assume that getSceneNodeFromScreenCoordinatesBB does this in a more efficient manner than just checking every mesh with a for loop.
That would be a mistaken assumption. You have the code available. See CSceneCollisionManager.cpp, getSceneNodeFromScreenCoordinatesBB(), getSceneNodeFromRayBB() and getPickedNodeBB().

Code: Select all

   const core::list<ISceneNode*>& children = root->getChildren();

   core::list<ISceneNode*>::ConstIterator it = children.begin();
   for (; it != children.end(); ++it)
      ...
Where 'root' is initially the scene manager's root scene node, and then it recurses through every node in the scene.

You can make it a little more efficient by specifying a bitmask, which will allow quick rejection of objects, but it still remains a Big Dumb Loop over every single scene node.

If you want something more efficient, I'd strongly suggest implementing your own test, perhaps based on the implementation of getPickedNodeBB() but using a smarter algorithm for selecting candidate nodes.

Without knowing more about your scene, I can't suggest anything specific, although in general you could consider dividing your objects into tiles/zones, or - depending if you rotate the camera - holding them in a list ordered by (e.g.) X co-ordinate, which will allow you to check only a subset of them.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Ico
Posts: 289
Joined: Tue Aug 22, 2006 11:35 pm

Post by Ico »

Haven't taken a look at the source but how about copying getSceneNodeFromScreenCoordinatesBB() and creating a second function taking a "root scene node" as an additional parameter. So you could add all clickable elements as children to a invisible scene node and then use that one as a parameter?
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

This is one of those situations that it may be very useful to use heirchical bounding volumes for culling. If every scene node had a bounding sphere that enclosed itself and its children you could easily do a simple distance from point to line test to rule out large parts of the scene [assuming the scene is heirarchically organized].

Travis
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

this is interesting, maybe someone can do a time trial on how long does it take to loop through or walk the scene nodes from root.

hard numbers would be nice for a spectrum of environments.

charts such as bar, line and pie would be nice to see.

in one of my demos, i got 98fps on a scene having less than 20 nodes. that's running on a radeon 3850 card, though. each node are low-polys.
Image
Post Reply