XNA Collision Detection Problem

mercuriousu2
mercuriousu2 used Ask the Experts™
on
I am using xna with c# to make a 3d game project. For the most part it's going ok but I've come across a problem with my collision detection.

I am using the xna framework's bounding box and bounding sphere classes for collisions (sphere - sphere collision and box - box collision)

I created several methods in my baseObject class which create the bounding shapes for the models and allow collision checks.

But here's my problem: No matter what position the character models are in they always detect a collision.

Here is my collision code.

I declare my bounding box
BoundingBox bb;

Open in new window

I then have the method for finding the min and max vertices of a model and use them for the bounding box
 protected BoundingBox CalculateBoundingBox()
    {

        Vector3 modelMax = new Vector3(float.MinValue, float.MinValue, float.MinValue);
        Vector3 modelMin = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
        transforms = new Matrix[model.Bones.Count];

        foreach (ModelMesh mesh in model.Meshes)
        {
            Vector3 meshMax = new Vector3(float.MinValue, float.MinValue, float.MinValue);
            Vector3 meshMin = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);

            foreach (ModelMeshPart part in mesh.MeshParts)
            {
                int stride = part.VertexBuffer.VertexDeclaration.VertexStride;

                byte[] vertexData = new byte[stride * part.NumVertices];
                part.VertexBuffer.GetData(part.VertexOffset * stride, vertexData, 0, part.NumVertices, 1); 

                Vector3 vertPosition = new Vector3();
                for (int ndx = 0; ndx < vertexData.Length; ndx += stride)
                {
                    vertPosition.X = BitConverter.ToSingle(vertexData, ndx);
                    vertPosition.Y = BitConverter.ToSingle(vertexData, ndx + sizeof(float));
                    vertPosition.Z = BitConverter.ToSingle(vertexData, ndx + sizeof(float) * 2);

                    meshMin = Vector3.Min(meshMin, vertPosition);
                    meshMax = Vector3.Max(meshMax, vertPosition);
                }
            }

            meshMin = Vector3.Transform(meshMin, transforms[mesh.ParentBone.Index]);
            meshMax = Vector3.Transform(meshMax, transforms[mesh.ParentBone.Index]);

            modelMin = Vector3.Min(modelMin, meshMin);
            modelMax = Vector3.Max(modelMax, meshMax);
        }

        return bb = new BoundingBox(modelMin, modelMax);

    }

Open in new window


I then made a method to use each bounding shape for collision detection.
    public bool BoxCollision(BoundingBox secondBox)
    {
        if (bb.Intersects(secondBox))
            return true;
        else            
            return false;
    }

public bool SphereCollision(Model secondModel, Matrix secondWorld)
    {
        foreach (ModelMesh modelMeshes in model.Meshes)
        {
            foreach (ModelMesh secondModelMesh in secondModel.Meshes)
            {
                if(modelMeshes.BoundingSphere.Transform(getWorldRotation()).Intersects(secondModelMesh.BoundingSphere.Transform(secondWorld)))
                    return true;
            }
        }
        return false;
    }

Open in new window


Finally I use the methods to check if a collision happens
public void CollisionCheck()
    {
        foreach (NonPlayerChar npc in npcList)
        {
            if(player.SphereCollision(npc.model, npc.getWorldRotation()))
            { npc.position = vector3.Zero; }

            if (player.BoxCollision(npc.bb))
            { npc.position = vector3.Zero; }                 
        }

    }

Open in new window



From what I can tell from debugging the project the variable bb isn't using the information it's given and is defaulting to 0's. I'm not sure why the sphere collision isn't working...

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Author

Commented:
Can anyone assist?
The objects are testing for collision in the wrong spaces.

Author

Commented:
Hi, could you provide more detail please?
Thanks
Introduction to R

R is considered the predominant language for data scientist and statisticians. Learn how to use R for your own data science projects.

Sorry mercuriousu2, I realise that's not very helpful.  My brain is a bit fried from fighting with my own work at the moment.

if(modelMeshes.BoundingSphere.Transform(getWorldRotation()).Intersects(secondModelMesh.BoundingSphere.Transform(secondWorld)))
                    return true;

Open in new window

This code appears to put one of the spheres into world space and then only rotates the other.  That makes no sense, spheres are the same shape when you rotate them and both need to be in the same space to collide properly.

The simplest way to do sphere-sphere collision is to get the center point of each sphere (or row 4 of its world matrix), and measure the distance between them.  If the distance between them is less than the sum of their radii, the spheres are overlapping.

Does the code recalculate the bounding box every frame?

Author

Commented:
Thanks for this, I've done the sphere collision and it's now working (thank you;).
As for bounding boxes they are calculated only once at the beginning of the code and the min/max values are stored for each model in an instance of bb.
The problem is that although min/max values are being calculated for each model in the method, they are not being used by bb which keeps it's value of 0.

Any ideas?
The problem is that although min/max values are being calculated for each model in the method, they are not being used by bb which keeps it's value of 0.
Thats probably not a 3D math problem.  The question is when does bb get the zero values?  Is the value of bb set properly before the end of the CalculateBoundingBox function?  Is it still set properly when execution returns to the calling function?

Author

Commented:
Bb gets its values of zero before the calculateBoundingBox() method happens.
Yes, I understand that.  Just before the function returns they should no longer be zero.  When program exectution returns to the function that called CalculateBoundingBox() they should still not be zero.  You should be able to put some breakpoints into the code and check the values.

Author

Commented:
Ok, I have found and fixed the problem. It seems the method calculated the values of the meshMin plus max and modelMin and max. But the four lines of code after the for loop and before the return caused the value change to zero. It wasn't getting the actual model bone count.
 
Great stuff Satsumo
Many thanks

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial