예제 #1
0
        public static float CalculateMinTriangleShape(BaseMesh mesh)
        {
            int faceCount = mesh.faceCount();

            Vector3[] tr       = new Vector3[3];
            float     minShape = 10.0f;

            for (int i = 0; i < faceCount; ++i)
            {
                Face f = mesh.faces[i];
                if (f.valid)
                {
                    for (int j = 0; j < 3; ++j)
                    {
                        tr[j] = mesh.vertices[f.v[j]].coords;
                    }
                    float val = KrablMesh.UnityUtils.TriangleCompactnessSqr(tr);
                    if (val < minShape)
                    {
                        minShape = val;
                    }
                }
            }
            return(minShape);
        }
예제 #2
0
        bool _producesNonManifold(BaseMesh mesh, CollapseInfo ci)
        {
            // ... If v0 and v1 don't have nr of commonfaces common neighbours
            List <Vertex> vertices = mesh.vertices;
            List <Face>   faces    = mesh.faces;
            int           common   = commonFaces.Count;
            int           tag      = mesh.GetUniqueTag();

            int count = faces0.Count;

            int[] faceArray = faces0.array;
            for (int i = 0; i < count; ++i)
            {
                int[] v = faces[faceArray[i]].v;
                // known to be a valid triangle
                vertices[v[0]].mark = tag;
                vertices[v[1]].mark = tag;
                vertices[v[2]].mark = tag;
            }
            count     = faces1.Count;
            faceArray = faces1.array;
            for (int i = 0; i < count; ++i)
            {
                int[] v = faces[faceArray[i]].v;
                if (vertices[v[0]].mark == tag)
                {
                    common--; if (common < 0)
                    {
                        return(true);
                    }
                    vertices[v[0]].mark = 0;
                }
                if (vertices[v[1]].mark == tag)
                {
                    common--; if (common < 0)
                    {
                        return(true);
                    }
                    vertices[v[1]].mark = 0;
                }
                if (vertices[v[2]].mark == tag)
                {
                    common--; if (common < 0)
                    {
                        return(true);
                    }
                    vertices[v[2]].mark = 0;
                }
            }

            return(common != 0);
        }
예제 #3
0
        /*
         * NOT USED. the badtopology test is faster & better
         *
         * bool _producesInvertedFaces(BaseMesh mesh, CollapseInfo ci) {
         *      Vector3[] tr = new Vector3[3];
         *      for (int k = 0; k < 2; ++k) {
         *              int vindex = ci.vp.v[k];
         *              List<int> linkedFaces = (k == 0) ? faces0 : faces1;
         *              for (int i = 0; i < linkedFaces.Count; ++i) {
         *                      Face f = mesh.faces[linkedFaces[i]];
         *                      Vector3 oldN = mesh.CalculateFaceNormal(linkedFaces[i]);
         *                      if (f.v[0] == vindex)       { tr[0] = ci.targetPosition;            tr[1] = mesh.vertex(f.v[1]).coords; tr[2] = mesh.vertex(f.v[2]).coords; }
         *                      else if (f.v[1] == vindex)  { tr[0] = mesh.vertex(f.v[0]).coords;   tr[1] = ci.targetPosition;          tr[2] = mesh.vertex(f.v[2]).coords; }
         *                      else                        { tr[0] = mesh.vertex(f.v[0]).coords;   tr[1] = mesh.vertex(f.v[1]).coords;	tr[2] = ci.targetPosition;          }
         *                      Vector3 newN = Vector3.Cross(tr[1] - tr[0], tr[2] - tr[1]);
         *                      if (Vector3.Dot(oldN, newN) < 0.0f) {
         *                              return true;
         *                      }
         *              }
         *      }
         *      return false;
         * }*/

        float _determineMeshSize(BaseMesh mesh)
        {
            Vector3 min      = mesh.vertices[0].coords;
            Vector3 max      = min;
            int     numVerts = mesh.vertCount();

            for (int i = 0; i < numVerts; ++i)
            {
                Vector3 c = mesh.vertices[i].coords;
                if (c.x < min.x)
                {
                    min.x = c.x;
                }
                else if (c.x > max.x)
                {
                    max.x = c.x;
                }
                if (c.y < min.y)
                {
                    min.y = c.y;
                }
                else if (c.y > max.y)
                {
                    max.y = c.y;
                }
                if (c.z < min.z)
                {
                    min.z = c.z;
                }
                else if (c.z > max.z)
                {
                    max.z = c.z;
                }
            }
            max -= min;
            float result = max.x;

            if (max.y > meshSize)
            {
                meshSize = max.y;
            }
            if (max.z > meshSize)
            {
                meshSize = max.z;
            }
            return(result);
        }
