/// <summary>
        /// Calculate when two point right. The result is one triangle
        /// </summary>
        static void CalculateOneTr(BzMeshDataEditor meshDataEditor, int inV, int outA, int outB, List <BzTriangle> trianglesSliced)
        {
            //  outA\^^^^^^^^^^^^^/outB
            //       \           /
            //        \         /
            //      ---------------
            //    new2  \     /  new1
            //           \   /
            //            \ /
            //            inV

            int new1 = meshDataEditor.GetIndexFor(inV, outB);
            int new2 = meshDataEditor.GetIndexFor(inV, outA);

            if (new1 != inV & new2 != inV)
            {
                var tr = new BzTriangle(inV, new2, new1);
                trianglesSliced.Add(tr);
            }

            // save edge to chash
            if (new1 != new2)
            {
                meshDataEditor.CapEdges.Add(new IndexVector(new1, new2));
            }
        }
Exemple #2
0
        public void GetEdgeLoops()
        {
            //Arrange
            var vertices = new Vector3[]
            {
                new Vector3(0f, 0f, 0),
                new Vector3(0f, 1f, 0),
                new Vector3(0f, 1f, 0),
                new Vector3(0.5f, 1f, 0),
                new Vector3(1f, 1f, 0),
            };

            var mesh = new Mesh();

            mesh.vertices = vertices;

            var meshData            = new BzMeshData(mesh, null);
            var adapter             = new BzMockAdapter(vertices);
            BzMeshDataEditor editor = new BzMeshDataEditor(meshData, new Plane(), adapter);

            editor.CapEdges.Add(new IndexVector(0, 1));
            editor.CapEdges.Add(new IndexVector(1, 2));
            editor.CapEdges.Add(new IndexVector(2, 3));
            editor.CapEdges.Add(new IndexVector(3, 4));

            //Act
            var loops = editor.GetEdgeLoops();

            //Assert
            Assert.AreEqual(1, loops.Count);

            var loop = loops.Single();

            CollectionAssert.AreEqual(new[] { 0, 1, 4 }, LoopToArray(loop));
        }
Exemple #3
0
        public void GetEdgeLoopsByIndex()
        {
            //Arrange
            BzMeshDataEditor editor = new BzMeshDataEditor(null, new Plane(), null);

            editor.CapEdges.Add(new IndexVector(1, 5));
            editor.CapEdges.Add(new IndexVector(5, 3));
            editor.CapEdges.Add(new IndexVector(3, 6));
            editor.CapEdges.Add(new IndexVector(6, 7));
            editor.CapEdges.Add(new IndexVector(7, 8));

            editor.CapEdges.Add(new IndexVector(2, 4));
            editor.CapEdges.Add(new IndexVector(4, 9));
            editor.CapEdges.Add(new IndexVector(9, 10));

            //Act
            var loops = editor.GetEdgeLoopsByIndex();

            //Assert
            Assert.AreEqual(2, loops.Count);

            var loop1 = loops.Single(loop => loop.size == 6);
            var loop2 = loops.Single(loop => loop.size == 4);

            Assert.IsTrue(Enumerable.SequenceEqual(new[] { 1, 5, 3, 6, 7, 8 }, LoopToArray(loop1)));
            Assert.IsTrue(Enumerable.SequenceEqual(new[] { 2, 4, 9, 10 }, LoopToArray(loop2)));
        }
