my collision detection code doesn't work

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

36 Replies - 3557 Views - Last Post: 05 February 2011 - 06:42 AM

#1 prabh   User is offline

  • D.I.C Regular
  • member icon

Reputation: 3
  • View blog
  • Posts: 382
  • Joined: 27-December 08

my collision detection code doesn't work

Posted 02 February 2011 - 08:16 AM

Hi

my code works fine for plane surface
but i have terrain which has a plane in middle and some mountains on side

Image attached below will tell you more
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using JigLibX.Math;
using JigLibX.Physics;
using JigLibX.Geometry;

namespace RacerX
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        RasterizerState rs;
        SpriteBatch spriteBatch;
        Model terrain;
        Model car;
        Model WheelfrontRight;
        Vector3 frontRightWheelPos = new Vector3(1.8f, 0.4f, 1.0f);
        Model WheelfrontLeft;
        Model WheelbackRight;
        Model WheelbackLeft;
        Vector3 cameraPosition = new Vector3(0.0f, 10.0f, 20.0f);
        Vector3 cameraLookAt;
        float angle = 0.0f;
        Vector3 rayDir;
        float speed;
        Vector3 vertex1, vertex2, vertex3;
        List<string> insideBoundingSpheres = new List<string>();
        Matrix cameraViewMatrix;
        Matrix cameraProjectionMatrix;
        Matrix wheelMatrix;
        Matrix terrainWorldMatrix;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            rs = new RasterizerState();
            rs.FillMode = FillMode.WireFrame;
            graphics.GraphicsDevice.RasterizerState = rs;
           
            terrain = Content.Load<Model>("terrain");
            terrainWorldMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(-90.0f)) * Matrix.CreateTranslation(Vector3.Zero);
            car = Content.Load<Model>("car");
            WheelfrontRight=Content.Load<Model>("wheel");
            WheelfrontLeft = Content.Load<Model>("wheel");
            WheelbackRight = Content.Load<Model>("wheel");
            WheelbackLeft = Content.Load<Model>("wheel");
            wheelMatrix = Matrix.CreateTranslation(frontRightWheelPos);
            rayDir = Vector3.Down;
            speed = 0.025f;
            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            
            cameraLookAt = frontRightWheelPos;
            
            cameraViewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookAt, Vector3.Up);
            cameraProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), graphics.GraphicsDevice.Viewport.AspectRatio, 1.0f, 10000.0f);
            KeyboardState keyboard = Keyboard.GetState();
            if(keyboard.IsKeyDown(Keys.Up))
            {

            angle += 2.0f;
            if (angle == 360.0f)
            {
                angle = 0.0f;
            }
            else
            {
                frontRightWheelPos.X += speed;
                rayDir.X += speed;
                cameraPosition.X += speed;
                wheelMatrix = Matrix.Identity * Matrix.CreateRotationZ(MathHelper.ToRadians(-angle)) * Matrix.CreateTranslation(frontRightWheelPos);
                
            }
            
            }
            if(keyboard.IsKeyDown(Keys.Down))
            {
                angle -= 2.0f;
            if (angle == 360.0f)
            {
                angle = 0.0f;
            }
            else
            {
                frontRightWheelPos.X -= speed;
                rayDir.X -= speed;
                cameraPosition.X -= speed;
                wheelMatrix = Matrix.Identity * Matrix.CreateRotationZ(MathHelper.ToRadians(-angle)) * Matrix.CreateTranslation(frontRightWheelPos);
            }
            }
 
            // TODO: Add your update logic here
              UpdatePicking();
              //this.Update(gameTime);
            base.Update(gameTime);
            
        }
        #region CollisionDetection

        void UpdatePicking()
        {
            // Look up a collision ray based on the current cursor position. See the
            // Picking Sample documentation for a detailed explanation of this.
            Microsoft.Xna.Framework.Ray wheelRay;
            wheelRay.Direction = rayDir;
            wheelRay.Position = frontRightWheelPos;
            insideBoundingSpheres.Clear();


          

                bool insideBoundingSphere;
                

                // Perform the ray to model intersection test.
                float? intersection = RayIntersectsModel(wheelRay, terrain,
                                                         Matrix.CreateTranslation(Vector3.Zero),
                                                         out insideBoundingSphere,
                                                         out vertex1, out vertex2,
                                                         out vertex3);

                // If this model passed the initial bounding sphere test, remember
                // that so we can display it at the top of the screen.
                if (insideBoundingSphere)
                    insideBoundingSpheres.Add("terrain");


                Vector3 triNormal;
                Vector3 vN1 = Vector3.Subtract(vertex2, vertex1);
                Vector3 vN2 = Vector3.Subtract(vertex3, vertex2);
                triNormal = Vector3.Cross(vN1, vN2);
                float d;
                d = -Vector3.Dot(vertex1, triNormal);
                Vector3 ray;
                ray = Vector3.Subtract(rayDir, frontRightWheelPos);
                Vector3.Normalize(ray);
                float time = -(d + Vector3.Dot(triNormal, frontRightWheelPos)) / Vector3.Dot(triNormal, ray);
                Vector3 intersect = frontRightWheelPos + (ray * time);
                if (intersection != null)
                {
                    frontRightWheelPos.Y = intersect.Y + .4f;
                }
                else
                {
                    wheelRay.Position = new Vector3(frontRightWheelPos.X, 10.0f, frontRightWheelPos.Z);
                }
                
                if (float.IsNaN(intersect.Y))
                {
                    //System.Diagnostics.Debugger.Break();
                }
        }



        static float? RayIntersectsModel(Microsoft.Xna.Framework.Ray ray, Model model, Matrix modelTransform,
                                         out bool insideBoundingSphere,
                                         out Vector3 vertex1, out Vector3 vertex2,
                                         out Vector3 vertex3)
        {
            vertex1 = vertex2 = vertex3 = Vector3.Zero;


            Matrix inverseTransform = Matrix.Invert(modelTransform);

            ray.Position = Vector3.Transform(ray.Position, inverseTransform);
            ray.Direction = Vector3.TransformNormal(ray.Direction, inverseTransform);

            // Look up our custom collision data from the Tag property of the model.
            Dictionary<string, object> tagData = (Dictionary<string, object>)model.Tag;

            if (tagData == null)
            {
                throw new InvalidOperationException(
                    "Model.Tag is not set correctly. Make sure your model " +
                    "was built using the custom TrianglePickingProcessor.");
            }

            // Start off with a fast bounding sphere test.
            BoundingSphere boundingSphere = (BoundingSphere)tagData["BoundingSphere"];

            if (boundingSphere.Intersects(ray) == null)
            {
                // If the ray does not intersect the bounding sphere, we cannot
                // possibly have picked this model, so there is no need to even
                // bother looking at the individual triangle data.
                insideBoundingSphere = false;
                //System.Diagnostics.Debugger.Break();
                return null;
            }
            else
            {
                // The bounding sphere test passed, so we need to do a full
                // triangle picking test.
                insideBoundingSphere = true;

                // Keep track of the closest triangle we found so far,
                // so we can always return the closest one.
                float? closestIntersection = null;

                // Loop over the vertex data, 3 at a time (3 vertices = 1 triangle).
                Vector3[] vertices = (Vector3[])tagData["Vertices"];

                for (int i = 0; i < vertices.Length; i += 3)
                {
                    // Perform a ray to triangle intersection test.
                    float? intersection;

                    RayIntersectsTriangle(ref ray,
                                          ref vertices[i],
                                          ref vertices[i + 1],
                                          ref vertices[i + 2],
                                          out intersection);

                    // Does the ray intersect this triangle?
                    if (intersection != null)
                    {
                        // If so, is it closer than any other previous triangle?
                        if ((closestIntersection == null) ||
                            (intersection < closestIntersection))
                        {
                            // Store the distance to this triangle.
                            closestIntersection = intersection;

                            // Transform the three vertex positions into world space,
                            // and store them into the output vertex parameters.
                            Vector3.Transform(ref vertices[i],
                                              ref modelTransform, out vertex1);

                            Vector3.Transform(ref vertices[i + 1],
                                              ref modelTransform, out vertex2);

                            Vector3.Transform(ref vertices[i + 2],
                                              ref modelTransform, out vertex3);
                        }
                    }
                }

                return closestIntersection;
            }
        }


        static void RayIntersectsTriangle(ref Microsoft.Xna.Framework.Ray ray,
                                          ref Vector3 vertex1,
                                          ref Vector3 vertex2,
                                          ref Vector3 vertex3, out float? result)
        {
            // Compute vectors along two edges of the triangle.
            Vector3 edge1, edge2;

            Vector3.Subtract(ref vertex2, ref vertex1, out edge1);
            Vector3.Subtract(ref vertex3, ref vertex1, out edge2);

            // Compute the determinant.
            Vector3 directionCrossEdge2;
            Vector3.Cross(ref ray.Direction, ref edge2, out directionCrossEdge2);

            float determinant;
            Vector3.Dot(ref edge1, ref directionCrossEdge2, out determinant);

            // If the ray is parallel to the triangle plane, there is no collision.
            if (determinant > -float.Epsilon && determinant < float.Epsilon)
            {
                result = null;
                return;
            }

            float inverseDeterminant = 1.0f / determinant;

            // Calculate the U parameter of the intersection point.
            Vector3 distanceVector;
            Vector3.Subtract(ref ray.Position, ref vertex1, out distanceVector);

            float triangleU;
            Vector3.Dot(ref distanceVector, ref directionCrossEdge2, out triangleU);
            triangleU *= inverseDeterminant;

            // Make sure it is inside the triangle.
            if (triangleU < 0 || triangleU > 1)
            {
                result = null;
                return;
            }

            // Calculate the V parameter of the intersection point.
            Vector3 distanceCrossEdge1;
            Vector3.Cross(ref distanceVector, ref edge1, out distanceCrossEdge1);

            float triangleV;
            Vector3.Dot(ref ray.Direction, ref distanceCrossEdge1, out triangleV);
            triangleV *= inverseDeterminant;

            // Make sure it is inside the triangle.
            if (triangleV < 0 || triangleU + triangleV > 1)
            {
                result = null;
                return;
            }

            // Compute the distance along the ray to the triangle.
            float rayDistance;
            Vector3.Dot(ref edge2, ref distanceCrossEdge1, out rayDistance);
            rayDistance *= inverseDeterminant;

            // Is the triangle behind the ray origin?
            if (rayDistance < 0)
            {
                result = null;
                return;
            }

            result = rayDistance;
        }
        #endregion
        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
           
            LoadTerrain();
            // TODO: Add your drawing code here
            DrawModel(car, new Vector3(0.0f,0.1f,0.0f));
            CreateWheels(WheelfrontRight, wheelMatrix);
            base.Draw(gameTime);
        }
        void DrawModel(Model model,Vector3 Position)
        {
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.PreferPerPixelLighting = true;

                    effect.World = Matrix.CreateTranslation(Position);
                    effect.Projection = cameraProjectionMatrix;
                    effect.View = cameraViewMatrix;
                }
                mesh.Draw();
            }
        }
        void CreateWheels(Model wheelModel, Matrix wheelMatrix)
        {
            foreach (ModelMesh mesh in wheelModel.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.PreferPerPixelLighting = true;
                    effect.DirectionalLight0.Direction = Vector3.Down;
                    
                    effect.World = wheelMatrix;
                    effect.Projection = cameraProjectionMatrix;
                    effect.View = cameraViewMatrix;
                }
                mesh.Draw();
            }
        }
        void LoadTerrain()
        {
            
            Matrix terrainWorldMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(-90.0f)) * Matrix.CreateTranslation(Vector3.Zero);
            
            foreach (ModelMesh mesh in terrain.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.PreferPerPixelLighting = true;
                    effect.DirectionalLight0.Direction = Vector3.Down;

                    effect.World = terrainWorldMatrix;
                    effect.Projection = cameraProjectionMatrix;
                    effect.View = cameraViewMatrix;
                }
                mesh.Draw();
            }
        }

    }
}




