/// <summary> /// Test single triangle given ray in same coordinate system as the vertices and normal. /// </summary> /// <param name="ray">Ray in same coordinate system as the vertices and normal.</param> /// <param name="rayLength">Length of the ray.</param> /// <param name="triangleIndex">Triangle index of current triangle.</param> /// <param name="v1">First vertex.</param> /// <param name="v2">Second vertex.</param> /// <param name="v3">Third vertex.</param> /// <param name="normal">Normal of the triangle.</param> /// <returns>Local result of test.</returns> public static TriangleTestResult TestTriangle(Ray ray, float rayLength, int triangleIndex, Vector3 v1, Vector3 v2, Vector3 v3, Vector3 normal) { TriangleTestResult result = new TriangleTestResult() { Normal = normal, TriangleIndex = triangleIndex }; result.Hit = IntersectRayTriangle(ray, rayLength, v1, v2, v3, normal, ref result.PointInTriangle, ref result.Time); return(result); }
/// <summary> /// Test all triangles in a mesh to find the first triangle that intersects the ray. /// </summary> /// <param name="worldRay">Ray given in world coordinates (e.g., HandleUtility.GUIPointToWorldRay( Event.current.mousePosition )).</param> /// <param name="rayLength">Length of the ray.</param> /// <param name="mesh">The mesh.</param> /// <param name="parent">Parent game object that transforms the mesh.</param> /// <returns>Result of the test.</returns> public static Raycast.TriangleHit TestAllTriangles(Ray worldRay, float rayLength, UnityEngine.Mesh mesh, GameObject parent) { if (mesh == null || parent == null) { return(Raycast.TriangleHit.Invalid); } // Mesh bounds are in local coordinates - transform ray to local. Ray localRay = new Ray(parent.transform.InverseTransformPoint(worldRay.origin), parent.transform.InverseTransformVector(worldRay.direction).normalized); if (!mesh.bounds.IntersectRay(localRay)) { return(Raycast.TriangleHit.Invalid); } int[] triangles = mesh.triangles; Vector3[] vertices = mesh.vertices; TriangleTestResult testResult = new TriangleTestResult(); for (int i = 0; i < triangles.Length; i += 3) { Vector3 v1 = vertices[triangles[i + 0]]; Vector3 v2 = vertices[triangles[i + 1]]; Vector3 v3 = vertices[triangles[i + 2]]; Vector3 normal = Vector3.Cross(v2 - v1, v3 - v1).normalized; TriangleTestResult test = TestTriangle(localRay, rayLength, i, v1, v2, v3, normal); if (test.Hit && test.Time < testResult.Time) { testResult = test; } } if (!testResult.Hit) { return(Raycast.TriangleHit.Invalid); } Vector3 worldIntersectionPoint = parent.transform.TransformPoint(testResult.PointInTriangle); return(new Raycast.TriangleHit() { Target = parent, Vertices = new Vector3[] { parent.transform.TransformPoint(vertices[triangles[testResult.TriangleIndex + 0]]), parent.transform.TransformPoint(vertices[triangles[testResult.TriangleIndex + 1]]), parent.transform.TransformPoint(vertices[triangles[testResult.TriangleIndex + 2]]) }, Point = worldIntersectionPoint, Normal = parent.transform.TransformDirection(testResult.Normal), Distance = Vector3.Distance(worldRay.GetPoint(0), worldIntersectionPoint) }); }