Beispiel #1
0
        internal void UpdatePreContract(MxPairContraction conx)
        {
            var v1 = conx.VertId1;
            var v2 = conx.VertId2;

            var star = new List <int>();

            foreach (var edge in edgeLinks[v1])
            {
                star.Add(edge.OppositeVertex(v1));
            }

            foreach (var edge in edgeLinks[v2])
            {
                var vertU = (edge.V1 == v2) ? edge.V2 : edge.V1;
                Debug.Assert(edge.V1 == v2 || edge.V2 == v2);
                Debug.Assert(vertU != v2);

                if (vertU == v1 || star.Contains(vertU))
                {
                    edgeLinks[vertU].Remove(edge);
                    heap.RemoveItem(edge);
                }
                else
                {
                    edge.V1 = v1;
                    edge.V2 = vertU;
                    edgeLinks[v1].Add(edge);
                }
            }

            edgeLinks[v2].Clear();
        }
Beispiel #2
0
        internal void ComputeContraction(int vertId1, int vertId2, MxPairContraction conx, double[] newVert)
        {
            conx.VertId1 = vertId1;
            conx.VertId2 = vertId2;

            if (newVert != null)
            {
                MxVectorOps.Sub3(ref conx.DeltaV1, newVert, Vertex(vertId1).Pos);
                MxVectorOps.Sub3(ref conx.DeltaV2, newVert, Vertex(vertId2).Pos);
            }
            else
            {
                conx.DeltaV1 = new[] { 0.0, 0.0, 0.0 };
                conx.DeltaV2 = new[] { 0.0, 0.0, 0.0 };
            }

            conx.DeltaFaces.Clear();
            conx.DeadFaces.Clear();

            MarkNeighborhood(vertId2, 0x0);
            MarkNeighborhood(vertId1, 0x1);
            MarkNeighborhoodDelta(vertId2, 0x1);

            PartitionMarkedNeighbors(vertId1, 0x2, conx.DeltaFaces, conx.DeadFaces);
            conx.DeltaPivot = conx.DeltaFaces.Count;
            PartitionMarkedNeighbors(vertId2, 0x2, conx.DeltaFaces, conx.DeadFaces);
        }
Beispiel #3
0
 internal void Contract(int vertId1, int vertId2, double[] newVert, MxPairContraction conx)
 {
     ComputeContraction(vertId1, vertId2, conx, null);
     MxVectorOps.Sub3(ref conx.DeltaV1, newVert, Vertex(vertId1).Pos);
     MxVectorOps.Sub3(ref conx.DeltaV2, newVert, Vertex(vertId2).Pos);
     ApplyContraction(conx);
 }
Beispiel #4
0
        internal void ApplyExpansion(MxPairContraction conx)
        {
            UpdatePreExpand(conx);

            model.ApplyExpansion(conx);
            ValidVerts++;
            ValidFaces             += conx.DeadFaces.Count;
            quadrics[conx.VertId1] -= quadrics[conx.VertId2];

            UpdatePostExpand(conx);
        }
Beispiel #5
0
        internal void ApplyExpansion(MxPairContraction conx)
        {
            UpdatePreExpand(conx);

            model.ApplyExpansion(conx);
            ValidVerts++;
            ValidFaces += conx.DeadFaces.Count;
            quadrics[conx.VertId1] -= quadrics[conx.VertId2];

            UpdatePostExpand(conx);
        }
Beispiel #6
0
        internal MxPairContraction(MxPairContraction contraction)
        {
            VertId1    = contraction.VertId1;
            VertId2    = contraction.VertId2;
            DeltaV1    = (double[])contraction.DeltaV1.Clone();
            DeltaV2    = (double[])contraction.DeltaV2.Clone();
            DeltaFaces = new List <int>(contraction.DeltaFaces);
            DeadFaces  = new List <int>(contraction.DeadFaces);

            DeltaPivot = contraction.DeltaPivot;
        }
Beispiel #7
0
        internal MxPairContraction(MxPairContraction contraction)
        {
            VertId1 = contraction.VertId1;
            VertId2 = contraction.VertId2;
            DeltaV1 = (double[])contraction.DeltaV1.Clone();
            DeltaV2 = (double[])contraction.DeltaV2.Clone();
            DeltaFaces = new List<int>(contraction.DeltaFaces);
            DeadFaces = new List<int>(contraction.DeadFaces);

            DeltaPivot = contraction.DeltaPivot;
        }