Thanks for any help you provide

Attached image(s)

  • Attached Image


Is This A Good Question/Topic? 0
  • +

Replies To: my collision detection code doesn't work

#2 Kilorn   User is offline

  • XNArchitect
  • member icon



Reputation: 1361
  • View blog
  • Posts: 3,534
  • Joined: 03-May 10

Re: my collision detection code doesn't work

Posted 02 February 2011 - 08:34 AM

Just so I understand the problem completely, you're saying that when you go beyond that one edge, your wheel suddenly drops below the surface of the terrain?
Was This Post Helpful? 0
  • +
  • -

#3 prabh   User is offline

  • D.I.C Regular
  • member icon

Reputation: 3
  • View blog
  • Posts: 382
  • Joined: 27-December 08

Re: my collision detection code doesn't work

Posted 02 February 2011 - 08:39 AM

View PostKilorn, on 02 February 2011 - 08:34 AM, said:

Just so I understand the problem completely, you're saying that when you go beyond that one edge, your wheel suddenly drops below the surface of the terrain?

You Are right
it should travel up as per inclined triangle
Was This Post Helpful? 0
  • +
  • -

#4 Kilorn   User is offline

  • XNArchitect
  • member icon



Reputation: 1361
  • View blog
  • Posts: 3,534
  • Joined: 03-May 10

