Terrain Picking (ie. Int. Tut. 3) w/ .NET MouseEvents

jmonw

30-05-2006 05:54:40

I'm trying to do terrain picking based on where my mouse is, to place entities in a scene, so I looked at Intermediate Tutorials 2 and 3, and it seems that they use ODN's events.

I try the same code they use, but using the mouse coordinates given to me by the UserControl's (my "RenderWindow") MouseMove events, but it barely works at all. I have to have the camera very close to the terrain for the entities to be placed at all, and even then, they don't go to the right place. I was wondering how I need to modify the code to make it work with .NET's events.

If there's already been a post about this, please point me to it. I didn't find one when searching.

Also, if I was unclear, please let me know.

Thanks very much. And, by the way, ODN rocks! It's perfect, IMO, for level editors and such, which is what I am using it for. Very nice. Thanks.

Olivier

30-05-2006 07:52:09

Hi jmonw,

I'm trying to do terrain picking based on where my mouse ...
I was wondering how I need to modify the code to make it work with .NET's events.

I'm trying the same


If there's already been a post about this, please point me to it. I didn't find one when searching.

I don't know if this link and discussion would satisfy you, but this is the way i expressed almost the same thing:

http://www.ogre3d.org/phpBB2addons/viewtopic.php?t=1298

I found a beginning of a solution.
The download link still contain the orignal app, but i'll update it this evening.


It's perfect, IMO, for level editors and such, which is what I am using it for. Very nice. Thanks.


This is also my aim.
I you fell in the mood of sharing idea and so, or think about a cooperative development, let me know.

In the first step, I would want to introspect media package, and offer objects in to put in the real 3d window world RenderWindow, move them, name instances, and then save all of those.

Olivier

jmonw

30-05-2006 22:54:39

I you fell in the mood of sharing idea and so, or think about a cooperative development, let me know.

I very much appreciate the offer, but the level editor I'm working on is fairly specialized for a game a friend and I thought up. I'm not 100% sure that it will ever be in truly serious development, so I don't want to build a team or anything.

Thanks for the link and the sample code.

I'm always willing to tell you how I've done things, share my code, etc... Just let me know.

[EDIT]
You are still using the OgreDotNet EventHandler. I am trying to use .NET events generated by the UserControl I am using for rendering.

jmonw

31-05-2006 05:53:13

OK, after some further investigation, I think I have a better way to ask my question.

How can I select an object (or find the coordinates of a location on terrain) using 2D mouse coordinates relative to the control that is being used for rendering (ie. (0,0) is the top left of the control)?

I think I need a way to cast a ray from the 2d coordinates to the scene. I'm not 100% sure what GetCameraToViewportRay does (I haven't had a lot of time today), but it, for whatever reason, is not working properly for me.

Thanks very much for any help!

[EDIT]
Also, the control gets resized occasionally, so I think I'll need to update the camera's aspect ratio to get this to work. Is that correct?

jmonw

01-06-2006 05:15:56

OK, I got it working, sort of. It works now if the camera is relatively close to the terrain, but for some reason does not work if it's far away. At least, that's the case for me.

The trick was this: The function mCamera.GetCameraToViewportRay() expects the coordinates that you pass it to be floats and percentages of the screen, like CEGUI handles things. So, all you have to do is divide the X and Y coords of the MouseEventArgs by the width and height of the control you are rendering to (and making sure they are both floats. Otherwise you will get (0,0) exept at the very bottom right corner.)

So, here's the code:
//Create Query
OgreDotNet.Ray mouseRay = mCamera.GetCameraToViewportRay((float)e.X/(float)mControl.Width, (float)e.Y/(float)mControl.Height);

//Execute Query
RaySceneQueryResult result = mRaySceneQuery.execute();
RaySceneQueryResult.RaySceneQueryResultEnumerator itr = result.GetEnumerator();

// Get results, create a node/entity on the position
if ((itr != null) && (itr.MoveNext()))
{
Entity ent = mSceneMgr.CreateEntity("Robot" + mCount.ToString(), "robot.mesh");
mCurrentObject = mSceneMgr.GetRootSceneNode().CreateChildSceneNode("RobotNode" + mCount.ToString());
mCurrentObject.SetPosition(itr.Current.getWorldFragment().getSingleIntersection());
mCount++;
mCurrentObject.AttachObject(ent);
mCurrentObject.SetScale(10.0f, 10.0f, 10.0f); // optional
}


I'd really like to post this on the wiki, but I want to get it completely funcitonal. If anyone has any ideas about why it's behaving strangely, or if it's not for you, please let me know.

Thanks!

[EDIT]
Also, I believe that any time the control you are using for rendering gets resized, you need to change the camera's aspect ratio, and maybe recreate the viewport. I'm testing that.

[EDIT 2]
OK, then, after testing it seems that you don't have to do either of those. Rock on!

[EDIT 3]
OK, so this does work from far away. It was just a particular point that was giving me problems. I'll post this to the wiki.