Exemple #1
0
        void cache_input_sdfs_bounded()
        {
            if (cached_bounded_sdfs == null)
            {
                cached_bounded_sdfs        = new MeshSignedDistanceGrid[mesh_sources.Count];
                cached_bounded_sdf_maxdist = new double[mesh_sources.Count];
            }
            cache_bvtrees(false);

            double falloff_distance = blend_falloff;

            gParallel.ForEach(Interval1i.Range(mesh_sources.Count), (k) => {
                if (falloff_distance > cached_bounded_sdf_maxdist[k])
                {
                    cached_bounded_sdfs[k] = null;
                }

                // [TODO] we could expand via flood-fill here instead of throwing away all previously computed!

                if (cached_bounded_sdfs[k] != null)
                {
                    return;
                }
                if (is_invalidated())
                {
                    return;
                }

                int exact_cells = (int)(falloff_distance / grid_cell_size) + 2;

                DMesh3 source_mesh         = mesh_sources[k].GetDMeshUnsafe();
                DMeshAABBTree3 use_spatial = GenerateClosedMeshOp.MeshSDFShouldUseSpatial(
                    cached_bvtrees[k], exact_cells, grid_cell_size, source_edge_stats[k].z);

                MeshSignedDistanceGrid sdf = new MeshSignedDistanceGrid(source_mesh, grid_cell_size, use_spatial)
                {
                    ExactBandWidth = exact_cells
                };
                if (use_spatial != null)
                {
                    sdf.NarrowBandMaxDistance = falloff_distance + grid_cell_size;
                    sdf.ComputeMode           = MeshSignedDistanceGrid.ComputeModes.NarrowBand_SpatialFloodFill;
                }
                sdf.CancelF = is_invalidated;
                sdf.Compute();
                if (is_invalidated())
                {
                    return;
                }

                cached_bounded_sdfs[k]        = sdf;
                cached_bounded_sdf_maxdist[k] = falloff_distance;
            });
        }
Exemple #2
0
        protected virtual void update_level_set()
        {
            double unsigned_offset = Math.Abs(offset_distance);

            if (cached_sdf == null ||
                unsigned_offset > cached_sdf_max_offset ||
                grid_cell_size != cached_sdf.CellSize)
            {
                DMesh3 meshIn      = MeshSource.GetDMeshUnsafe();
                int    exact_cells = (int)(unsigned_offset / grid_cell_size) + 1;

                // only use spatial DS if we are computing enough cells
                DMeshAABBTree3 use_spatial = GenerateClosedMeshOp.MeshSDFShouldUseSpatial(
                    input_spatial, exact_cells, grid_cell_size, input_mesh_edge_stats.z);
                MeshSignedDistanceGrid sdf = new MeshSignedDistanceGrid(meshIn, grid_cell_size, use_spatial)
                {
                    ExactBandWidth = exact_cells
                };
                if (use_spatial != null)
                {
                    sdf.NarrowBandMaxDistance = unsigned_offset + grid_cell_size;
                    sdf.ComputeMode           = MeshSignedDistanceGrid.ComputeModes.NarrowBand_SpatialFloodFill;
                }

                sdf.CancelF = is_invalidated;
                sdf.Compute();
                if (is_invalidated())
                {
                    return;
                }
                cached_sdf            = sdf;
                cached_sdf_max_offset = unsigned_offset;
                cached_sdf_bounds     = meshIn.CachedBounds;
            }

            var           iso = new DenseGridTrilinearImplicit(cached_sdf.Grid, cached_sdf.GridOrigin, cached_sdf.CellSize);
            MarchingCubes c   = new MarchingCubes();

            c.Implicit = iso;
            c.IsoValue = offset_distance;
            c.Bounds   = cached_sdf_bounds;
            c.CubeSize = mesh_cell_size;
            c.Bounds.Expand(offset_distance + 3 * c.CubeSize);
            c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps;
            c.RootModeSteps = 5;

            c.CancelF = is_invalidated;
            c.Generate();
            if (is_invalidated())
            {
                return;
            }

            Reducer r = new Reducer(c.Mesh);

            r.FastCollapsePass(c.CubeSize * 0.5, 3, true);
            if (is_invalidated())
            {
                return;
            }

            if (min_component_volume > 0)
            {
                MeshEditor.RemoveSmallComponents(c.Mesh, min_component_volume, min_component_volume);
            }
            if (is_invalidated())
            {
                return;
            }

            ResultMesh = c.Mesh;
        }
        protected virtual DMesh3 update_step_2(DMesh3 meshIn)
        {
            double unsigned_offset = Math.Abs(distance);
            int    exact_cells     = (int)(unsigned_offset / grid_cell_size) + 1;

            // only use spatial DS if we are computing enough cells
            bool compute_spatial = GenerateClosedMeshOp.MeshSDFShouldUseSpatial(
                input_spatial, exact_cells, grid_cell_size, input_mesh_edge_stats.z) != null;
            DMeshAABBTree3         use_spatial = (compute_spatial) ? new DMeshAABBTree3(meshIn, true) : null;
            MeshSignedDistanceGrid sdf         = new MeshSignedDistanceGrid(meshIn, grid_cell_size, use_spatial)
            {
                ExactBandWidth = exact_cells
            };

            if (use_spatial != null)
            {
                sdf.NarrowBandMaxDistance = unsigned_offset + grid_cell_size;
                sdf.ComputeMode           = MeshSignedDistanceGrid.ComputeModes.NarrowBand_SpatialFloodFill;
            }

            sdf.CancelF = is_invalidated;
            sdf.Compute();
            if (is_invalidated())
            {
                return(null);
            }

            var           iso = new DenseGridTrilinearImplicit(sdf.Grid, sdf.GridOrigin, sdf.CellSize);
            MarchingCubes c   = new MarchingCubes();

            c.Implicit = iso;

            if (op_type == OperationTypes.Close)
            {
                c.IsoValue = -distance;
            }
            else
            {
                c.IsoValue = distance;
            }

            c.Bounds   = cached_sdf_bounds;
            c.CubeSize = mesh_cell_size;
            c.Bounds.Expand(distance + 3 * c.CubeSize);
            c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps;
            c.RootModeSteps = 5;

            c.CancelF = is_invalidated;
            c.Generate();
            if (is_invalidated())
            {
                return(null);
            }

            Reducer r = new Reducer(c.Mesh);

            r.FastCollapsePass(c.CubeSize * 0.5, 3, true);
            if (is_invalidated())
            {
                return(null);
            }

            if (min_component_volume > 0)
            {
                MeshEditor.RemoveSmallComponents(c.Mesh, min_component_volume, min_component_volume);
            }
            if (is_invalidated())
            {
                return(null);
            }

            return(c.Mesh);
        }