Exemple #4
0
        public void JoinBySameValue()
        {
            //Arrange
            var vertices = new Vector3[]
            {
                new Vector3(0, 0, 0),
                new Vector3(1, 0, 0),
                new Vector3(1, 0, 0),
                new Vector3(3, 0, 0),

                new Vector3(4, 0, 0),
                new Vector3(5, 0, 0),
                new Vector3(5, 0, 0),
                new Vector3(7, 0, 0),
            };

            var mesh = new Mesh();

            mesh.vertices = vertices;

            var meshData            = new BzMeshData(mesh, null);
            var adapter             = new BzMockAdapter(vertices);
            BzMeshDataEditor editor = new BzMeshDataEditor(meshData, new Plane(), adapter);

            editor.CapEdges.Add(new IndexVector(2, 3));
            editor.CapEdges.Add(new IndexVector(0, 1));

            editor.CapEdges.Add(new IndexVector(4, 5));
            editor.CapEdges.Add(new IndexVector(5, 6));
            editor.CapEdges.Add(new IndexVector(6, 7));

            //Act
            var loops = editor.GetEdgeLoopsByIndex();

            Assert.AreEqual(3, loops.Count);
            editor.EdgeLoops_JoinBySameValue(loops);

            //Assert
            Assert.AreEqual(2, loops.Count);

            var loop1 = loops.Single(loop => loop.first.value == 0 | loop.last.value == 0);
            var loop2 = loops.Single(loop => loop.first.value == 4 | loop.last.value == 4);

            Assert.IsTrue(Enumerable.SequenceEqual(new[] { 0, 1, 3 }, LoopToArray(loop1)));
            Assert.IsTrue(Enumerable.SequenceEqual(new[] { 4, 5, 6, 7 }, LoopToArray(loop2)));
        }
        /// <summary>
        /// Cut this trianle by plane (plane from MeshPeparator)
        /// </summary>
        /// <param name="tr">Out triangle 1 (always exists)</param>
        /// <param name="trNegExtra">Out triangle 2 (can be null)</param>
        public void DivideByPlane(BzMeshDataEditor meshDataEditorNeg, BzMeshDataEditor meshDataEditorPos,
                                  List <BzTriangle> trianglesNegSliced, List <BzTriangle> trianglesPosSliced,
                                  bool _side1, bool _side2, bool _side3)
        {
            if (!_side1 & _side2 & _side3)
            {
                CalculateOneTr(meshDataEditorNeg, i1, i2, i3, trianglesNegSliced);
                CalculateTwoTr(meshDataEditorPos, i1, i2, i3, trianglesPosSliced);
            }
            else if (_side1 & !_side2 & _side3)
            {
                CalculateOneTr(meshDataEditorNeg, i2, i3, i1, trianglesNegSliced);
                CalculateTwoTr(meshDataEditorPos, i2, i3, i1, trianglesPosSliced);
            }
            else if (_side1 & _side2 & !_side3)
            {
                CalculateOneTr(meshDataEditorNeg, i3, i1, i2, trianglesNegSliced);
                CalculateTwoTr(meshDataEditorPos, i3, i1, i2, trianglesPosSliced);
            }


            else if (_side1 & !_side2 & !_side3)
            {
                CalculateTwoTr(meshDataEditorNeg, i1, i2, i3, trianglesNegSliced);
                CalculateOneTr(meshDataEditorPos, i1, i2, i3, trianglesPosSliced);
            }
            else if (!_side1 & _side2 & !_side3)
            {
                CalculateTwoTr(meshDataEditorNeg, i2, i3, i1, trianglesNegSliced);
                CalculateOneTr(meshDataEditorPos, i2, i3, i1, trianglesPosSliced);
            }
            else if (!_side1 & !_side2 & _side3)
            {
                CalculateTwoTr(meshDataEditorNeg, i3, i1, i2, trianglesNegSliced);
                CalculateOneTr(meshDataEditorPos, i3, i1, i2, trianglesPosSliced);
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
        /// <summary>
        /// Calculate when one point right. The result is two triangles
        /// </summary>
        static void CalculateTwoTr(BzMeshDataEditor meshDataEditor, int outV, int inA, int inB, List <BzTriangle> trianglesSliced)
        {
            //            outV
            //            / \
            //           /   \
            //    new2  /     \  new1
            //      ----.----------
            //        /   .     \
            //       /       .   \
            //   inB/___________._\inA

            int new1 = meshDataEditor.GetIndexFor(inA, outV);
            int new2 = meshDataEditor.GetIndexFor(inB, outV);

            if (new1 == outV | new2 == outV)
            {
                var tr = new BzTriangle(inB, outV, inA);
                trianglesSliced.Add(tr);
            }
            else
            {
                if (new1 != inA)
                {
                    var tr1 = new BzTriangle(inA, new2, new1);
                    trianglesSliced.Add(tr1);
                }
                if (new2 != inB)
                {
                    var tr2 = new BzTriangle(inB, new2, inA);
                    trianglesSliced.Add(tr2);
                }
            }

            // save edge to chash
            if (new2 != new1)
            {
                meshDataEditor.CapEdges.Add(new IndexVector(new1, new2));
            }
        }
Exemple #7
0
        /// <summary>
        /// Calculate when two point right. The result is one triangle
        /// </summary>
        static void CalculateOneTr(BzMeshDataEditor meshDataEditor, int neg, int rightA, int rightB, List <BzTriangle> trianglesSliced)
        {
            //            pos
            //    rA\^^^^^^^^^^^^^/rB
            //       \           /
            //        \         /
            //      ---------------
            //    new1  \     /  new2
            //           \   /
            //            \ /
            //            neg

            int new1 = meshDataEditor.GetIndexFor(neg, rightA);
            int new2 = meshDataEditor.GetIndexFor(neg, rightB);

            var tr = new BzTriangle(neg, new1, new2);

            trianglesSliced.Add(tr);

            // save eghe to chash
            meshDataEditor.CapEdges.Add(new IndexVector(new1, new2));
        }
Exemple #8
0
        /// <summary>
        /// Calculate when one point right. The result is two triangles
        /// </summary>
        static void CalculateTwoTr(BzMeshDataEditor meshDataEditor, int pos, int negA, int negB, List <BzTriangle> trianglesSliced)
        {
            //            pos
            //            / \
            //           /   \
            //    new1  /     \  new2
            //      ----.----------
            //        /   .     \
            //       /       .   \
            //    iB/___________._\iA
            //           neg

            int new1 = meshDataEditor.GetIndexFor(negB, pos);
            int new2 = meshDataEditor.GetIndexFor(negA, pos);

            var tr1 = new BzTriangle(negB, new1, negA);
            var tr2 = new BzTriangle(negA, new1, new2);

            trianglesSliced.Add(tr1);
            trianglesSliced.Add(tr2);

            // save eghe to chash
            meshDataEditor.CapEdges.Add(new IndexVector(new1, new2));
        }
        private SliceResult SliceMesh(Material sectionViewMaterial)
        {
            Profiler.BeginSample("SliceMesh");
            var planeInverted = new Plane(-_plane.normal, -_plane.distance);

            bool skipIfNotClosed = Configuration == null ? false : Configuration.SkipIfNotClosed;

            BzMeshDataEditor meshEditorNeg = new BzMeshDataEditor(_meshDataNeg, _plane, _adapter, skipIfNotClosed);
            BzMeshDataEditor meshEditorPos = new BzMeshDataEditor(_meshDataPos, planeInverted, _adapter, skipIfNotClosed);

            for (int subMeshIndex = 0; subMeshIndex < _subMeshes.Length; ++subMeshIndex)
            {
                int[] newTriangles = _subMeshes[subMeshIndex];

                int trCount            = newTriangles.Length / 3;
                var trianglesNeg       = new List <BzTriangle>(trCount);
                var trianglesPos       = new List <BzTriangle>(trCount);
                var trianglesNegSliced = new List <BzTriangle>(trCount / 10);
                var trianglesPosSliced = new List <BzTriangle>(trCount / 10);

                for (int i = 0; i < trCount; ++i)
                {
                    int trIndex    = i * 3;
                    var bzTriangle = new BzTriangle(
                        newTriangles[trIndex + 0],
                        newTriangles[trIndex + 1],
                        newTriangles[trIndex + 2]);

                    Vector3 v1      = _adapter.GetWorldPos(bzTriangle.i1);
                    Vector3 v2      = _adapter.GetWorldPos(bzTriangle.i2);
                    Vector3 v3      = _adapter.GetWorldPos(bzTriangle.i3);
                    bool    side1   = _plane.GetSide(v1);
                    bool    side2   = _plane.GetSide(v2);
                    bool    side3   = _plane.GetSide(v3);
                    bool    PosSide = side1 | side2 | side3;
                    bool    NegSide = !side1 | !side2 | !side3;

                    if (NegSide & PosSide)
                    {
                        bzTriangle.DivideByPlane(
                            meshEditorNeg, meshEditorPos,
                            trianglesNegSliced, trianglesPosSliced,
                            side1, side2, side3);
                    }
                    else if (NegSide)
                    {
                        trianglesNeg.Add(bzTriangle);
                    }
                    else if (PosSide)
                    {
                        trianglesPos.Add(bzTriangle);
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }
                }

                MeshTriangleOptimizer.OptimizeEdgeTriangles(meshEditorNeg.GetEdgeLoopsByIndex(), _meshDataNeg, trianglesNegSliced);
                MeshTriangleOptimizer.OptimizeEdgeTriangles(meshEditorPos.GetEdgeLoopsByIndex(), _meshDataPos, trianglesPosSliced);
                _meshDataNeg.SubMeshes[subMeshIndex] = MakeTriangleToList(trianglesNeg, trianglesNegSliced);
                _meshDataPos.SubMeshes[subMeshIndex] = MakeTriangleToList(trianglesPos, trianglesPosSliced);
            }

            CapsNeg = meshEditorNeg.CapSlice(sectionViewMaterial);
            CapsPos = meshEditorPos.CapSlice(sectionViewMaterial);

            meshEditorNeg.DeleteUnusedVertices();
            meshEditorPos.DeleteUnusedVertices();

            Profiler.EndSample();

            if (!CheckNewMesh(_meshDataNeg))
            {
                return(SliceResult.Pos);
            }
            if (!CheckNewMesh(_meshDataPos))
            {
                return(SliceResult.Neg);
            }

            return(SliceResult.Sliced);
        }
Exemple #10
0
        private static void OptimizeEdgeTriangles(BzMeshDataEditor meshEditor, BzMeshData meshData, List <BzTriangle> bzTriangles)
        {
            var edgeLoops = meshEditor.GetEdgeLoopsByIndex();

            bool[] trToDelete = new bool[bzTriangles.Count];

            var edgeLoopsNode = edgeLoops.First;

            while (edgeLoopsNode != null)
            {
                var edgeLoop = edgeLoopsNode.Value;
                edgeLoopsNode = edgeLoopsNode.Next;

                var edge    = edgeLoop.first;
                int counter = edgeLoop.size;
                while (counter > 0 & edgeLoop.size >= 3)
                {
                    --counter;

                    var edgeItem1 = edge;
                    var edgeItem2 = edgeItem1.next;
                    var edgeItem3 = edgeItem2.next;

                    int i1 = edgeItem1.value;
                    int i2 = edgeItem2.value;
                    int i3 = edgeItem3.value;

                    var v1 = meshData.Vertices[i1];
                    var v2 = meshData.Vertices[i2];
                    var v3 = meshData.Vertices[i3];

                    if (v1 == v2)
                    {
                        EmptyRedundantIndex(i2, i3, bzTriangles, trToDelete);
                        edgeItem2.Remove();
                        continue;
                    }

                    var dir1 = (v2 - v1).normalized;
                    var dir2 = (v3 - v2).normalized;

                    if (dir1 == dir2)
                    {
                        EmptyRedundantIndex(i2, i3, bzTriangles, trToDelete);
                        edgeItem2.Remove();
                    }
                    else
                    {
                        edge = edge.next;
                    }
                }
            }

            // remove empty
            int count = 0;

            for (int i = 0; i < bzTriangles.Count; i++)
            {
                var value = bzTriangles[i];
                bzTriangles[count] = value;

                if (!trToDelete[i])
                {
                    ++count;
                }
            }

            bzTriangles.RemoveRange(count, bzTriangles.Count - count);
        }