/** * Find the nearest triangle intersected by InWorldRay on this pb_Object. 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). */ public static bool MeshRaycast(Ray InWorldRay, qe_Mesh mesh, out qe_RaycastHit hit, float distance, Culling cullingMode) { /** * Transform ray into model space */ InWorldRay.origin -= mesh.transform.position; // Why doesn't worldToLocalMatrix apply translation? InWorldRay.origin = mesh.transform.worldToLocalMatrix * InWorldRay.origin; InWorldRay.direction = mesh.transform.worldToLocalMatrix * InWorldRay.direction; Vector3[] vertices = mesh.vertices; float dist = 0f; Vector3 point = Vector3.zero; float OutHitPoint = Mathf.Infinity; float dot; // vars used in loop Vector3 nrm; // vars used in loop int OutHitFace = -1; Vector3 OutNrm = Vector3.zero; /** * Iterate faces, testing for nearest hit to ray origin. Optionally ignores backfaces. */ for(int CurFace = 0; CurFace < mesh.faces.Length; ++CurFace) { int[] Indices = mesh.faces[CurFace].indices; for(int CurTriangle = 0; CurTriangle < Indices.Length; CurTriangle += 3) { Vector3 a = vertices[Indices[CurTriangle+0]]; Vector3 b = vertices[Indices[CurTriangle+1]]; Vector3 c = vertices[Indices[CurTriangle+2]]; nrm = Vector3.Cross(b-a, c-a); dot = Vector3.Dot(InWorldRay.direction, nrm); bool ignore = false; switch(cullingMode) { case Culling.Front: if(dot > 0f) ignore = true; break; case Culling.Back: if(dot < 0f) ignore = true; break; } if(!ignore && qe_Math.RayIntersectsTriangle(InWorldRay, a, b, c, out dist, out point)) { if(dist > OutHitPoint || dist > distance) continue; OutNrm = nrm; OutHitFace = CurFace; OutHitPoint = dist; continue; } } } hit = new qe_RaycastHit(OutHitPoint, InWorldRay.GetPoint(OutHitPoint), OutNrm, OutHitFace); return OutHitFace > -1; }
/** * Find a triangle intersected by InRay on InMesh. InRay is in world space. * Returns the index in mesh.faces of the hit face, or -1. Optionally can ignore * backfaces. */ public static bool MeshRaycast(Ray InWorldRay, qe_Mesh mesh, out qe_RaycastHit hit) { return(MeshRaycast(InWorldRay, mesh, out hit, Mathf.Infinity, Culling.Front)); }
/** * Find a triangle intersected by InRay on InMesh. InRay is in world space. * Returns the index in mesh.faces of the hit face, or -1. Optionally can ignore * backfaces. */ public static bool MeshRaycast(Ray InWorldRay, qe_Mesh mesh, out qe_RaycastHit hit) { return MeshRaycast(InWorldRay, mesh, out hit, Mathf.Infinity, Culling.Front); }
/** * Find the nearest triangle intersected by InWorldRay on this pb_Object. 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). */ public static bool MeshRaycast(Ray InWorldRay, qe_Mesh mesh, out qe_RaycastHit hit, float distance, Culling cullingMode) { /** * Transform ray into model space */ InWorldRay.origin -= mesh.transform.position; // Why doesn't worldToLocalMatrix apply translation? InWorldRay.origin = mesh.transform.worldToLocalMatrix * InWorldRay.origin; InWorldRay.direction = mesh.transform.worldToLocalMatrix * InWorldRay.direction; Vector3[] vertices = mesh.vertices; float dist = 0f; Vector3 point = Vector3.zero; float OutHitPoint = Mathf.Infinity; float dot; // vars used in loop Vector3 nrm; // vars used in loop int OutHitFace = -1; Vector3 OutNrm = Vector3.zero; /** * Iterate faces, testing for nearest hit to ray origin. Optionally ignores backfaces. */ for (int CurFace = 0; CurFace < mesh.faces.Length; ++CurFace) { int[] Indices = mesh.faces[CurFace].indices; for (int CurTriangle = 0; CurTriangle < Indices.Length; CurTriangle += 3) { Vector3 a = vertices[Indices[CurTriangle + 0]]; Vector3 b = vertices[Indices[CurTriangle + 1]]; Vector3 c = vertices[Indices[CurTriangle + 2]]; nrm = Vector3.Cross(b - a, c - a); dot = Vector3.Dot(InWorldRay.direction, nrm); bool ignore = false; switch (cullingMode) { case Culling.Front: if (dot > 0f) { ignore = true; } break; case Culling.Back: if (dot < 0f) { ignore = true; } break; } if (!ignore && qe_Math.RayIntersectsTriangle(InWorldRay, a, b, c, out dist, out point)) { if (dist > OutHitPoint || dist > distance) { continue; } OutNrm = nrm; OutHitFace = CurFace; OutHitPoint = dist; continue; } } } hit = new qe_RaycastHit(OutHitPoint, InWorldRay.GetPoint(OutHitPoint), OutNrm, OutHitFace); return(OutHitFace > -1); }