/// <summary> /// Adapted from http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf /// </summary> /// <param name="origin">Origin point of the ray</param> /// <param name="direction">Unit vector representing the direction of the ray</param> /// <param name="vert0">Position of the first triangle corner</param> /// <param name="vert1">Position of the second triangle corner</param> /// <param name="vert2">Position of the third triangle corner</param> /// <param name="collisionPoint">The collision point in the triangle</param> /// <returns>True if the ray passes through the triangle, otherwise false</returns> static bool RayTriangleIntersection(Vertex origin, Vertex direction, Vertex vert0, Vertex vert1, Vertex vert2, out Vertex collisionPoint) { const float EPSILON = 0.00001f; Vertex edge1, edge2, pvec; float determinant, invDeterminant; // Find vectors for two edges sharing vert0 edge1 = vert1 - vert0; edge2 = vert2 - vert0; // Begin calculating the determinant pvec = direction.cross(edge2); // If the determinant is near zero, ray lies in plane of triangle determinant = edge1.dot(pvec); if (determinant > -EPSILON && determinant < EPSILON) { collisionPoint = (Vertex)Vertex.Zero; return(false); } invDeterminant = 1f / determinant; // Calculate distance from vert0 to ray origin Vertex tvec = origin - vert0; // Calculate U parameter and test bounds float u = tvec.dot(pvec) * invDeterminant; if (u < 0.0f || u > 1.0f) { collisionPoint = (Vertex)Vertex.Zero; return(false); } // Prepare to test V parameter Vertex qvec = tvec.cross(edge1); // Calculate V parameter and test bounds float v = direction.dot(qvec) * invDeterminant; if (v < 0.0f || u + v > 1.0f) { collisionPoint = (Vertex)Vertex.Zero; return(false); } //t = Vertex.Dot(edge2, qvec) * invDeterminant; collisionPoint = new Vertex( vert0.X + u * (vert1.X - vert0.X) + v * (vert2.X - vert0.X), vert0.Y + u * (vert1.Y - vert0.Y) + v * (vert2.Y - vert0.Y), vert0.Z + u * (vert1.Z - vert0.Z) + v * (vert2.Z - vert0.Z)); return(true); }
/// <summary> /// Adapted from http://www.cs.virginia.edu/~gfx/Courses/2003/ImageSynthesis/papers/Acceleration/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf /// </summary> /// <param name="origin">Origin point of the ray</param> /// <param name="direction">Unit vector representing the direction of the ray</param> /// <param name="vert0">Position of the first triangle corner</param> /// <param name="vert1">Position of the second triangle corner</param> /// <param name="vert2">Position of the third triangle corner</param> /// <param name="collisionPoint">The collision point in the triangle</param> /// <returns>True if the ray passes through the triangle, otherwise false</returns> static bool RayTriangleIntersection(Vertex origin, Vertex direction, Vertex vert0, Vertex vert1, Vertex vert2, out Vertex collisionPoint) { const float EPSILON = 0.00001f; Vertex edge1, edge2, pvec; float determinant, invDeterminant; // Find vectors for two edges sharing vert0 edge1 = vert1 - vert0; edge2 = vert2 - vert0; // Begin calculating the determinant pvec = direction.cross(edge2); // If the determinant is near zero, ray lies in plane of triangle determinant = edge1.dot(pvec); if (determinant > -EPSILON && determinant < EPSILON) { collisionPoint = (Vertex)Vertex.Zero; return false; } invDeterminant = 1f / determinant; // Calculate distance from vert0 to ray origin Vertex tvec = origin - vert0; // Calculate U parameter and test bounds float u = tvec.dot(pvec) * invDeterminant; if (u < 0.0f || u > 1.0f) { collisionPoint = (Vertex)Vertex.Zero; return false; } // Prepare to test V parameter Vertex qvec = tvec.cross(edge1); // Calculate V parameter and test bounds float v = direction.dot(qvec) * invDeterminant; if (v < 0.0f || u + v > 1.0f) { collisionPoint = (Vertex)Vertex.Zero; return false; } //t = Vertex.Dot(edge2, qvec) * invDeterminant; collisionPoint = new Vertex( vert0.X + u * (vert1.X - vert0.X) + v * (vert2.X - vert0.X), vert0.Y + u * (vert1.Y - vert0.Y) + v * (vert2.Y - vert0.Y), vert0.Z + u * (vert1.Z - vert0.Z) + v * (vert2.Z - vert0.Z)); return true; }