From cbeb86d3f12ab767aae7e634968f65be5c36b3a4 Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Wed, 19 Feb 2020 18:19:17 -0800 Subject: [PATCH] Mesh reduce is working now (a bit) --- .../ApplicationView/ApplicationController.cs | 16 ++- .../EditableTypes/MeshExtensions.cs | 50 ++++++++ .../Operations/DecimateObject3D.cs | 119 ++++++++++++++++++ .../Operations/HollowOutObject3D.cs | 71 ++--------- MatterControlLib/MatterControlLib.csproj | 1 + 5 files changed, 192 insertions(+), 65 deletions(-) create mode 100644 MatterControlLib/DesignTools/EditableTypes/MeshExtensions.cs create mode 100644 MatterControlLib/DesignTools/Operations/DecimateObject3D.cs diff --git a/MatterControlLib/ApplicationView/ApplicationController.cs b/MatterControlLib/ApplicationView/ApplicationController.cs index cbebf7870..ba2de3c6d 100644 --- a/MatterControlLib/ApplicationView/ApplicationController.cs +++ b/MatterControlLib/ApplicationView/ApplicationController.cs @@ -954,8 +954,20 @@ namespace MatterHackers.MatterControl TitleResolver = () => "Hollow Out".Localize(), Action = (sceneContext) => { - var inflate = new HollowOutObject3D(); - inflate.WrapSelectedItemAndSelect(sceneContext.Scene); + var hollowOut = new HollowOutObject3D(); + hollowOut.WrapSelectedItemAndSelect(sceneContext.Scene); + }, + Icon = (invertIcon) => AggContext.StaticData.LoadIcon("pinch.png", 16, 16, invertIcon), + IsEnabled = (sceneContext) => sceneContext.Scene.SelectedItem != null, + }, + new SceneSelectionOperation() + { + OperationType = typeof(DecimateObject3D), + TitleResolver = () => "Reduce".Localize(), + Action = (sceneContext) => + { + var hollowOut = new DecimateObject3D(); + hollowOut.WrapSelectedItemAndSelect(sceneContext.Scene); }, Icon = (invertIcon) => AggContext.StaticData.LoadIcon("pinch.png", 16, 16, invertIcon), IsEnabled = (sceneContext) => sceneContext.Scene.SelectedItem != null, diff --git a/MatterControlLib/DesignTools/EditableTypes/MeshExtensions.cs b/MatterControlLib/DesignTools/EditableTypes/MeshExtensions.cs new file mode 100644 index 000000000..e09b0d650 --- /dev/null +++ b/MatterControlLib/DesignTools/EditableTypes/MeshExtensions.cs @@ -0,0 +1,50 @@ +using System; +using g3; +using MatterHackers.PolygonMesh; +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.DesignTools +{ + public static class MeshExtensions + { + public static DMesh3 ToDMesh3(this Mesh inMesh) + { + var outMesh = new DMesh3(); + foreach (var vertex in inMesh.Vertices) + { + outMesh.AppendVertex(new Vector3d(vertex.X, vertex.Y, vertex.Z)); + } + + foreach (var face in inMesh.Faces) + { + outMesh.AppendTriangle(face.v0, face.v1, face.v2); + } + + return outMesh; + } + + public static Mesh ToMesh(this DMesh3 mesh) + { + var outMesh = new Mesh(); + int[] mapV = new int[mesh.MaxVertexID]; + int nAccumCountV = 0; + foreach (int vi in mesh.VertexIndices()) + { + mapV[vi] = nAccumCountV++; + Vector3d v = mesh.GetVertex(vi); + outMesh.Vertices.Add(new Vector3(v[0], v[1], v[2])); + } + + foreach (int ti in mesh.TriangleIndices()) + { + Index3i t = mesh.GetTriangle(ti); + t[0] = mapV[t[0]]; + t[1] = mapV[t[1]]; + t[2] = mapV[t[2]]; + outMesh.Faces.Add(t[0], t[1], t[2], outMesh.Vertices); + } + + return outMesh; + } + } +} diff --git a/MatterControlLib/DesignTools/Operations/DecimateObject3D.cs b/MatterControlLib/DesignTools/Operations/DecimateObject3D.cs new file mode 100644 index 000000000..548a17654 --- /dev/null +++ b/MatterControlLib/DesignTools/Operations/DecimateObject3D.cs @@ -0,0 +1,119 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +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.Threading.Tasks; +using g3; +using MatterHackers.DataConverters3D; +using MatterHackers.Localizations; +using MatterHackers.MatterControl.DesignTools.Operations; +using MatterHackers.PolygonMesh; +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.DesignTools +{ + public class DecimateObject3D : OperationSourceContainerObject3D + { + public DecimateObject3D() + { + Name = "Reduce".Localize(); + } + + public double ReduceRatio { get; set; } = .9; + + public bool MaintainSurface { get; set; } = true; + + public bool PreserveBoundries { get; set; } = true; + + public Mesh Reduce(Mesh inMesh) + { + DMesh3 mesh = inMesh.ToDMesh3(); + + MeshProjectionTarget target = null; + + if (MaintainSurface) + { + var tree = new DMeshAABBTree3(new DMesh3(mesh)); + tree.Build(); + target = new MeshProjectionTarget(tree.Mesh, tree); + } + + Reducer reducer = new Reducer(mesh); + if (PreserveBoundries) + { + reducer.SetExternalConstraints(new MeshConstraints()); + MeshConstraintUtil.FixAllBoundaryEdges(reducer.Constraints, mesh); + } + + if (target != null) + { + reducer.SetProjectionTarget(target); + reducer.ProjectionMode = Reducer.TargetProjectionMode.Inline; + } + + reducer.ReduceToTriangleCount(Math.Max(4, (int)(mesh.TriangleCount * ReduceRatio))); + + return reducer.Mesh.ToMesh(); + } + + public override Task Rebuild() + { + this.DebugDepth("Rebuild"); + + var rebuildLocks = this.RebuilLockAll(); + + return ApplicationController.Instance.Tasks.Execute( + "Reduce".Localize(), + null, + (reporter, cancellationToken) => + { + SourceContainer.Visible = true; + RemoveAllButSource(); + + foreach (var sourceItem in SourceContainer.VisibleMeshes()) + { + var originalMesh = sourceItem.Mesh; + var reducedMesh = Reduce(originalMesh); + + var newMesh = new Object3D() + { + Mesh = reducedMesh + }; + newMesh.CopyWorldProperties(sourceItem, this, Object3DPropertyFlags.All); + this.Children.Add(newMesh); + } + + SourceContainer.Visible = false; + rebuildLocks.Dispose(); + Invalidate(InvalidateType.Children); + return Task.CompletedTask; + }); + } + } +} \ No newline at end of file diff --git a/MatterControlLib/DesignTools/Operations/HollowOutObject3D.cs b/MatterControlLib/DesignTools/Operations/HollowOutObject3D.cs index 058af12a8..2a9111dc2 100644 --- a/MatterControlLib/DesignTools/Operations/HollowOutObject3D.cs +++ b/MatterControlLib/DesignTools/Operations/HollowOutObject3D.cs @@ -27,16 +27,13 @@ of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ +using System.ComponentModel; +using System.Threading.Tasks; using g3; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; using MatterHackers.MatterControl.DesignTools.Operations; using MatterHackers.PolygonMesh; -using MatterHackers.VectorMath; -using System; -using System.ComponentModel; -using System.Threading; -using System.Threading.Tasks; namespace MatterHackers.MatterControl.DesignTools { @@ -50,20 +47,9 @@ namespace MatterHackers.MatterControl.DesignTools [DisplayName("Back Ratio")] public double PinchRatio { get; set; } = .5; - public void HollowOut() + public Mesh HollowOut(Mesh inMesh) { - - } - - /// - /// Good for reducing a mesh. - /// http://www.gradientspace.com/tutorials/2017/8/30/mesh-simplification - /// - /// - /// - public Mesh Reduce(Mesh inMesh) - { - DMesh3 mesh = MeshToDMesh3(inMesh); + DMesh3 mesh = inMesh.ToDMesh3(); var maintainSurface = true; @@ -92,17 +78,7 @@ namespace MatterHackers.MatterControl.DesignTools reducer.ReduceToTriangleCount(500); - return DMesh3ToMesh(reducer.Mesh); - } - - private DMesh3 MeshToDMesh3(Mesh inMesh) - { - throw new NotImplementedException(); - } - - private Mesh DMesh3ToMesh(DMesh3 mesh) - { - throw new NotImplementedException(); + return reducer.Mesh.ToMesh(); } public override Task Rebuild() @@ -112,57 +88,26 @@ namespace MatterHackers.MatterControl.DesignTools var rebuildLocks = this.RebuilLockAll(); return ApplicationController.Instance.Tasks.Execute( - "Pinch".Localize(), + "Reduce".Localize(), null, (reporter, cancellationToken) => { SourceContainer.Visible = true; RemoveAllButSource(); - // remember the current matrix then clear it so the parts will rotate at the original wrapped position - var currentMatrix = Matrix; - Matrix = Matrix4X4.Identity; - - var aabb = SourceContainer.GetAxisAlignedBoundingBox(); - foreach (var sourceItem in SourceContainer.VisibleMeshes()) { var originalMesh = sourceItem.Mesh; - var transformedMesh = originalMesh.Copy(CancellationToken.None); - var itemMatrix = sourceItem.WorldMatrix(SourceContainer); - var invItemMatrix = itemMatrix.Inverted; - - for (int i = 0; i < originalMesh.Vertices.Count; i++) - { - var pos = originalMesh.Vertices[i]; - pos = pos.Transform(itemMatrix); - - var ratioToApply = PinchRatio; - - var distFromCenter = pos.X - aabb.Center.X; - var distanceToPinch = distFromCenter * (1 - PinchRatio); - var delta = (aabb.Center.X + distFromCenter * ratioToApply) - pos.X; - - // find out how much to pinch based on y position - var amountOfRatio = (pos.Y - aabb.MinXYZ.Y) / aabb.YSize; - - var newPos = new Vector3Float(pos.X + delta * amountOfRatio, pos.Y, pos.Z); - - transformedMesh.Vertices[i] = newPos.Transform(invItemMatrix); - } - - transformedMesh.CalculateNormals(); + var reducedMesh = HollowOut(originalMesh); var newMesh = new Object3D() { - Mesh = transformedMesh + Mesh = reducedMesh }; newMesh.CopyWorldProperties(sourceItem, this, Object3DPropertyFlags.All); this.Children.Add(newMesh); } - // set the matrix back - Matrix = currentMatrix; SourceContainer.Visible = false; rebuildLocks.Dispose(); Invalidate(InvalidateType.Children); diff --git a/MatterControlLib/MatterControlLib.csproj b/MatterControlLib/MatterControlLib.csproj index d239a9cc5..5051ac0b5 100644 --- a/MatterControlLib/MatterControlLib.csproj +++ b/MatterControlLib/MatterControlLib.csproj @@ -79,6 +79,7 @@ +