Beispiel #8
0
        internal void ApplyExpansion(MxPairContraction conx)
        {
            var vertId1 = conx.VertId1;
            var vertId2 = conx.VertId2;

            var newPos1 = new double[3];

            MxVectorOps.Sub3(ref newPos1, Vertex(vertId1).Pos, conx.DeltaV2);
            Vertex(vertId2).Pos = newPos1;

            var newPos2 = Vertex(vertId2).Pos;

            MxVectorOps.SubFrom3(ref newPos2, conx.DeltaV1);
            Vertex(vertId2).Pos = newPos2;

            foreach (var faceId in conx.DeadFaces)
            {
                FaceMarkValid(faceId);

                var face = Face(faceId);
                faceLinks[face[0]].Add(faceId);
                faceLinks[face[1]].Add(faceId);
                faceLinks[face[2]].Add(faceId);
            }

            for (var i = conx.DeltaPivot; i < conx.DeltaFaces.Count; i++)
            {
                var faceId = conx.DeltaFaces[i];
                var face   = Face(faceId);
                face.RemapVertex(vertId1, vertId2);
                faceLinks[vertId2].Add(faceId);
                faceLinks[vertId1].Remove(faceId);
            }

            if (NormalBinding == MxBinding.PerFace)
            {
                var nml = new double[3];
                foreach (var faceId in conx.DeltaFaces)
                {
                    ComputeFaceNormal(faceId, ref nml);
                    Normal(faceId, new MxNormal(nml));
                }

                foreach (var faceId in conx.DeadFaces)
                {
                    ComputeFaceNormal(faceId, ref nml);
                    Normal(faceId, new MxNormal(nml));
                }
            }

            VertexMarkValid(vertId2);
        }
Beispiel #9
0
        internal override bool Decimate(int target)
        {
            while (ValidFaces > target)
            {
                var info = heap.Extract() as MxQSlimEdge;
                if (info == null)
                {
                    return(false);
                }

                var v1 = info.V1;
                var v2 = info.V2;


                if (!model.VertexIsValid(v1) || !model.VertexIsValid(v2))
                {
                    continue;
                }

                var inversion = CheckLocalInversion(v1, info.vNew);
                if (inversion < 0.00)
                {
                    continue;
                }

                inversion = CheckLocalInversion(v2, info.vNew);
                if (inversion < 0.00)
                {
                    continue;
                }

                var conx = new MxPairContraction();
                model.ComputeContraction(v1, v2, conx, info.vNew);

                if (WillJoinOnly && conx.DeadFaces.Count > 0)
                {
                    continue;
                }


                var evt = Contracted;
                if (evt != null)
                {
                    evt(conx, -info.HeapKey);
                }

                ApplyContraction(conx);
            }

            return(true);
        }
Beispiel #10
0
        internal void ApplyExpansion(MxPairContraction conx)
        {
            var vertId1 = conx.VertId1;
            var vertId2 = conx.VertId2;

            var newPos1 = new double[3];
            MxVectorOps.Sub3(ref newPos1, Vertex(vertId1).Pos, conx.DeltaV2);
            Vertex(vertId2).Pos = newPos1;

            var newPos2 = Vertex(vertId2).Pos;
            MxVectorOps.SubFrom3(ref newPos2, conx.DeltaV1);
            Vertex(vertId2).Pos = newPos2;

            foreach (var faceId in conx.DeadFaces)
            {
                FaceMarkValid(faceId);

                var face = Face(faceId);
                faceLinks[face[0]].Add(faceId);
                faceLinks[face[1]].Add(faceId);
                faceLinks[face[2]].Add(faceId);
            }

            for (var i = conx.DeltaPivot; i < conx.DeltaFaces.Count; i++)
            {
                var faceId = conx.DeltaFaces[i];
                var face = Face(faceId);
                face.RemapVertex(vertId1, vertId2);
                faceLinks[vertId2].Add(faceId);
                faceLinks[vertId1].Remove(faceId);
            }

            if (NormalBinding == MxBinding.PerFace)
            {
                var nml = new double[3];
                foreach(var faceId in conx.DeltaFaces)
                {
                    ComputeFaceNormal(faceId, ref nml);
                    Normal(faceId, new MxNormal(nml));
                }

                foreach(var faceId in conx.DeadFaces)
                {
                    ComputeFaceNormal(faceId, ref nml);
                    Normal(faceId, new MxNormal(nml));
                }
            }

            VertexMarkValid(vertId2);
        }
Beispiel #11
0
        internal void ApplyContraction(MxPairContraction conx)
        {
            ValidVerts--;
            ValidFaces -= conx.DeadFaces.Count;
            quadrics[conx.VertId1] += quadrics[conx.VertId2];

            UpdatePreContract(conx);
            model.ApplyContraction(conx);
            UpdatePostContract(conx);

            foreach (var edge in edgeLinks[conx.VertId1])
            {
                ComputeEdgeInfo(edge);
            }
        }
