/// <summary> /// compute offset meshes as simple extrusions /// </summary> void compute_offset_meshes_nosdf() { if (cached_inner_sdf_offset != inner_offset) { InnerOffsetMesh = new DMesh3(cachedInputMesh); MeshTransforms.FromFrame(InnerOffsetMesh, cachedInputsTransform); MeshNormals.QuickCompute(InnerOffsetMesh); MeshTransforms.VertexNormalOffset(InnerOffsetMesh, inner_offset); Reducer reducer = new Reducer(InnerOffsetMesh); reducer.ReduceToTriangleCount(5000); InnerOffsetMeshSpatial = new DMeshAABBTree3(InnerOffsetMesh, true); cached_inner_sdf_offset = inner_offset; } double max_offset = inner_offset + thickness; if (cached_outer_sdf_offset != max_offset) { OuterOffsetMesh = new DMesh3(cachedInputMesh); MeshTransforms.FromFrame(OuterOffsetMesh, cachedInputsTransform); MeshNormals.QuickCompute(OuterOffsetMesh); MeshTransforms.VertexNormalOffset(OuterOffsetMesh, max_offset); Reducer reducer = new Reducer(OuterOffsetMesh); reducer.ReduceToTriangleCount(5000); OuterOffsetMeshSpatial = new DMeshAABBTree3(OuterOffsetMesh, true); cached_outer_sdf_offset = max_offset; } //Util.WriteDebugMesh(MeshSource.GetIMesh(), "c:\\scratch\\__OFFESTS_orig.obj"); //Util.WriteDebugMesh(InnerOffsetMesh, "c:\\scratch\\__OFFESTS_inner.obj"); //Util.WriteDebugMesh(OuterOffsetMesh, "c:\\scratch\\__OFFESTS_outer.obj"); }
void compute_trimmed_mesh() { // curve is on base leg, map to deformed leg // [TODO] really should be doing this via deformation, rather than nearest-point DCurve3 curve = new DCurve3(CurveSource.GetICurve()); for (int i = 0; i < curve.VertexCount; ++i) { curve[i] = MeshQueries.NearestPointFrame(cachedInputMesh, cachedInputMeshSpatial, curve[i]).Origin; } TrimmedMesh = new DMesh3(cachedInputMesh); TrimmedMesh.EnableTriangleGroups(0); AxisAlignedBox3d bounds = TrimmedMesh.CachedBounds; // try to find seed based on raycast, which doesn't always work. // Note that seed is the seed for the *eroded* region, not the kept region Vector3d basePt = bounds.Center + 10 * bounds.Extents.y * Vector3d.AxisY; int hit_tid = cachedInputMeshSpatial.FindNearestHitTriangle(new Ray3d(basePt, -Vector3d.AxisY)); Vector3d seed = cachedInputMesh.GetTriCentroid(hit_tid); if (flip_trim_side) { basePt = bounds.Center - 10 * bounds.Extents.y * Vector3d.AxisY; hit_tid = cachedInputMeshSpatial.FindNearestHitTriangle(new Ray3d(basePt, Vector3d.AxisY)); seed = cachedInputMesh.GetTriCentroid(hit_tid); } MeshTrimLoop trim = new MeshTrimLoop(TrimmedMesh, curve, seed, cachedInputMeshSpatial); trim.Trim(); if (TrimmedMesh.HasVertexColors == false) { TrimmedMesh.EnableVertexColors(SocketVertexColor); } else { foreach (int vid in TrimmedMesh.VertexIndices()) { TrimmedMesh.SetVertexColor(vid, SocketVertexColor); } } MeshTransforms.FromFrame(TrimmedMesh, cachedInputsTransform); }
public IOWriteResult RunBackgroundWrite() { // transform meshes gParallel.ForEach(Interval1i.Range(ExportMeshes.Length), (i) => { if (MeshFrames[i].Origin != Vector3f.Zero || MeshFrames[i].Rotation != Quaternionf.Identity) { MeshTransforms.FromFrame(ExportMeshes[i], MeshFrames[i]); } MeshTransforms.FlipLeftRightCoordSystems(ExportMeshes[i]); if (ExportYUp == false) { MeshTransforms.ConvertYUpToZUp(ExportMeshes[i]); } }); List <WriteMesh> writeMeshes = new List <WriteMesh>(); for (int i = 0; i < ExportMeshes.Length; ++i) { writeMeshes.Add(new WriteMesh(ExportMeshes[i])); } WriteOptions options = WriteOptions.Defaults; options.bWriteBinary = true; options.ProgressFunc = BackgroundProgressFunc; StandardMeshWriter writer = new StandardMeshWriter(); IOWriteResult result = writer.Write(WritePath, writeMeshes, options); return(result); }
public void Compute() { int N = meshToScene.Length; slicer = new MeshPlanarSlicerPro() { LayerHeightMM = CC.Settings.LayerHeightMM, // [RMS] 1.5 here is a hack. If we don't leave a bit of space then often the filament gets squeezed right at // inside/outside transitions, which is bad. Need a better way to handle. OpenPathDefaultWidthMM = CC.Settings.NozzleDiameterMM * 1.5, SetMinZValue = 0, SliceFactoryF = PlanarSlicePro.FactoryF }; if (CC.Settings.OpenMode == PrintSettings.OpenMeshMode.Clipped) { slicer.DefaultOpenPathMode = PrintMeshOptions.OpenPathsModes.Clipped; } else if (CC.Settings.OpenMode == PrintSettings.OpenMeshMode.Embedded) { slicer.DefaultOpenPathMode = PrintMeshOptions.OpenPathsModes.Embedded; } else if (CC.Settings.OpenMode == PrintSettings.OpenMeshMode.Ignored) { slicer.DefaultOpenPathMode = PrintMeshOptions.OpenPathsModes.Ignored; } if (CC.Settings.StartLayers > 0) { int start_layers = CC.Settings.StartLayers; double std_layer_height = CC.Settings.LayerHeightMM; double start_layer_height = CC.Settings.StartLayerHeightMM; slicer.LayerHeightF = (layer_i) => { return((layer_i < start_layers) ? start_layer_height : std_layer_height); }; } try { assembly = new PrintMeshAssembly(); for (int k = 0; k < N; ++k) { DMesh3 mesh = meshCopies[k]; Frame3f mapF = meshToScene[k]; PrintMeshSettings settings = meshSettings[k]; PrintMeshOptions options = new PrintMeshOptions(); options.IsSupport = (settings.ObjectType == PrintMeshSettings.ObjectTypes.Support); options.IsCavity = (settings.ObjectType == PrintMeshSettings.ObjectTypes.Cavity); options.IsCropRegion = (settings.ObjectType == PrintMeshSettings.ObjectTypes.CropRegion); options.IsOpen = false; if (settings.OuterShellOnly) { options.IsOpen = true; } options.OpenPathMode = PrintMeshSettings.Convert(settings.OpenMeshMode); options.Extended = new ExtendedPrintMeshOptions() { ClearanceXY = settings.Clearance, OffsetXY = settings.OffsetXY }; Vector3f scale = localScale[k]; MeshTransforms.Scale(mesh, scale.x, scale.y, scale.z); MeshTransforms.FromFrame(mesh, mapF); MeshTransforms.FlipLeftRightCoordSystems(mesh); MeshTransforms.ConvertYUpToZUp(mesh); MeshAssembly decomposer = new MeshAssembly(mesh); decomposer.HasNoVoids = settings.NoVoids; decomposer.Decompose(); assembly.AddMeshes(decomposer.ClosedSolids, options); PrintMeshOptions openOptions = options.Clone(); assembly.AddMeshes(decomposer.OpenMeshes, openOptions); } if (slicer.Add(assembly) == false) { throw new Exception("error adding PrintMeshAssembly to Slicer!!"); } // set clip box Box2d clip_box = new Box2d(Vector2d.Zero, new Vector2d(CC.Settings.BedSizeXMM / 2, CC.Settings.BedSizeYMM / 2)); slicer.ValidRegions = new List <GeneralPolygon2d>() { new GeneralPolygon2d(new Polygon2d(clip_box.ComputeVertices())) }; result = slicer.Compute(); Success = true; } catch (Exception e) { DebugUtil.Log("GeometrySlicer.Compute: exception: " + e.Message); Success = false; } Finished = true; }
/// <summary> /// compute SDF for the scan object, and then compute offset iso-contours /// </summary> void compute_offset_meshes() { int sdf_cells = 128; int mesh_cells = 128; double max_offset = inner_offset + thickness; if (max_offset > cached_sdf_max_offset) { DMesh3 meshIn = new DMesh3(MeshSource.GetIMesh(), MeshHints.IsCompact, MeshComponents.None); MeshTransforms.FromFrame(meshIn, cachedInputsTransform); // [RMS] reduce this mesh? speeds up SDF quite a bit... Reducer r = new Reducer(meshIn); r.ReduceToTriangleCount(2500); double cell_size = meshIn.CachedBounds.MaxDim / sdf_cells; int exact_cells = (int)((max_offset) / cell_size) + 1; MeshSignedDistanceGrid sdf = new MeshSignedDistanceGrid(meshIn, cell_size) { ExactBandWidth = exact_cells }; sdf.Compute(); cached_sdf = sdf; cached_sdf_max_offset = max_offset; cached_sdf_bounds = meshIn.CachedBounds; cached_inner_sdf_offset = 0; cached_outer_sdf_offset = 0; } if (cached_inner_sdf_offset != inner_offset || cached_outer_sdf_offset != max_offset) { var iso = new DenseGridTrilinearImplicit(cached_sdf.Grid, cached_sdf.GridOrigin, cached_sdf.CellSize); MarchingCubes c = new MarchingCubes() { Implicit = iso }; c.Bounds = cached_sdf_bounds; c.CubeSize = c.Bounds.MaxDim / mesh_cells; c.Bounds.Expand(max_offset + 3 * c.CubeSize); if (cached_inner_sdf_offset != inner_offset) { c.IsoValue = inner_offset; c.Generate(); InnerOffsetMesh = c.Mesh; Reducer reducer = new Reducer(InnerOffsetMesh); reducer.ReduceToEdgeLength(c.CubeSize / 2); InnerOffsetMeshSpatial = new DMeshAABBTree3(InnerOffsetMesh, true); cached_inner_sdf_offset = inner_offset; } if (cached_outer_sdf_offset != max_offset) { c.IsoValue = inner_offset + thickness; c.Generate(); OuterOffsetMesh = c.Mesh; Reducer reducer = new Reducer(OuterOffsetMesh); reducer.ReduceToEdgeLength(c.CubeSize / 2); OuterOffsetMeshSpatial = new DMeshAABBTree3(OuterOffsetMesh, true); cached_outer_sdf_offset = max_offset; } } //Util.WriteDebugMesh(MeshSource.GetIMesh(), "c:\\scratch\\__OFFESTS_orig.obj"); //Util.WriteDebugMesh(InnerOffsetMesh, "c:\\scratch\\__OFFESTS_inner.obj"); //Util.WriteDebugMesh(OuterOffsetMesh, "c:\\scratch\\__OFFESTS_outer.obj"); }