kaykayman
kaykayman

Reputation: 393

XNA 3D Collision Detection for Terrain

I've been working on a basic 3D XNA game. So far I've managed to load various character models onto a larger level/world model. I've put in some basic controls which allows the user/player to move one of the characters around the world - and even implemented some collision detection using BoundingSphere/BoundingBox with other character models.

However, the character models (at the moment) are stuck in a fixed place on the Y-axis, and so my world is really just a flat plane for them to glide across.

What I want to do now is implement a gravity like force, which will allow characters to rise and fall with the flow of the terrain. I've spent a couple of hours on google searching (in vain) for some way of checking for a detailed collision between the bounding sphere of my character and the actual mesh of the world. The articles I have found all seem to explain how to use the sphere and box methods, or to implement some external physics engine (all of which seem really quite elaborate for what I want to achieve).

So my question is twofold -

NB. The models that I want to check for collisions are: Microsoft.Xna.Framework.Graphics.Model

EDIT:

I should also mention that I am not creating a single level, but a game engine which will work with various levels loaded from a Database. For this reason, I don't want to have to separately/manually define the constraints of the level. I would ideally like to load my single mesh from the database and be able to detect collisions with it as is, or alternatively automatically work out the constraints/bounding areas from the mesh data.

Upvotes: 2

Views: 5049

Answers (4)

Austin
Austin

Reputation: 1

You could fake it. In other words, I'm assuming, at every update call you could just set the height of your player to the height of the terrain wherever the player happens to be. I imagine not the most professional way to handle things, but might work.

Upvotes: -1

mdunsmuir
mdunsmuir

Reputation: 492

Here is a detailed description of a sphere/triangle technique I once adapted for 2D collision detection:

http://www.peroxide.dk/papers/collision/collision.pdf

I cannot say for certain that it will help you, but it may be useful for collisions with a terrain mesh and gravity. Combining that with collisions with other "characters" may be challenging, depending on exactly what it is you want to do. However, it does specifically describe how to implement gravity, and overall it is one of the simpler approaches you might take to collision detection and character physics in 3D.

As for the question of whether colliding with the entire terrain mesh is the "correct" way to go... if it is a simple mesh and you aren't resource-constrained, then sure. However, collision detection is computationally expensive, and applying it to all the triangles in your mesh may quickly become impossible. Generally, you may want to store your triangles in some efficiently searchable structure, like an octree or a k-d tree, and then do a rough search for triangles near your character which can then be tested more precisely for collisions in much less time than it would take to test every triangle in the mesh.

Upvotes: -1

Robert Templeton
Robert Templeton

Reputation: 63

The first answer gave you a first-pass test for detailed collision detection. You could refine that first-pass and use an AABB test. The second pass would then require a ray-triangle intersection test. Be careful since some of these will fail when the ray hits a triangle edge or vertex - so make sure that the tester code/algorithm you chose considers these. There are further modifications using quad-trees or other space-partitioning schemes to increase the speed of collision detection.

Upvotes: 0

Christopher Bales
Christopher Bales

Reputation: 1071

3d collision detection is more complex than it may seem at a glance, so using one of the prescribed methods (I.e. the BoundingSphere Object can help). Check http://msdn.microsoft.com/en-us/library/bb203906(v=xnagamestudio.10).aspx

Specifically this code block gives an idea:

static void CheckForCollisions( ref WorldObject c1, ref WorldObject c2 )
{
    for (int i = 0; i < c1.model.Meshes.Count; i++)
    {
        // Check whether the bounding boxes of the two cubes intersect.
        BoundingSphere c1BoundingSphere = c1.model.Meshes[i].BoundingSphere;
        c1BoundingSphere.Center += c1.position;

        for (int j = 0; j < c2.model.Meshes.Count; j++)
        {
            BoundingSphere c2BoundingSphere = c2.model.Meshes[j].BoundingSphere;
            c2BoundingSphere.Center += c2.position;

            if (c1BoundingSphere.Intersects( c2BoundingSphere ))
            {
                c2.ReverseVelocity();
                c1.Backup();
                c1.ReverseVelocity();
                return;
            }
        }
    }
}

Upvotes: 0

Related Questions