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.