using UnityEngine; using System.Collections; namespace Obi { public static class ObiMeshUtils { // Temporary vector3 values static Vector3 tv1, tv2, tv3, tv4; public static bool RayIntersectsTriangle(Vector3 origin, Vector3 dir, Vector3 vert0, Vector3 vert1, Vector3 vert2, ref float distance, ref Vector3 normal) { float det; ObiVectorMath.Subtract(vert0, vert1, ref tv1); ObiVectorMath.Subtract(vert0, vert2, ref tv2); ObiVectorMath.Cross(dir, tv2, ref tv4); det = Vector3.Dot(tv1, tv4); if (det < Mathf.Epsilon) return false; ObiVectorMath.Subtract(vert0, origin, ref tv3); float u = Vector3.Dot(tv3, tv4); if (u < 0f || u > det) return false; ObiVectorMath.Cross(tv3, tv1, ref tv4); float v = Vector3.Dot(dir, tv4); if (v < 0f || u + v > det) return false; distance = Vector3.Dot(tv2, tv4) * (1f / det); ObiVectorMath.Cross(tv1, tv2, ref normal); return true; } 
 /**
 * Find the nearest triangle intersected by InWorldRay on this mesh. InWorldRay is in world space.
 * @hit contains information about the hit point. @distance limits how far from @InWorldRay.origin the hit
 * point may be. @cullingMode determines what face orientations are tested (Culling.Front only tests front
 * faces, Culling.Back only tests back faces, and Culling.FrontBack tests both).
 * Ray origin and position values are in local space.
 */
 public static bool WorldRaycast(Ray InWorldRay, Matrix4x4 transform, Vector3[] vertices, int[] triangles, out ObiRaycastHit hit, float distance = Mathf.Infinity)
 { Ray ray = InWorldRay; if (transform != null) { Matrix4x4 inv = transform.inverse; ray.origin = inv.MultiplyPoint3x4(ray.origin); ray.direction = inv.MultiplyVector(ray.direction); }
 return MeshRaycast(ray, vertices, triangles, out hit, distance);
 }

 /**
 * Cast a ray (in model space) against a mesh.
 */
 public static bool MeshRaycast(Ray InRay, Vector3[] vertices, int[] triangles, out ObiRaycastHit hit, float distance = Mathf.Infinity)
 { Vector3 hitNormal = Vector3.zero; // vars used in loop Vector3 vert0, vert1, vert2; Vector3 origin = InRay.origin, direction = InRay.direction; hit = new ObiRaycastHit(Mathf.Infinity, Vector3.zero, Vector3.zero, -1); /** * Iterate faces, testing for nearest hit to ray origin. */ for (int CurTri = 0; CurTri < triangles.Length; CurTri += 3) { if (CurTri + 2 >= triangles.Length) continue; if (triangles[CurTri + 2] >= vertices.Length) continue; vert0 = vertices[triangles[CurTri + 0]]; vert1 = vertices[triangles[CurTri + 1]]; vert2 = vertices[triangles[CurTri + 2]]; // Second pass, test intersection with triangle if (RayIntersectsTriangle(origin, direction, vert0, vert1, vert2, ref distance, ref hitNormal)) { if (distance < hit.distance) { hit.distance = distance; hit.triangle = CurTri / 3; hit.position = InRay.GetPoint(hit.distance); hit.normal = hitNormal; } } } return hit.triangle > -1;
 } } }