float? RayIntersectsModel(Ray ray, Matrix modelTransform,

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);

// Keep track of the closest triangle we found so far,

// so we can always return the closest one.

float? closestIntersection = null;

for (int i = 0; i < terrain.TerrainVertices.Length -1; i += 3)

{

// Perform a ray to triangle intersection test.

float? intersection;

RayIntersectsTriangle(ref ray,

ref terrain.TerrainVertices1[i],

ref terrain.TerrainVertices1[i + 1],

ref terrain.TerrainVertices1[i + 2],

out intersection);

// Does the ray intersect this triangle?

if (intersection != null)

{

// If so, find the cloest one

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 terrain.TerrainVertices1[i],

ref modelTransform, out vertex1);

Vector3.Transform(ref terrain.TerrainVertices1[i + 1],

ref modelTransform, out vertex2);

Vector3.Transform(ref terrain.TerrainVertices1[i + 2],

ref modelTransform, out vertex3);

}

}

}

return closestIntersection;

}

void RayIntersectsTriangle(ref 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;

}