"Sticking" a mesh to the surface of another


05-12-2008 17:43:20

Hi, I'm using MogreNewt for my physics library, pretty good so far but I'm having trouble creating a character body/collision. It justs doesn't give me enough control over the character, I want to be able to do everything to it without some outside force working on it. So what I'm trying to do now is to make it so the character's mesh is "stuck" on the mesh of the terrain.

Basically the lowest vertex of the character mesh should be touching the terrain mesh below it. That way if there is a hill and the mesh moves up it, the lowest vertex will always being touching the mesh below it.

Any help would be greatly appreciated.


05-12-2008 17:56:53

You should just be able to raycast straight down from your character and move him to the collision point adding half of the Character's bounding box's height


06-12-2008 05:21:53

lol, thanks for making me like a super noob :)

That seriously went through one ear and out the other. What does raycasting mean? How do I do/use it? My apologies for being nooby.


06-12-2008 05:31:12


Intermediate tutorials 2 and 3 :)

The code is originally for OgreDotNet which is gone, but the code itself should still work


06-12-2008 15:28:17

Alright thanks a lot, I'll look over those and see what I can do.


13-12-2008 19:43:37

Here I put code snippits to the wiki how to use ray queries:

If an OgreDotNet Intermediate Tutorial works with Mogre without changes, it would be nice if somebody add a comment to the wiki.


21-12-2008 22:00:07

Alright thanks a lot for the help. The ogreDotNet tutorial shows how to keep the camera going through the terrain. However is there any way to get the height of a mesh that isn't generated by the terrain scene manager?

For example to get the height of the terrain that the ray is intersecting, you do this:

float terrainHeight = itr.Current.worldFragment.singleIntersection.y;

So how could I get the height of a mesh that the ray was intersecting?


25-12-2008 12:10:56

Maybe the height of the AABB (bounding box) is enough for you. This can be queried (from a SceneNode?).
To get the SceneNodes name you can use RaySceneQueryResultEntry.movable.Name.


26-12-2008 07:56:00

My terrain isn't generated by the terrain scene manager. It's an actual mesh. The bounding box would be the same height regardless of where my character was.

I'm trying to make it so the camera can't fall through the terrain. So far I have this: (my RaySceneQuery object is called rsq)

Vector3 origin = camera.Position;
Ray camRay = new Ray(new Vector3(origin.x, origin.y, origin.z), Vector3.NEGATIVE_UNIT_Y);
rsq.Ray = camRay;
RaySceneQueryResult result = rsq.Execute();
RaySceneQueryResultEntry entry;
Vector3 rayHitPoint = Vector3.ZERO;

for (Int16 i = 0; i < result.Count; i++)
entry = result[i];

rayHitPoint = origin + (camRay.Direction * entry.distance);

if (entry.movable != null)
if (rayHitPoint.y + 10 > origin.y)
camera.SetPosition(origin.x, rayHitPoint.y + 10, origin.z);

So I'm trying to get the height of the rayHitPoint, but this code yields strange results. The camera either shoots up into the sky continuously, or the terrain moves down. Any idea why this is happening?


26-12-2008 10:54:44

I think the second line is the problem. It creates no ray from top to down.
Vector3.NEGATIVE_UNIT_Y is equal to (0, -1, 0)
Your code creates a ray from the cam position to point (0, -1, 0).

To get a ray from top to down just use
rsq.Ray = Vector3.NEGATIVE_UNIT_Y;

rsq.Ray is a vector that just represents a direction. Independent from the position.

When you use the Terrain Scene Manager than the terrain is no mesh!
So you have to use if (entry.worldFragment != null) instead.
For terrain hits entry.movable is always null.


26-12-2008 11:05:32

With your code can be a problem if your camera gets under the terrain (possible by a move heading for a steep hillside).
So it would be better to add height. The query result for terrain is the same.
Vector3 origin = camera.Position;
origin.y += 100;

You can search for the keywords clamp terrain in the forums / wiki. Maybe you find some more informations about this problem.


26-12-2008 20:01:50

rsq.Ray is expecting a ray value. Vector3.NEGATIVE_UNIT_Y is a vector.

For a ray you need the origin and a direction, and that's what I have.


27-12-2008 11:38:27

Yes, my mistake.

Try to use camera.WorldPosition instead of camera.Position. Because if the camera node is not attached to the RootSceneNode than you get the local position. That can be totally different.

rsq.Ray = new Ray(camera.WorldPosition, Vector3.NEGATIVE_UNIT_Y);
rsq.Ray.Origin.y += 100;
RaySceneQueryResult result = rsq.Execute();
// ...

By the way - you can improve the code:
// old
Ray camRay = new Ray(new Vector3(origin.x, origin.y, origin.z), Vector3.NEGATIVE_UNIT_Y);

// better
Ray camRay = new Ray(origin, Vector3.NEGATIVE_UNIT_Y);

// more better
Ray camRay = new Ray(camera.WorldPosition, Vector3.NEGATIVE_UNIT_Y);


29-12-2008 21:03:42

Thanks for the suggestion, but so far it didn't work out.

Perhaps somebody could give me an example of using the ray hit points height to keep the camera above that position. Than I could compare mine, it would be extremely appreciated.