Re: my collision detection code doesn't work

Posted 02 February 2011 - 08:41 AM

Does the wheel drop on the Y axis proportionally? Meaning the further up the incline the wheel is supposed to go, the lower it actually gets on the Y axis?
Was This Post Helpful? 0
  • +
  • -

#5 prabh   User is offline

  • D.I.C Regular
  • member icon

Reputation: 3
  • View blog
  • Posts: 382
  • Joined: 27-December 08

Re: my collision detection code doesn't work

Posted 02 February 2011 - 08:45 AM

View PostKilorn, on 02 February 2011 - 08:41 AM, said:

Does the wheel drop on the Y axis proportionally? Meaning the further up the incline the wheel is supposed to go, the lower it actually gets on the Y axis?

No
it drops down to -7......
Was This Post Helpful? 0
  • +
  • -

#6 Kilorn   User is offline

  • XNArchitect
  • member icon



Reputation: 1361
  • View blog
  • Posts: 3,534
  • Joined: 03-May 10

Re: my collision detection code doesn't work

Posted 02 February 2011 - 08:52 AM

And stays there no matter how high the terrain gets as you continue to move it around? I'm just trying to get a feel for exactly whats happening so I can narrow down the search a bit.
Was This Post Helpful? 0
  • +
  • -

#7 prabh   User is offline

  • D.I.C Regular
  • member icon