Beispiel #12
0
        internal void ApplyContraction(MxPairContraction conx)
        {
            ValidVerts--;
            ValidFaces             -= conx.DeadFaces.Count;
            quadrics[conx.VertId1] += quadrics[conx.VertId2];

            UpdatePreContract(conx);
            model.ApplyContraction(conx);
            UpdatePostContract(conx);

            foreach (var edge in edgeLinks[conx.VertId1])
            {
                ComputeEdgeInfo(edge);
            }
        }
Beispiel #13
0
        internal void UpdatePostExpand(MxPairContraction conx)
        {
            var v1 = conx.VertId1;
            var v2 = conx.VertId2;

            var star  = new List <int>();
            var star2 = new List <int>();

            edgeLinks[conx.VertId2].Clear();
            model.CollectVertexStar(conx.VertId1, star);
            model.CollectVertexStar(conx.VertId2, star2);

            var i = 0;

            while (i < edgeLinks[v1].Count)
            {
                var edge  = edgeLinks[v1][i];
                var vertU = (edge.V1 == v1) ? edge.V2 : edge.V1;
                Debug.Assert(edge.V1 == v1 || edge.V2 == v1);
                Debug.Assert(vertU != v1 && vertU != v2);

                var v1Linked = star.Contains(vertU);
                var v2Linked = star2.Contains(vertU);

                if (v1Linked)
                {
                    if (v2Linked)
                    {
                        CreateEdge(v2, vertU);
                    }
                    i++;
                }
                else
                {
                    edge.V1 = v2;
                    edge.V2 = vertU;
                    edgeLinks[v2].Add(edge);
                    edgeLinks[v1].RemoveAt(i);
                }

                ComputeEdgeInfo(edge);
            }

            if (star.Contains(v2))
            {
                CreateEdge(v1, v2);
            }
        }
Beispiel #14
0
        internal void ApplyContraction(MxPairContraction conx)
        {
            var vertId1 = conx.VertId1;
            var vertId2 = conx.VertId2;

            // Move vert1 to new position
            var pos = Vertex(vertId1).Pos;

            MxVectorOps.AddInto3(ref pos, conx.DeltaV1);
            Vertex(vertId1).Pos = pos;

            // Remove dead faces
            foreach (var faceId in conx.DeadFaces)
            {
                UnLinkFace(faceId);
            }

            // Modify changed faces
            for (var i = conx.DeltaPivot; i < conx.DeltaFaces.Count; i++)
            {
                var faceId = conx.DeltaFaces[i];
                var face   = Face(faceId);
                face.RemapVertex(vertId2, vertId1);
                faceLinks[vertId1].Add(faceId);
            }

            if (NormalBinding == MxBinding.PerFace)
            {
                var nml = new double[3];
                foreach (var faceId in conx.DeltaFaces)
                {
                    ComputeFaceNormal(faceId, ref nml);
                    Normal(faceId, new MxNormal(nml));
                }
            }

            // Remove v2
            VertexMarkInvalid(vertId2);
            faceLinks[vertId2].Clear();
        }
Beispiel #15
0
        internal void ApplyContraction(MxPairContraction conx)
        {
            var vertId1 = conx.VertId1;
            var vertId2 = conx.VertId2;

            // Move vert1 to new position
            var pos = Vertex(vertId1).Pos;
            MxVectorOps.AddInto3(ref pos, conx.DeltaV1);
            Vertex(vertId1).Pos = pos;

            // Remove dead faces
            foreach (var faceId in conx.DeadFaces)
            {
                UnLinkFace(faceId);
            }

            // Modify changed faces
            for (var i = conx.DeltaPivot; i < conx.DeltaFaces.Count; i++)
            {
                var faceId = conx.DeltaFaces[i];
                var face = Face(faceId);
                face.RemapVertex(vertId2, vertId1);
                faceLinks[vertId1].Add(faceId);
            }

            if (NormalBinding == MxBinding.PerFace)
            {
                var nml = new double[3];
                foreach (var faceId in conx.DeltaFaces)
                {
                    ComputeFaceNormal(faceId, ref nml);
                    Normal(faceId, new MxNormal(nml));
                }
            }

            // Remove v2
            VertexMarkInvalid(vertId2);
            faceLinks[vertId2].Clear();
        }
Beispiel #16
0
 internal void ContractionCallback(MxPairContraction conx, float f)
 {
 }
Beispiel #17
0
 internal void Contract(int vertId1, int vertId2, double[] newVert, MxPairContraction conx)
 {
     ComputeContraction(vertId1, vertId2, conx, null);
     MxVectorOps.Sub3(ref conx.DeltaV1, newVert, Vertex(vertId1).Pos);
     MxVectorOps.Sub3(ref conx.DeltaV2, newVert, Vertex(vertId2).Pos);
     ApplyContraction(conx);
 }
Beispiel #18
0
 internal void UpdatePostContract(MxPairContraction conx)
 {
 }
