/**
         * 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;
        }
Пример #2
0
 /**
  * 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);
 }
Пример #4
0
        /**
         * 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);
        }