Beispiel #1
0
 public MarchingCubes()
 {
     // initialize w/ a basic sphere example
     Implicit = new ImplicitSphere3d();
     Bounds   = new AxisAlignedBox3d(Vector3d.Zero, 8);
     CubeSize = 0.25;
 }
Beispiel #2
0
 public WindingFieldImplicit(ImplicitFunction3d wf, double isoValue)
 {
     WindingF = wf;
     IsoValue = isoValue;
 }
Beispiel #3
0
        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;
        }