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))); }
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))); }
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); }
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); }