Reputation: 3
  • View blog
  • Posts: 382
  • Joined: 27-December 08

Re: my collision detection code doesn't work

Posted 02 February 2011 - 09:11 AM

View PostKilorn, on 02 February 2011 - 08:52 AM, said:

And stays there no matter how high the terrain gets as you continue to move it around? I'm just trying to get a feel for exactly whats happening so I can narrow down the search a bit.

after dropping down it doesn't changes its height again
Was This Post Helpful? 0
  • +
  • -

#8 Kilorn   User is offline

  • XNArchitect
  • member icon



Reputation: 1361
  • View blog
  • Posts: 3,534
  • Joined: 03-May 10

Re: my collision detection code doesn't work

Posted 02 February 2011 - 09:26 AM

I have a feeling that there is a problem pertaining to the following code:
    if (intersection != null)
    {
        frontRightWheelPos.Y = intersect.Y + .4f;
    }
    else
    {
        wheelRay.Position = new Vector3(frontRightWheelPos.X, 10.0f, frontRightWheelPos.Z);
    }



From what I can tell, as long as intersection's value is not null, the wheel is supposed to stay .4f above the terrain that it is currently "sitting on". Once you hit that one edge, it drops to -11.0f. I have a feeling there is something going on that is causing intersection to become null at that point, but I haven't been able to figure out exactly what yet.
Was This Post Helpful? 0
  • +
  • -

#9 prabh   User is offline

  • D.I.C Regular
  • member icon

Reputation: 3
  • View blog
  • Posts: 382
  • Joined: 27-December 08

