diff --git a/MatterControl.MeshOperations/RepairObject3D.cs b/MatterControl.MeshOperations/RepairObject3D.cs index 8e1e67570..c2fefd4dc 100644 --- a/MatterControl.MeshOperations/RepairObject3D.cs +++ b/MatterControl.MeshOperations/RepairObject3D.cs @@ -1,41 +1,21 @@ /* -Copyright (c) 2018, Lars Brubaker, John Lewin +Copyright (c) Ryan Schmidt (rms@gradientspace.com) - All Rights Reserved +Distributed under the Boost Software License, Version 1.0. http://www.boost.org/LICENSE_1_0.txt +Copyright (c) 2018, Lars Brubaker All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those -of the authors and should not be interpreted as representing official policies, -either expressed or implied, of the FreeBSD Project. */ +using System; +using System.ComponentModel; +using System.Threading; +using System.Threading.Tasks; using g3; using gs; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; using MatterHackers.MatterControl.DesignTools.Operations; using MatterHackers.PolygonMesh; -using System.ComponentModel; -using System.Threading; -using System.Threading.Tasks; +using static gs.MeshAutoRepair; namespace MatterHackers.MatterControl.DesignTools { @@ -46,9 +26,19 @@ namespace MatterHackers.MatterControl.DesignTools Name = "Repair".Localize(); } - [Description("Ensure that each reduced point is on the surface of the original mesh. This is not normally required and slows the computation significantly.")] + [Description("Make all the faces have a consistent orientation.")] public bool FaceOrientation { get; set; } = true; + [Description("Repair any small cracks or bad seams in the model.")] + public bool WeldEdges { get; set; } = true; + + [Description("Try to fill in any holes that are in the model.")] + public bool FillHoles { get; set; } = true; + + + [Description("Remove interior faces and bodies.")] + public RemoveModes RemoveMode { get; set; } = RemoveModes.None; + public override Task Rebuild() { this.DebugDepth("Rebuild"); @@ -95,218 +85,358 @@ namespace MatterHackers.MatterControl.DesignTools public Mesh Repair(Mesh inMesh, CancellationToken cancellationToken) { - var mesh = inMesh.ToDMesh3(); - if (FaceOrientation) + try { - var repaired = new MeshRepairOrientation(mesh); - repaired.OrientComponents(); - mesh = repaired.Mesh; - } + var mesh = inMesh.ToDMesh3(); + int repeatCount = 0; + int erosionIterations = 5; + double repairTolerance = MathUtil.ZeroTolerancef; + double minEdgeLengthTol = 0.0001; - { - int repeat_count = 0; + repeat_all: - repeat_all: - // Remove parts of the mesh we don't want before we bother with anything else - // TODO: maybe we need to repair orientation first? if we want to use MWN... - do_remove_inside(mesh); - if (cancellationToken.IsCancellationRequested) + if (FaceOrientation) { - return inMesh; + // make sure orientation of connected components is consistent + // TODO: what about mobius strip problems? + RepairOrientation(mesh, cancellationToken, true); } - // make sure orientation of connected components is consistent - // TODO: what about mobius strip problems? - repair_orientation(mesh, cancellationToken, false); - if (cancellationToken.IsCancellationRequested) + if (RemoveMode != RemoveModes.None) { - return inMesh; + // Remove parts of the mesh we don't want before we bother with anything else + // TODO: maybe we need to repair orientation first? if we want to use MWN (MeshWindingNumber)... + RremoveInside(mesh); + cancellationToken.ThrowIfCancellationRequested(); } - // Do safe close-cracks to handle easy cases - repair_cracks(true, RepairTolerance); - - if (Mesh.IsClosed()) goto all_done; - if (cancellationToken.IsCancellationRequested) + if (WeldEdges || FillHoles) { - return inMesh; - } + // Do safe close-cracks to handle easy cases + RepairCracks(mesh, true, repairTolerance); - // Collapse tiny edges and then try easy cases again, and - // then allow for handling of ambiguous cases - collapse_all_degenerate_edges(RepairTolerance * 0.5, true); - if (cancellationToken.IsCancellationRequested) - { - return inMesh; - } - - repair_cracks(true, 2 * RepairTolerance); - if (cancellationToken.IsCancellationRequested) - { - return inMesh; - } - - repair_cracks(false, 2 * RepairTolerance); - if (cancellationToken.IsCancellationRequested) - { - return inMesh; - } - - if (Mesh.IsClosed()) goto all_done; - - // Possibly we have joined regions with different orientation (is it?), fix that - // TODO: mobius strips again - repair_orientation(false); - if (cancellationToken.IsCancellationRequested) - { - return inMesh; - } - - - // get rid of any remaining single-triangles before we start filling holes - remove_loners(); - - // Ok, fill simple holes. - int nRemainingBowties = 0; - int nHoles; bool bSawSpans; - fill_trivial_holes(out nHoles, out bSawSpans); - if (cancellationToken.IsCancellationRequested) - { - return inMesh; - } - - if (Mesh.IsClosed()) goto all_done; - - // Now fill harder holes. If we saw spans, that means boundary loops could - // not be resolved in some cases, do we disconnect bowties and try again. - fill_any_holes(out nHoles, out bSawSpans); - if (Cancelled()) return false; - if (bSawSpans) - { - disconnect_bowties(out nRemainingBowties); - fill_any_holes(out nHoles, out bSawSpans); - } - - if (cancellationToken.IsCancellationRequested) - { - return inMesh; - } - - if (mesh.IsClosed()) - { - goto all_done; - } - - // We may have a closed mesh now but it might still have bowties (eg - // tetrahedra sharing vtx case). So disconnect those. - disconnect_bowties(out nRemainingBowties); - if (cancellationToken.IsCancellationRequested) - { - return inMesh; - } - - // If the mesh is not closed, we will do one more round to try again. - if (repeat_count == 0 && mesh.IsClosed() == false) - { - repeat_count++; - goto repeat_all; - } - - // Ok, we didn't get anywhere on our first repeat. If we are still not - // closed, we will try deleting boundary triangles and repeating. - //* Repeat this N times. - if (repeat_count <= ErosionIterations && Mesh.IsClosed() == false) - { - repeat_count++; - MeshFaceSelection bdry_faces = new MeshFaceSelection(Mesh); - foreach (int eid in MeshIterators.BoundaryEdges(Mesh)) + if (mesh.IsClosed()) { - bdry_faces.SelectEdgeTris(eid); + goto all_done; } - MeshEditor.RemoveTriangles(Mesh, bdry_faces, true); - goto repeat_all; + cancellationToken.ThrowIfCancellationRequested(); + + // Collapse tiny edges and then try easy cases again, and + // then allow for handling of ambiguous cases + CollapseAllDegenerateEdges(mesh, cancellationToken, repairTolerance * 0.5, true); + cancellationToken.ThrowIfCancellationRequested(); + + RepairCracks(mesh, true, 2 * repairTolerance); + cancellationToken.ThrowIfCancellationRequested(); + + RepairCracks(mesh, false, 2 * repairTolerance); + cancellationToken.ThrowIfCancellationRequested(); + + if (mesh.IsClosed()) + { + goto all_done; + } + + // Possibly we have joined regions with different orientation (is it?), fix that + // TODO: mobius strips again + RepairOrientation(mesh, cancellationToken, true); + cancellationToken.ThrowIfCancellationRequested(); + + // get rid of any remaining single-triangles before we start filling holes + MeshEditor.RemoveIsolatedTriangles(mesh); } - all_done: - // Remove tiny edges - if (MinEdgeLengthTol > 0) + if (FillHoles) { - collapse_all_degenerate_edges(MinEdgeLengthTol, false); + // Ok, fill simple holes. + int nRemainingBowties = 0; + FillTrivialHoles(mesh, cancellationToken, out int nHoles, out bool bSawSpans); + cancellationToken.ThrowIfCancellationRequested(); + + if (mesh.IsClosed()) + { + goto all_done; + } + + // Now fill harder holes. If we saw spans, that means boundary loops could + // not be resolved in some cases, do we disconnect bowties and try again. + FillAnyHoles(mesh, cancellationToken, out nHoles, out bSawSpans); + cancellationToken.ThrowIfCancellationRequested(); + + if (bSawSpans) + { + DisconnectBowties(mesh, out nRemainingBowties); + FillAnyHoles(mesh, cancellationToken, out nHoles, out bSawSpans); + } + + cancellationToken.ThrowIfCancellationRequested(); + + if (mesh.IsClosed()) + { + goto all_done; + } + + // We may have a closed mesh now but it might still have bowties (eg + // tetrahedra sharing vtx case). So disconnect those. + DisconnectBowties(mesh, out nRemainingBowties); + cancellationToken.ThrowIfCancellationRequested(); + + // If the mesh is not closed, we will do one more round to try again. + if (repeatCount == 0 && mesh.IsClosed() == false) + { + repeatCount++; + goto repeat_all; + } + + // Ok, we didn't get anywhere on our first repeat. If we are still not + // closed, we will try deleting boundary triangles and repeating. + // Repeat this N times. + if (repeatCount <= erosionIterations && mesh.IsClosed() == false) + { + repeatCount++; + var bdry_faces = new MeshFaceSelection(mesh); + foreach (int eid in MeshIterators.BoundaryEdges(mesh)) + { + bdry_faces.SelectEdgeTris(eid); + } + + MeshEditor.RemoveTriangles(mesh, bdry_faces, true); + goto repeat_all; + } } - if (cancellationToken.IsCancellationRequested) + all_done: + + // and do a final clean up of the model + if (FillHoles) { - return inMesh; + // Remove tiny edges + if (minEdgeLengthTol > 0) + { + CollapseAllDegenerateEdges(mesh, cancellationToken, minEdgeLengthTol, false); + } + + cancellationToken.ThrowIfCancellationRequested(); + + // finally do global orientation + RepairOrientation(mesh, cancellationToken, true); + cancellationToken.ThrowIfCancellationRequested(); } - // finally do global orientation - repair_orientation(mesh, cancellationToken, true); - if (cancellationToken.IsCancellationRequested) - { - return inMesh; - } + return mesh.ToMesh(); } - - return mesh.ToMesh(); - } - - void repair_orientation(DMesh3 Mesh, CancellationToken cancellationToken, bool bGlobal) - { - MeshRepairOrientation orient = new MeshRepairOrientation(Mesh); - orient.OrientComponents(); - if (cancellationToken.IsCancellationRequested) + catch (OperationCanceledException) { - return; + return inMesh; } - - if (bGlobal) - { - orient.SolveGlobalOrientation(); - } - } - - bool remove_interior(DMesh3 Mesh, out int nRemoved) - { - RemoveOccludedTriangles remove = new RemoveOccludedTriangles(Mesh); - remove.PerVertex = true; - remove.InsideMode = RemoveOccludedTriangles.CalculationMode.FastWindingNumber; - remove.Apply(); - nRemoved = remove.RemovedT.Count(); - return true; - } - - bool remove_occluded(DMesh3 Mesh, out int nRemoved) - { - RemoveOccludedTriangles remove = new RemoveOccludedTriangles(Mesh); - remove.PerVertex = true; - remove.InsideMode = RemoveOccludedTriangles.CalculationMode.SimpleOcclusionTest; - remove.Apply(); - nRemoved = remove.RemovedT.Count(); - return true; - } - - bool do_remove_inside(DMesh3 Mesh) - { - int nRemoved = 0; - if (RemoveMode == RemoveModes.Interior) - { - return remove_interior(Mesh, out nRemoved); - } - else if (RemoveMode == RemoveModes.Occluded) - { - return remove_occluded(Mesh, out nRemoved); - } - - return true; } public void UpdateControls(PublicPropertyChange change) { - //if (change.Context.GetEditRow(nameof(TargetPercent)) is GuiWidget percentWidget) - //{ - // percentWidget.Visible = Mode == ReductionMode.Polygon_Percent; - //} + // if (change.Context.GetEditRow(nameof(TargetPercent)) is GuiWidget percentWidget) + // { + // percentWidget.Visible = Mode == ReductionMode.Polygon_Percent; + // } + } + + private bool CollapseAllDegenerateEdges(DMesh3 mesh, + CancellationToken cancellationToken, + double minLength, + bool bBoundaryOnly) + { + bool repeat = true; + while (repeat) + { + cancellationToken.ThrowIfCancellationRequested(); + CollapseDegenerateEdges(mesh, cancellationToken, minLength, bBoundaryOnly, out int collapseCount); + if (collapseCount == 0) + { + repeat = false; + } + } + + return true; + } + + private bool CollapseDegenerateEdges(DMesh3 mesh, + CancellationToken cancellationToken, + double minLength, + bool bBoundaryOnly, + out int collapseCount) + { + collapseCount = 0; + // don't iterate sequentially because there may be pathological cases + foreach (int eid in MathUtil.ModuloIteration(mesh.MaxEdgeID)) + { + cancellationToken.ThrowIfCancellationRequested(); + if (mesh.IsEdge(eid) == false) + { + continue; + } + + bool isBoundaryEdge = mesh.IsBoundaryEdge(eid); + if (bBoundaryOnly && isBoundaryEdge == false) + { + continue; + } + + Index2i ev = mesh.GetEdgeV(eid); + Vector3d a = mesh.GetVertex(ev.a), b = mesh.GetVertex(ev.b); + if (a.Distance(b) < minLength) + { + int keep = mesh.IsBoundaryVertex(ev.a) ? ev.a : ev.b; + int discard = (keep == ev.a) ? ev.b : ev.a; + MeshResult result = mesh.CollapseEdge(keep, discard, out DMesh3.EdgeCollapseInfo collapseInfo); + if (result == MeshResult.Ok) + { + ++collapseCount; + if (mesh.IsBoundaryVertex(keep) == false || isBoundaryEdge) + { + mesh.SetVertex(keep, (a + b) * 0.5); + } + } + } + } + + return true; + } + + private bool DisconnectBowties(DMesh3 mesh, out int nRemaining) + { + var editor = new MeshEditor(mesh); + nRemaining = editor.DisconnectAllBowties(); + return true; + } + + private bool RremoveInside(DMesh3 mesh) + { + if (RemoveMode == RemoveModes.Interior) + { + return RemoveInterior(mesh, out _); + } + else if (RemoveMode == RemoveModes.Occluded) + { + return RemoveOccluded(mesh, out _); + } + + return true; + } + + private void FillAnyHoles(DMesh3 mesh, + CancellationToken cancellationToken, + out int nRemaining, + out bool sawSpans) + { + var loops = new MeshBoundaryLoops(mesh); + nRemaining = 0; + sawSpans = loops.SawOpenSpans; + + foreach (var loop in loops) + { + cancellationToken.ThrowIfCancellationRequested(); + var filler = new MinimalHoleFill(mesh, loop); + bool filled = filler.Apply(); + if (filled == false) + { + cancellationToken.ThrowIfCancellationRequested(); + var fallback = new SimpleHoleFiller(mesh, loop); + fallback.Fill(); + } + } + } + + private void FillTrivialHoles(DMesh3 mesh, + CancellationToken cancellationToken, + out int nRemaining, + out bool sawSpans) + { + var loops = new MeshBoundaryLoops(mesh); + nRemaining = 0; + sawSpans = loops.SawOpenSpans; + + foreach (var loop in loops) + { + cancellationToken.ThrowIfCancellationRequested(); + bool filled = false; + if (loop.VertexCount == 3) + { + var filler = new SimpleHoleFiller(mesh, loop); + filled = filler.Fill(); + } + else if (loop.VertexCount == 4) + { + var filler = new MinimalHoleFill(mesh, loop); + filled = filler.Apply(); + if (filled == false) + { + var fallback = new SimpleHoleFiller(mesh, loop); + filled = fallback.Fill(); + } + } + + if (filled == false) + { + ++nRemaining; + } + } + } + + private bool RemoveInterior(DMesh3 mesh, out int nRemoved) + { + var remove = new RemoveOccludedTriangles(mesh) + { + PerVertex = true, + InsideMode = RemoveOccludedTriangles.CalculationMode.FastWindingNumber + }; + remove.Apply(); + nRemoved = remove.RemovedT.Count; + return true; + } + + private bool RemoveOccluded(DMesh3 mesh, out int nRemoved) + { + var remove = new RemoveOccludedTriangles(mesh) + { + PerVertex = true, + InsideMode = RemoveOccludedTriangles.CalculationMode.SimpleOcclusionTest + }; + remove.Apply(); + nRemoved = remove.RemovedT.Count; + return true; + } + + private bool RepairCracks(DMesh3 mesh, bool bUniqueOnly, double mergeDist) + { + try + { + var merge = new MergeCoincidentEdges(mesh) + { + OnlyUniquePairs = bUniqueOnly, + MergeDistance = mergeDist + }; + return merge.Apply(); + } + catch (Exception /*e*/) + { + // ?? + return false; + } + } + + private void RepairOrientation(DMesh3 mesh, + CancellationToken cancellationToken, + bool bGlobal) + { + cancellationToken.ThrowIfCancellationRequested(); + var orient = new MeshRepairOrientation(mesh); + orient.OrientComponents(); + + if (bGlobal) + { + cancellationToken.ThrowIfCancellationRequested(); + orient.SolveGlobalOrientation(); + } } } } \ No newline at end of file diff --git a/MatterControlLib/DesignTools/EditorTools/RotateControls/RotateCornerControl.cs b/MatterControlLib/DesignTools/EditorTools/RotateControls/RotateCornerControl.cs index 8c5e29560..c149178d0 100644 --- a/MatterControlLib/DesignTools/EditorTools/RotateControls/RotateCornerControl.cs +++ b/MatterControlLib/DesignTools/EditorTools/RotateControls/RotateCornerControl.cs @@ -149,7 +149,7 @@ namespace MatterHackers.Plugins.EditorTools } } - CollisionVolume = rotationHandle.CreateTraceData(); + CollisionVolume = rotationHandle.CreateBVHData(); InteractionContext.GuiSurface.AfterDraw += InteractionLayer_AfterDraw; } diff --git a/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleCornerControl.cs b/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleCornerControl.cs index d3c044862..0d5800c7a 100644 --- a/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleCornerControl.cs +++ b/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleCornerControl.cs @@ -110,7 +110,7 @@ namespace MatterHackers.Plugins.EditorTools minXminYMesh = PlatonicSolids.CreateCube(selectCubeSize, selectCubeSize, selectCubeSize); - CollisionVolume = minXminYMesh.CreateTraceData(); + CollisionVolume = minXminYMesh.CreateBVHData(); InteractionContext.GuiSurface.AfterDraw += InteractionLayer_AfterDraw; } diff --git a/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleTopControl.cs b/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleTopControl.cs index ccb3c1256..0d4aa38ef 100644 --- a/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleTopControl.cs +++ b/MatterControlLib/DesignTools/EditorTools/ScaleControls/ScaleTopControl.cs @@ -139,7 +139,7 @@ namespace MatterHackers.Plugins.EditorTools topScaleMesh = PlatonicSolids.CreateCube(selectCubeSize, selectCubeSize, selectCubeSize); - CollisionVolume = topScaleMesh.CreateTraceData(); + CollisionVolume = topScaleMesh.CreateBVHData(); InteractionContext.GuiSurface.AfterDraw += InteractionLayer_AfterDraw; } diff --git a/MatterControlLib/PartPreviewWindow/SceneViewer/AABBDrawable.cs b/MatterControlLib/PartPreviewWindow/SceneViewer/AABBDrawable.cs index ac7eaf77a..733feb178 100644 --- a/MatterControlLib/PartPreviewWindow/SceneViewer/AABBDrawable.cs +++ b/MatterControlLib/PartPreviewWindow/SceneViewer/AABBDrawable.cs @@ -55,7 +55,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { foreach (var child in sceneContext.Scene.Children) { - world.RenderDebugAABB(e.Graphics2D, child.TraceData().GetAxisAlignedBoundingBox()); + world.RenderDebugAABB(e.Graphics2D, child.GetBVHData().GetAxisAlignedBoundingBox()); world.RenderDebugAABB(e.Graphics2D, child.GetAxisAlignedBoundingBox()); } } diff --git a/MatterControlLib/PartPreviewWindow/SceneViewer/ItemTraceDataDrawable.cs b/MatterControlLib/PartPreviewWindow/SceneViewer/ItemTraceDataDrawable.cs index 30df1b9e2..64b6a40c7 100644 --- a/MatterControlLib/PartPreviewWindow/SceneViewer/ItemTraceDataDrawable.cs +++ b/MatterControlLib/PartPreviewWindow/SceneViewer/ItemTraceDataDrawable.cs @@ -61,7 +61,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { var center = item.GetAxisAlignedBoundingBox().Center; - var traceData = item.TraceData(); + var traceData = item.GetBVHData(); var xy = traceData.Contains(center); diff --git a/MatterControlLib/PartPreviewWindow/SceneViewer/SceneTraceDataDrawable.cs b/MatterControlLib/PartPreviewWindow/SceneViewer/SceneTraceDataDrawable.cs index 74a1c4b4e..dbc297a56 100644 --- a/MatterControlLib/PartPreviewWindow/SceneViewer/SceneTraceDataDrawable.cs +++ b/MatterControlLib/PartPreviewWindow/SceneViewer/SceneTraceDataDrawable.cs @@ -56,7 +56,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow public void Draw(GuiWidget sender, DrawEventArgs e, Matrix4X4 itemMaxtrix, WorldView world) { // RenderSceneTraceData - var bvhIterator = new BvhIterator(scene?.TraceData(), decentFilter: (x) => + var bvhIterator = new BvhIterator(scene?.GetBVHData(), decentFilter: (x) => { var center = x.Bvh.GetCenter(); var worldCenter = Vector3Ex.Transform(center, x.TransformToWorld); diff --git a/MatterControlLib/PartPreviewWindow/View3D/Gui3D/MoveInZControl.cs b/MatterControlLib/PartPreviewWindow/View3D/Gui3D/MoveInZControl.cs index 24df6412a..1f05d54a6 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/Gui3D/MoveInZControl.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/Gui3D/MoveInZControl.cs @@ -142,7 +142,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow upArrowMesh = StlProcessing.Load(arrowStream, CancellationToken.None); } - CollisionVolume = upArrowMesh.CreateTraceData(); + CollisionVolume = upArrowMesh.CreateBVHData(); InteractionContext.GuiSurface.AfterDraw += InteractionLayer_AfterDraw; } diff --git a/MatterControlLib/PartPreviewWindow/View3D/MeshViewerWidget.cs b/MatterControlLib/PartPreviewWindow/View3D/MeshViewerWidget.cs index c228f2a49..f20e03b09 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/MeshViewerWidget.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/MeshViewerWidget.cs @@ -190,7 +190,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow if (nameFound) { - AxisAlignedBoundingBox bounds = child.TraceData().GetAxisAlignedBoundingBox(); + AxisAlignedBoundingBox bounds = child.GetBVHData().GetAxisAlignedBoundingBox(); RectangleDouble screenBoundsOfObject3D = RectangleDouble.ZeroIntersection; for (int i = 0; i < 4; i++) diff --git a/MatterControlLib/PartPreviewWindow/View3D/TumbleCubeControl.cs b/MatterControlLib/PartPreviewWindow/View3D/TumbleCubeControl.cs index f74e2eca6..166de640c 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/TumbleCubeControl.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/TumbleCubeControl.cs @@ -188,7 +188,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow connections.Add(new ConnectedFaces(1, 1, 2, 3, 1, 0)); connections.Add(new ConnectedFaces(1, -1, 1, 3, 2, 0)); - cubeTraceData = cube.CreateTraceData(); + cubeTraceData = cube.CreateBVHData(); }); MouseLeave += (s, e) => diff --git a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs index 13b0e48af..a44151a5d 100644 --- a/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs +++ b/MatterControlLib/PartPreviewWindow/View3D/View3DWidget.cs @@ -913,7 +913,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow foundTriangleInSelectionBounds = false; // Filter the IPrimitive trace data finding matches as defined in InSelectionBounds - var filteredResults = item.TraceData().Filter(InSelectionBounds); + var filteredResults = item.GetBVHData().Filter(InSelectionBounds); // Accumulate all matching BvhIterator results for debug rendering allResults.AddRange(filteredResults); @@ -1461,7 +1461,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { foreach (Object3D object3D in selectedItem.Children) { - if (object3D.TraceData().Contains(info.HitPosition)) + if (object3D.GetBVHData().Contains(info.HitPosition)) { CurrentSelectInfo.PlaneDownHitPos = info.HitPosition; CurrentSelectInfo.LastMoveDelta = default(Vector3); @@ -1711,12 +1711,12 @@ namespace MatterHackers.MatterControl.PartPreviewWindow Vector2 meshViewerWidgetScreenPosition = this.InteractionLayer.TransformFromParentSpace(this, screenPosition); Ray ray = sceneContext.World.GetRayForLocalBounds(meshViewerWidgetScreenPosition); - intersectionInfo = Scene.TraceData().GetClosestIntersection(ray); + intersectionInfo = Scene.GetBVHData().GetClosestIntersection(ray); if (intersectionInfo != null) { foreach (Object3D object3D in Scene.Children) { - if (object3D.TraceData().Contains(intersectionInfo.HitPosition)) + if (object3D.GetBVHData().Contains(intersectionInfo.HitPosition)) { CurrentSelectInfo.PlaneDownHitPos = intersectionInfo.HitPosition; CurrentSelectInfo.LastMoveDelta = default(Vector3); diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index b35883486..5d3c5e029 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit b3588348683eeca5d1308dc9a0c7179c2488835f +Subproject commit 5d3c5e0290472cddbe0abc95ad8ef99559ea82b4