XNA Creators Club Online
Page 1 of 1 (3 items)
Sort Posts: Previous Next

Ray model intersection

Last post 11/12/2009 12:10 AM by DrRisc. 2 replies.
  • 11/11/2009 5:39 PM

    Ray model intersection

    Im makeing a 3d flight sym and im having a problem with ray model intersection first my program tests to see if the ray is within the bounding sphere of the enemy and then if it is it loops through each face of the model and tests if it intersects the ray. The problem is that if i shoot a bullet through the left side of the enemy the bullet model goes through the enemy model but the collision detection doesnt go off if i shoot a bullet through the right side it will but the model is perfectly cemetricle. As far as i can see the collsion detection should go off as the ray and model are all scaled and positioned correctly.


     Im using the ray intersection code from:
    http://www.ziggyware.com/readarticle.php?article_id=103

    Heres the code im using:

    1 Direction = Vector3.Transform(Vector3.Forward, Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(Bullet.Rotation.Y), MathHelper.ToRadians(Bullet.Rotation.X), MathHelper.ToRadians(Bullet.Rotation.Z))); 
    2 Transform = Matrix.CreateScale(Enemy.Scale) * Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(Enemy.Rotation.Y), MathHelper.ToRadians(Enemy.Rotation.X), MathHelper.ToRadians(Enemy.Rotation.Z)) * Matrix.CreateTranslation(Enemy.Position); 
    3 float Distance = RayModel(new Ray(Bullet.Position, Direction), Enemy.Model, Transform); 

    And here is the RayModel function

    1 struct VertexPositionNormal { 
    2     public Vector3 Position; 
    3     public Vector3 Normal; 
    4
    5  
    6 public float RayModel(Ray Ray, Model Model, Matrix Transform) { 
    7     float Ret = -1; 
    8  
    9 //Get Vertex information 
    10     VertexPositionNormal[] Verts = new VertexPositionNormal[Model.Meshes[0].VertexBuffer.SizeInBytes / Model.Meshes[0].MeshParts[0].VertexStride]; 
    11     Model.Meshes[0].VertexBuffer.GetData<VertexPositionNormal>(Verts); 
    12  
    13 //get index information 
    14     short[] Indices = new short[Model.Meshes[0].IndexBuffer.SizeInBytes / sizeof(short)]; 
    15     Model.Meshes[0].IndexBuffer.GetData<short>(Indices); 
    16  
    17 //loop though each face 
    18     for (int x = 0; x < Indices.Length; x += 3) { 
    19         float fDist=0; 
    20  
    21         Vector3 edge1 = Vector3.Transform(Verts[Indices[x + 1]].Position, Transform) - Vector3.Transform(Verts[Indices[x + 0]].Position, Transform); 
    22         Vector3 edge2 = Vector3.Transform(Verts[Indices[x + 2]].Position, Transform) - Vector3.Transform(Verts[Indices[x + 0]].Position, Transform); 
    23  
    24         Vector3 tvec, pvec, qvec; 
    25         float det, inv_det; 
    26  
    27         pvec = Vector3.Cross(Ray.Direction, edge2); 
    28  
    29         det = Vector3.Dot(edge1, pvec); 
    30  
    31         if (det > -0.000001f && det < 0.000001f) 
    32             continue
    33  
    34         inv_det = 1.0f / det; 
    35  
    36         tvec = Ray.Position - Vector3.Transform(Verts[Indices[x + 0]].Position, Transform); 
    37  
    38         float u = Vector3.Dot(tvec, pvec) * inv_det; 
    39         if (u < 0.0f || u > 1.0f) 
    40             continue
    41  
    42         qvec = Vector3.Cross(tvec, edge1); 
    43  
    44         float v = Vector3.Dot(Ray.Direction, qvec) * inv_det; 
    45         if (v < 0.0f || u + v > 1.0f) 
    46             continue
    47  
    48         fDist = Vector3.Dot(edge2, qvec) * inv_det; 
    49  
    50 //if this face collides with the ray and is closer than any other face 
    51 //set it to Ret 
    52         if (fDist < Ret || Ret == -1) 
    53             Ret = fDist; 
    54     } 
    55  
    56     return Ret; 
    57

    The model has only one mesh(mesh[0]) and is a .x file loaded through the default content pipeline and its indexs are all shorts.

    I realy have no idea why this is working some times but not otheres as the model and ray seem to be scaled and positioned correctly and the model is cymetrical so both sides are the same they should both work.
  • 11/11/2009 6:50 PM In reply to

    Re: Ray model intersection

    Have you tried debugging?   I would start of testing the code with a very simple model like a cube, and then step through each face and make sure the results that you get are what you expect.


  • 11/12/2009 12:10 AM In reply to

    Re: Ray model intersection

    Answer
    Reply Quote
    Got it!

    Ziggyware's code is wrong or not for version 3.1 i downloaded the provided source code for version 3.1 and seen that it was diffrent from the tutorial when getting access to the verts. Here are some of the changes that fix the problem


    line 10 and 11

    VertexPositionNormal[] Verts = new VertexPositionNormal[Model.Meshes[0].VertexBuffer.SizeInBytes / Model.Meshes[0].MeshParts[0].VertexStride];
    Model.Meshes[0].VertexBuffer.GetData<VertexPositionNormal>(Verts);

    become

    Vector3[] Verts = new Vector3[Model.Meshes[0].MeshParts[0].NumVertices];
    Model.Meshes[0].VertexBuffer.GetData<Vector3>(Model.Meshes[0].MeshParts[0].BaseVertex * Model.Meshes[0].MeshParts[0].VertexStride, Verts, 0, Model.Meshes[0].MeshParts[0].NumVertices, Model.Meshes[0].MeshParts[0].VertexStride);

    and line 14 and 15

    short[] Indices = new short[Model.Meshes[0].IndexBuffer.SizeInBytes / sizeof(short)];
    Model.Meshes[0].IndexBuffer.GetData<short>(Indices);

    become

    short[] Indices = new short[Model.Meshes[0].MeshParts[0].PrimitiveCount * 3];
    Model.Meshes[0].IndexBuffer.GetData<short>(Model.Meshes[0].MeshParts[0].StartIndex * sizeof(short), Indices, 0, Model.Meshes[0].MeshParts[0].PrimitiveCount * 3);

    with these changes there is no need for the VertexPositionNormal struct so i removed it.
Page 1 of 1 (3 items) Previous Next