Re: my collision detection code doesn't work

Posted 02 February 2011 - 09:35 AM

View PostKilorn, on 02 February 2011 - 09:26 AM, said:

I have a feeling that there is a problem pertaining to the following code:
    if (intersection != null)
    {
        frontRightWheelPos.Y = intersect.Y + .4f;
    }
    else
    {
        wheelRay.Position = new Vector3(frontRightWheelPos.X, 10.0f, frontRightWheelPos.Z);
    }



From what I can tell, as long as intersection's value is not null, the wheel is supposed to stay .4f above the terrain that it is currently "sitting on". Once you hit that one edge, it drops to -11.0f. I have a feeling there is something going on that is causing intersection to become null at that point, but I haven't been able to figure out exactly what yet.


You got It


I'm also unable to figure why do i get intersection = null
thats why i posted my code
i was not sure if it was the problem so i didn't poseted that intersection is also null

one more thing

Ray is intersecting the bounding sphere
i have tried to break if insideboundingsphere=false

but it never returns false
Was This Post Helpful? 0
  • +
  • -

#10 Kilorn   User is offline

  • XNArchitect
  • member icon



Reputation: 1361
  • View blog
  • Posts: 3,534
  • Joined: 03-May 10

Re: my collision detection code doesn't work

Posted 02 February 2011 - 09:47 AM

One thing we can try, is to remove the "?" from the intersection declaration. This will declare a float that is not nullable. Try that and let's see what happens.
Was This Post Helpful? 0
  • +
  • -

#11 prabh   User is offline

  • D.I.C Regular
  • member icon

Reputation: 3
  • View blog
  • Posts: 382
  • Joined: 27-December 08

Re: my collision detection code doesn't work

Posted 02 February 2011 - 09:58 AM

View PostKilorn, on 02 February 2011 - 09:47 AM, said:

One thing we can try, is to remove the "?" from the intersection declaration. This will declare a float that is not nullable. Try that and let's see what happens.

can you tell me from where
because when i removed from it from everywhere
i got a bunch of errors
Was This Post Helpful? 0
  • +
  • -

#12 Kilorn   User is offline

  • XNArchitect
  • member icon



Reputation: 1361
  • View blog
  • Posts: 3,534
  • Joined: 03-May 10

Re: my collision detection code doesn't work

Posted 02 February 2011 - 10:01 AM

From the declaration on line 170 inside the UpdatePicking method.

EDIT: And if you run into any errors after that, paste them here as well.

This post has been edited by Kilorn: 02 February 2011 - 10:02 AM

Was This Post Helpful? 0
  • +
  • -

#13 prabh   User is offline

  • D.I.C Regular
  • member icon

Reputation: 3
  • View blog
  • Posts: 382
  • Joined: 27-December 08

Re: my collision detection code doesn't work

Posted 02 February 2011 - 10:04 AM

if remove it from the first declaration
i got a lot lot of errors

removing "?"
from one place

after that
whole code needs to be changed
Was This Post Helpful? 0
  • +
  • -

#14 Kilorn   User is offline

  • XNArchitect
  • member icon



Reputation: 1361
  • View blog
  • Posts: 3,534
  • Joined: 03-May 10

Re: my collision detection code doesn't work

Posted 02 February 2011 - 10:06 AM

Okay. I see now that there is a second declaration of a float? named intersection inside the RayIntersectsModel method which is called on line 170 when you declare intersection in the UpdatePicking method. The RayIntersectsModel method is of type float? so the declaration on line 170 is going to have to be of the same type.
Was This Post Helpful? 0
  • +
  • -

#15 prabh   User is offline

  • D.I.C Regular
  • member icon

Reputation: 3
  • View blog
  • Posts: 382
  • Joined: 27-December 08

Re: my collision detection code doesn't work

Posted 02 February 2011 - 10:06 AM

Error 1 Cannot implicitly convert type 'float?' to 'float'. An explicit conversion exists (are you missing a cast?) C:\Documents and Settings\Administrator\my documents\visual studio 2010\Projects\RacerX\RacerX\RacerX\Game1.cs 170 38 RacerX

thats the error
Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3