Exemple #1
0
        public static int DecimateVertices(int targetFaces, ref MinHeap <MeshPairContraction> pairContractions, ref Vector3[] verts, ref MeshIndexTriangle[] indexTris, ref List <int>[] trisAttachedToVerts, ref Quadric[] vertQuadrics)
        {
            int           validFaces = indexTris.Length;
            int           counter    = 1;
            StringBuilder debug      = new StringBuilder();

            debug.AppendLine("Target Faces: " + targetFaces);
            try
            {
                while (validFaces > targetFaces)
                {
                    debug.AppendLine("Iteration: " + counter + " Faces: " + validFaces);

                    //Get the pair contraction with the least error associated with it
                    MeshPairContraction pair = pairContractions.ExtractDominating();

                    debug.AppendLine("Contraction between vertices at indicies: " + pair.v0 + " and " + pair.v1);
                    debug.AppendLine("Tris attached to v0: " + trisAttachedToVerts[pair.v0].Count + " Tris attached to v1: " + trisAttachedToVerts[pair.v1].Count);

                    //Get faces that will be deleted / changed by contraction
                    ComputeContraction(ref pair, indexTris, trisAttachedToVerts);

                    //Act on faces, delete extra vertex, change all references to second vertex
                    validFaces -= ApplyContraction(ref pair, ref pairContractions, ref verts, ref indexTris, ref trisAttachedToVerts, ref vertQuadrics);

                    counter++;
                }
                for (int i = 0; i < indexTris.Length; i++)
                {
                    MeshIndexTriangle tri = indexTris[i];
                    if (tri == null)
                    {
                        continue;
                    }
                    if (trisAttachedToVerts[tri.v0] == null)
                    {
                        debug.AppendLine("Tri at index " + i + " points to nonexistent vertex at index " + tri.v0);
                    }
                    if (trisAttachedToVerts[tri.v1] == null)
                    {
                        debug.AppendLine("Tri at index " + i + " points to nonexistent vertex at index " + tri.v1);
                    }
                    if (trisAttachedToVerts[tri.v2] == null)
                    {
                        debug.AppendLine("Tri at index " + i + " points to nonexistent vertex at index " + tri.v2);
                    }
                }

                debug.AppendLine("Final: Faces: " + validFaces);
            }
            catch (Exception e)
            {
                debug.AppendLine("Error: " + e.Message);
                debug.AppendLine("Stack trace");
                debug.AppendLine(e.StackTrace);
            }


            Debug.Log(debug.ToString());
            return(validFaces);
        }
Exemple #2
0
        public static int ApplyContraction(ref MeshPairContraction pair, ref MinHeap <MeshPairContraction> pairContractions, ref Vector3[] verts, ref MeshIndexTriangle[] indexTris, ref List <int>[] trisAttachedToVerts, ref Quadric[] vertQuadrics)
        {
            int removedFaces = pair.deletedFaces.Count;

            //Move v0, clear v1
            verts[pair.v0] = pair.contractedPosition;
            verts[pair.v1] = Vector3.zero;

            foreach (int triIndex in trisAttachedToVerts[pair.v1])
            {
                if (!pair.deletedFaces.Contains(triIndex) && !trisAttachedToVerts[pair.v0].Contains(triIndex))
                {
                    trisAttachedToVerts[pair.v0].Add(triIndex);
                }
            }

            //Clear out all the tris attached to a non-existent vertex
            trisAttachedToVerts[pair.v1] = null;

            //Accumulate quadrics, clear unused one
            vertQuadrics[pair.v0] += vertQuadrics[pair.v1];
            vertQuadrics[pair.v1]  = new Quadric();

            //Adjust deformed triangles
            foreach (int changedTri in pair.deformedFaces)
            {
                MeshIndexTriangle tri = indexTris[changedTri];
                if (tri.v0.Equals(pair.v1))
                {
                    tri.v0 = pair.v0;
                }
                else if (tri.v1.Equals(pair.v1))
                {
                    tri.v1 = pair.v0;
                }
                else
                {
                    tri.v2 = pair.v0;
                }

                indexTris[changedTri] = tri;
            }

            //Clear deleted triangles
            foreach (int deletedTri in pair.deletedFaces)
            {
                indexTris[deletedTri] = null;
            }

            List <MeshPairContraction> pairList = pairContractions.ToList();

            for (int i = 0; i < pairContractions.Count; i++)
            {
                MeshPairContraction otherPair = pairList[i];
                if (otherPair.v0.Equals(pair.v1))
                {
                    otherPair.v0 = pair.v0;
                }
                else if (otherPair.v1.Equals(pair.v1))
                {
                    otherPair.v1 = pair.v0;
                }
                pairList[i] = otherPair;
            }

            int count = pairList.Count;

            for (int i = 0; i < count; i++)
            {
                MeshPairContraction iItem = pairList[i];
                for (int j = i + 1; j < count; j++)
                {
                    if (pairList[j].Equals(iItem))
                    {
                        pairList.RemoveAt(j);   //Remove duplicate element
                        count--;                //Reduce length to iterate over
                        j--;                    //Make sure not to skip over a duplicate
                    }
                }
                if (iItem.v1 == iItem.v0)
                {
                    pairList.RemoveAt(i);   //Remove degenerate edge
                    count--;                //Reduce length to iterate over
                    i--;                    //Make sure not to skip over a duplicate
                    continue;
                }
                CalculateTargetPositionForPairContraction(ref iItem, verts, vertQuadrics);
                pairList[i] = iItem;
            }

            pairContractions = new MinHeap <MeshPairContraction>(pairList);

            return(removedFaces);
        }