Exemple #4
0
        protected virtual void compute_shell_distancefield()
        {
            if (cached_is_closed == false)
            {
                compute_shell_distancefield_unsigned();
                return;
            }

            double     offset_distance = shell_thickness;
            Interval1d shell_range     = new Interval1d(0, offset_distance);

            if (shell_direction == ShellDirections.Symmetric)
            {
                shell_range = new Interval1d(-offset_distance / 2, offset_distance / 2);
            }
            else if (shell_direction == ShellDirections.Inner)
            {
                shell_range     = new Interval1d(-offset_distance, 0);
                offset_distance = -offset_distance;
            }


            if (cached_sdf == null ||
                shell_thickness > cached_sdf_max_offset ||
                grid_cell_size != cached_sdf.CellSize)
            {
                DMesh3 meshIn      = MeshSource.GetDMeshUnsafe();
                int    exact_cells = (int)((shell_thickness) / grid_cell_size) + 1;

                // only use spatial DS if we are computing enough cells
                DMeshAABBTree3         use_spatial = GenerateClosedMeshOp.MeshSDFShouldUseSpatial(input_spatial, exact_cells, grid_cell_size, input_mesh_edge_stats.z);
                MeshSignedDistanceGrid sdf         = new MeshSignedDistanceGrid(meshIn, grid_cell_size, use_spatial)
                {
                    ExactBandWidth = exact_cells
                };
                if (use_spatial != null)
                {
                    sdf.NarrowBandMaxDistance = shell_thickness + grid_cell_size;
                    sdf.ComputeMode           = MeshSignedDistanceGrid.ComputeModes.NarrowBand_SpatialFloodFill;
                }

                sdf.CancelF = is_invalidated;
                sdf.Compute();
                if (is_invalidated())
                {
                    return;
                }
                cached_sdf            = sdf;
                cached_sdf_max_offset = shell_thickness;
                cached_sdf_bounds     = meshIn.CachedBounds;
            }

            var iso = new DenseGridTrilinearImplicit(cached_sdf.Grid, cached_sdf.GridOrigin, cached_sdf.CellSize);
            BoundedImplicitFunction3d shell_field = (shell_direction == ShellDirections.Symmetric) ?
                                                    (BoundedImplicitFunction3d) new ImplicitShell3d()
            {
                A = iso, Inside = shell_range
            } :
            (BoundedImplicitFunction3d) new ImplicitOffset3d()
            {
                A = iso, Offset = offset_distance
            };
            //var shell_field = new ImplicitShell3d() { A = iso, Inside = shell_range };
            //BoundedImplicitFunction3d shell_field = (signed_field) ?
            //    (BoundedImplicitFunction3d)new ImplicitShell3d() { A = iso, Inside = shell_range } :
            //    (BoundedImplicitFunction3d)new ImplicitOffset3d() { A = iso, Offset = offset_distance };
            //ImplicitOffset3d offset = new ImplicitOffset3d() { A = iso, Offset = offset_distance };

            MarchingCubes c = new MarchingCubes();

            c.Implicit = shell_field;
            c.IsoValue = 0;
            c.Bounds   = cached_sdf_bounds;
            c.CubeSize = mesh_cell_size;
            c.Bounds.Expand(offset_distance + 3 * c.CubeSize);
            c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps;
            c.RootModeSteps = 5;

            c.CancelF = is_invalidated;
            c.Generate();
            if (is_invalidated())
            {
                return;
            }

            Reducer r = new Reducer(c.Mesh);

            r.FastCollapsePass(c.CubeSize * 0.5, 3, true);
            if (is_invalidated())
            {
                return;
            }

            if (min_component_volume > 0)
            {
                MeshEditor.RemoveSmallComponents(c.Mesh, min_component_volume, min_component_volume);
            }
            if (is_invalidated())
            {
                return;
            }

            if (shell_surface_only)
            {
                if (shell_direction == ShellDirections.Inner || shell_direction == ShellDirections.Outer)
                {
                    c.Mesh.AttachMetadata("is_partial", new object());
                }
            }

            ResultMesh = c.Mesh;
        }
        protected virtual void compute_hollow()
        {
            double offset_distance = -wall_thickness;

            if (cached_sdf == null ||
                wall_thickness > cached_sdf_max_offset ||
                grid_cell_size != cached_sdf.CellSize)
            {
                DMesh3 meshIn      = MeshSource.GetDMeshUnsafe();
                int    exact_cells = (int)((wall_thickness) / grid_cell_size) + 1;

                // only use spatial DS if we are computing enough cells
                DMeshAABBTree3         use_spatial = GenerateClosedMeshOp.MeshSDFShouldUseSpatial(input_spatial, exact_cells, grid_cell_size, input_mesh_edge_stats.z);
                MeshSignedDistanceGrid sdf         = new MeshSignedDistanceGrid(meshIn, grid_cell_size, use_spatial)
                {
                    ExactBandWidth = exact_cells
                };
                if (use_spatial != null)
                {
                    sdf.NarrowBandMaxDistance = wall_thickness + grid_cell_size;
                    sdf.ComputeMode           = MeshSignedDistanceGrid.ComputeModes.NarrowBand_SpatialFloodFill;
                }

                sdf.CancelF = is_invalidated;
                sdf.Compute();
                if (is_invalidated())
                {
                    return;
                }
                cached_sdf            = sdf;
                cached_sdf_max_offset = wall_thickness;
                cached_sdf_bounds     = meshIn.CachedBounds;
            }

            var iso = new DenseGridTrilinearImplicit(cached_sdf.Grid, cached_sdf.GridOrigin, cached_sdf.CellSize);
            ImplicitOffset3d shell_field = new ImplicitOffset3d()
            {
                A = iso, Offset = offset_distance
            };
            ImplicitFunction3d use_iso = shell_field;


            if (enable_infill)
            {
                GridDistanceField grid_df = new GridDistanceField()
                {
                    CellSize = infill_spacing,
                    Radius   = infill_thickness * 0.5,
                    Origin   = cached_sdf.GridOrigin
                };
                ImplicitDifference3d diff = new ImplicitDifference3d()
                {
                    A = shell_field, B = grid_df
                };
                use_iso = diff;
            }


            MarchingCubes c = new MarchingCubes();

            c.Implicit = use_iso;
            c.IsoValue = 0;
            c.Bounds   = cached_sdf_bounds;
            c.CubeSize = mesh_cell_size;
            c.Bounds.Expand(offset_distance + 3 * c.CubeSize);
            c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps;
            c.RootModeSteps = 5;

            c.CancelF = is_invalidated;
            c.Generate();
            if (is_invalidated())
            {
                return;
            }

            Reducer r = new Reducer(c.Mesh);

            r.FastCollapsePass(c.CubeSize * 0.5, 3, true);
            if (is_invalidated())
            {
                return;
            }

            //r.ReduceToTriangleCount(c.Mesh.TriangleCount / 5);
            //if (is_invalidated())
            //    return;

            if (min_component_volume > 0)
            {
                MeshEditor.RemoveSmallComponents(c.Mesh, min_component_volume, min_component_volume);
            }
            if (is_invalidated())
            {
                return;
            }

            c.Mesh.AttachMetadata("is_partial", new object());

            ResultMesh = c.Mesh;
        }