예제 #4
0
        //Vector3[] tr = new Vector3[3];

        /*
         * // rchecks result triangles against limit
         * bool _producesSharpTriangles(Mesh mesh, CollapseInfo ci, float limitSqr) {
         *      for (int k = 0; k < 2; ++k) {
         *              int vindex = ci.vp.v[k];
         *              List<int> linkedFaces = (k == 0) ? faces0 : faces1;
         *              for (int i = 0; i < linkedFaces.Count; ++i) {
         *                      Face f = mesh.faces[linkedFaces[i]];
         *                      if (f.v[0] == vindex)       { tr[0] = ci.targetPosition;            tr[1] = mesh.vertex(f.v[1]).coords; tr[2] = mesh.vertex(f.v[2]).coords; }
         *                      else if (f.v[1] == vindex)  { tr[0] = mesh.vertex(f.v[0]).coords;   tr[1] = ci.targetPosition;          tr[2] = mesh.vertex(f.v[2]).coords; }
         *                      else                        { tr[0] = mesh.vertex(f.v[0]).coords;   tr[1] = mesh.vertex(f.v[1]).coords;	tr[2] = ci.targetPosition;          }
         *                      float val = UnityUtils.TriangleCompactnessSqr(tr);
         *                      if (val < limitSqr) return true;
         *              }
         *      }
         *      return false;
         * }
         */

        // Check topology to avoid flipping the mesh by collapsing
        bool _producesBadTopology(BaseMesh mesh, CollapseInfo ci, int filterTag = 0)
        {
            Vector3       p1, origPos, vOpp, faceNormal, normal;
            List <Vertex> vertices = mesh.vertices;
            List <Face>   faces    = mesh.faces;

            for (int k = 0; k < 2; ++k)
            {
                int vindex = ci.vp.v[k];
                origPos = vertices[vindex].coords;
                IndexList linkedFacesList = (k == 0) ? faces0 : faces1;
                int[]     linkedFaces     = linkedFacesList.array;
                for (int i = 0; i < linkedFacesList.Count; ++i)
                {
                    Face f = faces[linkedFaces[i]];
                    if (f.mark >= filterTag)
                    {
                        // Construct a plane from opposing sides (p1->p2) && the face normal -> todo make this better (faster)
                        if (f.v[0] == vindex)
                        {
                            p1   = vertices[f.v[1]].coords;
                            vOpp = vertices[f.v[2]].coords - p1;
                        }
                        else if (f.v[1] == vindex)
                        {
                            p1   = vertices[f.v[2]].coords;
                            vOpp = vertices[f.v[0]].coords - p1;
                        }
                        else
                        {
                            p1   = vertices[f.v[0]].coords;
                            vOpp = vertices[f.v[1]].coords - p1;
                        }

                        faceNormal = Vector3.Cross(vOpp, origPos - p1);                   // the face normal
                        normal     = Vector3.Cross(faceNormal, vOpp);                     // normal of constructed plane
                        if (Vector3.Dot(ci.targetPosition - p1, normal) < 0.0f)
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
예제 #5
0
        /// <summary>
        /// Joins vertices in a mesh that have the same geometric location based on the mesh's
        /// equalityTolerance parameter which is set when a mesh is create (it's usually zero.)
        /// </summary>
        /// <param name='mesh'>
        /// The mesh to search for duplicate vertices.
        /// </param>
        public static void RemoveDoubleVertices(BaseMesh mesh)
        {
            int numVerts = mesh.vertCount();

            List <int> vertexOrder = new List <int>(numVerts);

            for (int i = 0; i < numVerts; ++i)
            {
                vertexOrder.Add(i);
            }

            vertexOrder.Sort(delegate(int a, int b) {
                return(mesh.CompareVertices(a, b, mesh.equalityTolerance));
            });

            int[] uniqueVertex = new int[numVerts];
            int   unique       = vertexOrder[0];

            uniqueVertex[unique] = unique;
            for (int i = 1; i < numVerts; ++i)
            {
                int vertexIndex = vertexOrder[i];
                if (mesh.CompareVertices(unique, vertexIndex, mesh.equalityTolerance) != 0)
                {
                    unique = vertexIndex;
                }
                uniqueVertex[vertexIndex] = unique;
            }
            // TODO: maybe use the center of all the almost equal vertices .. probably does not matter
            for (int i = 0; i < numVerts; ++i)
            {
                if (i != uniqueVertex[i])
                {
                    mesh.ReplaceVertex(i, uniqueVertex[i]);
                }
            }
            /* int num = */ mesh.InvalidateUnconnectedVertices();
            //Debug.Log("RemoveDoubleVertices Invalidated " + num + " unconnected vertices.");
            /*num = */ mesh.InvalidateDegenerateFaces();
            // Debug.Log("RemoveDoubleVertices Invalidated " + num + " degenerate faces.");
        }
예제 #6
0
        public float cost;                 // Total cose including penalties

        public float Ratio(BaseMesh m)
        {
            return(KrablMesh.UnityUtils.ProjectedRatioOfPointOnVector(targetPosition, m.vertices[vp.v[0]].coords, m.vertices[vp.v[1]].coords));
        }
예제 #7
0
        public static void Triangulate(BaseMesh mesh)
        {
            if (mesh.topology == MeshTopology.Triangles)
            {
                return;
            }

            int faceIndex, cornerIndex;

            int numFaces = mesh.faceCount();

            Vector3[] coords = new Vector3[4];
            for (faceIndex = 0; faceIndex < numFaces; ++faceIndex)
            {
                Face f = mesh.faces[faceIndex];
                if (f.valid && f.cornerCount == 4)
                {
                    Face fnew = new Face(3);
                    // copy face parameters
                    fnew.material = f.material;
                    for (cornerIndex = 0; cornerIndex < 4; ++cornerIndex)
                    {
                        coords[cornerIndex] = mesh.vertices[f.v[cornerIndex]].coords;
                    }

                    Vector3 diag02 = coords[0] - coords[2];
                    Vector3 diag13 = coords[1] - coords[3];
                    if (diag02.sqrMagnitude < diag13.sqrMagnitude)
                    {
                        // Create triangles 201 and 023 .. use diag as first edge as a hint
                        fnew.CopyVertexInfoFromFace(f, 0, 0);
                        fnew.CopyVertexInfoFromFace(f, 2, 1);
                        fnew.CopyVertexInfoFromFace(f, 3, 2);
                    }
                    else
                    {
                        // Create triangles 312 and 013 .. use diag as first edge as a hint
                        fnew.CopyVertexInfoFromFace(f, 3, 0);
                        fnew.CopyVertexInfoFromFace(f, 1, 1);
                        fnew.CopyVertexInfoFromFace(f, 2, 2);
                        f.CopyVertexInfoFromFace(f, 3, 2);
                    }
                    mesh.AddFace(fnew);
                    // First face needs to become a triangle
                    f.cornerCount = 3;
                }
            }
            // Rebuild linkedFaces for Verts
            int numVerts = mesh.vertCount();

            for (int vertIndex = 0; vertIndex < numVerts; ++vertIndex)
            {
                mesh.vertices[vertIndex].linkedFaces = new IndexList(18);
            }
            numFaces = mesh.faceCount();

            for (faceIndex = 0; faceIndex < numFaces; ++faceIndex)
            {
                Face f = mesh.faces[faceIndex];
                for (cornerIndex = 0; cornerIndex < f.cornerCount; ++cornerIndex)
                {
                    mesh.vertices[f.v[cornerIndex]].linkedFaces.Add(faceIndex);
                }
            }
            mesh.topology = MeshTopology.Triangles;
        }
예제 #8
0
 // Count number of surrounding faces after the collapse
 int _vertexDegreeAfterCollapse(BaseMesh mesh, CollapseInfo ci)
 {
     return(faces0.Count + faces1.Count);
 }