/// <summary> /// Performs a raycast against the mesh triangles and returns info /// about the closest hit or null if no triangle was hit by the ray. /// </summary> /// <param name="meshTransform"> /// The mesh transform which brings the mesh in the same space as the /// ray. /// </param> /// <remarks> /// This method will build the tree if it hasn't already been built. /// </remarks> public MeshRayHit RaycastClosest(Ray ray, Matrix4x4 meshTransform) { // Build the tree if it hasn't already been built if (!_isBuilt) { Build(); } // Work in mesh local space by transforming the ray by the inverse of // the mesh transform. It is faster to perform this transformation here // instead of transforming every possibly hit triangle by 'meshTransform'. Ray modelSpaceRay = ray.InverseTransform(meshTransform); // Get the list of tree nodes which are hit by the ray List <SphereTreeNodeRayHit <MeshTriangle> > nodeHits = _tree.RaycastAll(modelSpaceRay); if (nodeHits.Count == 0) { return(null); } // Store data in preparation for closest hit identification float t; float minT = float.MaxValue; MeshTriangle closestTriangle = null; bool foundTriangle = false; // Loop through each node hit foreach (SphereTreeNodeRayHit <MeshTriangle> nodeHit in nodeHits) { // Get the associated mesh triangle and check if the ray intersects it MeshTriangle meshTriangle = nodeHit.HitNode.Data; if (TriangleMath.Raycast(modelSpaceRay, out t, meshTriangle.Vertex0, meshTriangle.Vertex1, meshTriangle.Vertex2)) { if (Vector3.Dot(modelSpaceRay.direction, meshTriangle.Normal) < 0.0f) { // If the intersection offset is smaller than what we have so far, // it means we have a new closest hit. if (t < minT) { minT = t; closestTriangle = meshTriangle; foundTriangle = true; } } } } // If we found a triangle, we can return the mesh ray hit information if (foundTriangle) { // Convert the t value in world space. Do the same for the normal. Vector3 worldHit = meshTransform.MultiplyPoint(modelSpaceRay.GetPoint(minT)); minT = (ray.origin - worldHit).magnitude / ray.direction.magnitude; Vector3 transformedNormal = meshTransform.inverse.transpose.MultiplyVector(closestTriangle.Normal).normalized; // Return the hit instance return(new MeshRayHit(ray, closestTriangle.TriangleIndex, minT, transformedNormal)); } return(null); }