Exemple #1
0
        /// <summary>
        /// Given a local edge, this guarantees that both indexes belong to the same face.
        /// Note that this will only return the first valid edge found - there will usually
        /// be multiple matches (well, 2 if your geometry is sane).
        /// </summary>
        /// <param name="mesh"></param>
        /// <param name="edge"></param>
        /// <param name="validEdge"></param>
        /// <returns></returns>
        public static bool ValidateEdge(ProBuilderMesh mesh, Edge edge, out SimpleTuple <Face, Edge> validEdge)
        {
            Face[]         faces         = mesh.facesInternal;
            SharedVertex[] sharedIndexes = mesh.sharedVerticesInternal;

            Edge universal = GetSharedVertexHandleEdge(mesh, edge);

            for (int i = 0; i < faces.Length; i++)
            {
                int dist_x   = -1,
                    dist_y   = -1,
                    shared_x = -1,
                    shared_y = -1;

                if (faces[i].distinctIndexesInternal.ContainsMatch(sharedIndexes[universal.a].arrayInternal, out dist_x, out shared_x) &&
                    faces[i].distinctIndexesInternal.ContainsMatch(sharedIndexes[universal.b].arrayInternal, out dist_y, out shared_y))
                {
                    int x = faces[i].distinctIndexesInternal[dist_x];
                    int y = faces[i].distinctIndexesInternal[dist_y];

                    validEdge = new SimpleTuple <Face, Edge>(faces[i], new Edge(x, y));
                    return(true);
                }
            }

            validEdge = new SimpleTuple <Face, Edge>();

            return(false);
        }
        internal static bool FaceRaycastBothCullModes(Ray worldRay, ProBuilderMesh mesh, ref SimpleTuple <Face, Vector3> back, ref SimpleTuple <Face, Vector3> front)
        {
            // Transform ray into model space
            worldRay.origin   -= mesh.transform.position; // Why doesn't worldToLocalMatrix apply translation?
            worldRay.origin    = mesh.transform.worldToLocalMatrix * worldRay.origin;
            worldRay.direction = mesh.transform.worldToLocalMatrix * worldRay.direction;

            var positions = mesh.positionsInternal;
            var faces     = mesh.facesInternal;

            back.item1  = null;
            front.item1 = null;

            float backDistance  = Mathf.Infinity;
            float frontDistance = Mathf.Infinity;

            // Iterate faces, testing for nearest hit to ray origin. Optionally ignores backfaces.
            for (int i = 0, fc = faces.Length; i < fc; ++i)
            {
                int[] indexes = mesh.facesInternal[i].indexesInternal;

                for (int j = 0, ic = indexes.Length; j < ic; j += 3)
                {
                    Vector3 a = positions[indexes[j + 0]];
                    Vector3 b = positions[indexes[j + 1]];
                    Vector3 c = positions[indexes[j + 2]];

                    float   dist;
                    Vector3 point;

                    if (Math.RayIntersectsTriangle(worldRay, a, b, c, out dist, out point))
                    {
                        if (dist < backDistance || dist < frontDistance)
                        {
                            Vector3 nrm = Vector3.Cross(b - a, c - a);
                            float   dot = Vector3.Dot(worldRay.direction, nrm);

                            if (dot < 0f)
                            {
                                if (dist < backDistance)
                                {
                                    backDistance = dist;
                                    back.item1   = faces[i];
                                }
                            }
                            else
                            {
                                if (dist < frontDistance)
                                {
                                    frontDistance = dist;
                                    front.item1   = faces[i];
                                }
                            }
                        }
                    }
                }
            }

            if (back.item1 != null)
            {
                back.item2 = worldRay.GetPoint(backDistance);
            }

            if (front.item1 != null)
            {
                front.item2 = worldRay.GetPoint(frontDistance);
            }

            return(back.item1 != null || front.item1 != null);
        }