Beispiel #19
0
        internal void ComputeContraction(int vertId1, int vertId2, MxPairContraction conx, double[] newVert)
        {
            conx.VertId1 = vertId1;
            conx.VertId2 = vertId2;

            if (newVert != null)
            {
                MxVectorOps.Sub3(ref conx.DeltaV1, newVert, Vertex(vertId1).Pos);
                MxVectorOps.Sub3(ref conx.DeltaV2, newVert, Vertex(vertId2).Pos);
            }
            else
            {
                conx.DeltaV1 = new[] { 0.0, 0.0, 0.0 };
                conx.DeltaV2 = new[] { 0.0, 0.0, 0.0 };
            }

            conx.DeltaFaces.Clear();
            conx.DeadFaces.Clear();

            MarkNeighborhood(vertId2, 0x0);
            MarkNeighborhood(vertId1, 0x1);
            MarkNeighborhoodDelta(vertId2, 0x1);

            PartitionMarkedNeighbors(vertId1, 0x2, conx.DeltaFaces, conx.DeadFaces);
            conx.DeltaPivot = conx.DeltaFaces.Count;
            PartitionMarkedNeighbors(vertId2, 0x2, conx.DeltaFaces, conx.DeadFaces);
        }
Beispiel #20
0
 internal void ContractionCallback(MxPairContraction conx, float f)
 {
 }
Beispiel #21
0
 internal void UpdatePreExpand(MxPairContraction conx)
 {
 }
Beispiel #22
0
 internal void UpdatePreExpand(MxPairContraction conx)
 {
 }
Beispiel #23
0
        internal void UpdatePreContract(MxPairContraction conx)
        {
            var v1 = conx.VertId1;
            var v2 = conx.VertId2;

            var star = new List<int>();

            foreach(var edge in edgeLinks[v1])
            {
                star.Add(edge.OppositeVertex(v1));
            }

            foreach (var edge in edgeLinks[v2])
            {
                var vertU = (edge.V1 == v2) ? edge.V2 : edge.V1;
                Debug.Assert(edge.V1 == v2 || edge.V2 == v2);
                Debug.Assert(vertU != v2);

                if (vertU == v1 || star.Contains(vertU))
                {
                    edgeLinks[vertU].Remove(edge);
                    heap.RemoveItem(edge);
                }
                else
                {
                    edge.V1 = v1;
                    edge.V2 = vertU;
                    edgeLinks[v1].Add(edge);
                }
            }

            edgeLinks[v2].Clear();
        }
Beispiel #24
0
        internal void UpdatePostExpand(MxPairContraction conx)
        {
            var v1 = conx.VertId1;
            var v2 = conx.VertId2;

            var star = new List<int>();
            var star2 = new List<int>();
            edgeLinks[conx.VertId2].Clear();
            model.CollectVertexStar(conx.VertId1, star);
            model.CollectVertexStar(conx.VertId2, star2);

            var i = 0;
            while (i < edgeLinks[v1].Count)
            {
                var edge = edgeLinks[v1][i];
                var vertU = (edge.V1 == v1) ? edge.V2 : edge.V1;
                Debug.Assert(edge.V1 == v1 || edge.V2 == v1);
                Debug.Assert(vertU != v1 && vertU != v2);

                var v1Linked = star.Contains(vertU);
                var v2Linked = star2.Contains(vertU);

                if (v1Linked)
                {
                    if (v2Linked) CreateEdge(v2, vertU);
                    i++;
                }
                else
                {
                    edge.V1 = v2;
                    edge.V2 = vertU;
                    edgeLinks[v2].Add(edge);
                    edgeLinks[v1].RemoveAt(i);
                }

                ComputeEdgeInfo(edge);
            }

            if (star.Contains(v2)) CreateEdge(v1, v2);
        }
Beispiel #25
0
 internal void UpdatePostContract(MxPairContraction conx)
 {
 }
Beispiel #26
0
        internal override bool Decimate(int target)
        {
            while(ValidFaces > target)
            {
                var info = heap.Extract() as MxQSlimEdge;
                if (info == null) return false;

                var v1 = info.V1;
                var v2 = info.V2;

                if (!model.VertexIsValid(v1) || !model.VertexIsValid(v2)) continue;

                var inversion = CheckLocalInversion(v1, info.vNew);
                if (inversion < 0.00) continue;

                inversion = CheckLocalInversion(v2, info.vNew);
                if (inversion < 0.00) continue;

                var conx = new MxPairContraction();
                model.ComputeContraction(v1, v2, conx, info.vNew);

                if (WillJoinOnly && conx.DeadFaces.Count > 0) continue;

                var evt = Contracted;
                if (evt != null)
                {
                    evt(conx, -info.HeapKey);
                }

                ApplyContraction(conx);
            }

            return true;
        }