Exemple #1
0
        //the Boolean operation
        private static DMesh3 BooleanSubtraction(DMesh3 mesh1, DMesh3 mesh2)
        {
            BoundedImplicitFunction3d meshA = meshToImplicitF(mesh1, 64, 0.2f);
            BoundedImplicitFunction3d meshB = meshToImplicitF(mesh2, 64, 0.2f);

            //take the difference of the bolus mesh minus the tools
            ImplicitDifference3d mesh = new ImplicitDifference3d()
            {
                A = meshA, B = meshB
            };

            //calculate the boolean mesh
            MarchingCubes c = new MarchingCubes();

            c.Implicit      = mesh;
            c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps;
            c.RootModeSteps = 5;
            c.Bounds        = mesh.Bounds();
            c.CubeSize      = c.Bounds.MaxDim / 128;
            c.Bounds.Expand(3 * c.CubeSize);
            c.Generate();
            MeshNormals.QuickCompute(c.Mesh);

            int     triangleCount = c.Mesh.TriangleCount / 2;
            Reducer r             = new Reducer(c.Mesh);

            r.ReduceToTriangleCount(triangleCount);
            return(c.Mesh);
        }
Exemple #2
0
        public static ImplicitDifference3d ImplicitDifference(BoundedImplicitFunction3d meshA, BoundedImplicitFunction3d meshB)
        {
            var diff = new ImplicitDifference3d()
            {
                A = meshA, B = meshB
            };

            return(diff);
        }
        void generate_mesh(DenseGrid3f supportGrid, DenseGridTrilinearImplicit distanceField)
        {
            DenseGridTrilinearImplicit volume = new DenseGridTrilinearImplicit(
                supportGrid, GridOrigin, CellSize);
            BoundedImplicitFunction3d inputF = volume;

            if (SubtractMesh)
            {
                BoundedImplicitFunction3d sub = distanceField;
                if (SubtractMeshOffset > 0)
                {
                    sub = new ImplicitOffset3d()
                    {
                        A = distanceField, Offset = SubtractMeshOffset
                    }
                }
                ;
                ImplicitDifference3d subtract = new ImplicitDifference3d()
                {
                    A = volume, B = sub
                };
                inputF = subtract;
            }

            ImplicitHalfSpace3d cutPlane = new ImplicitHalfSpace3d()
            {
                Origin = Vector3d.Zero, Normal = Vector3d.AxisY
            };
            ImplicitDifference3d cut = new ImplicitDifference3d()
            {
                A = inputF, B = cutPlane
            };

            MarchingCubes mc = new MarchingCubes()
            {
                Implicit = cut, Bounds = grid_bounds, CubeSize = CellSize
            };

            mc.Bounds.Min.y  = -2 * mc.CubeSize;
            mc.Bounds.Min.x -= 2 * mc.CubeSize; mc.Bounds.Min.z -= 2 * mc.CubeSize;
            mc.Bounds.Max.x += 2 * mc.CubeSize; mc.Bounds.Max.z += 2 * mc.CubeSize;
            mc.Generate();

            SupportMesh = mc.Mesh;
        }
    }
        public static void test_marching_cubes_implicits()
        {
            DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj");

            MeshTransforms.Translate(mesh, -mesh.CachedBounds.Center);
            double meshCellsize             = mesh.CachedBounds.MaxDim / 32;
            MeshSignedDistanceGrid levelSet = new MeshSignedDistanceGrid(mesh, meshCellsize);

            levelSet.ExactBandWidth = 3;
            levelSet.UseParallel    = true;
            levelSet.ComputeMode    = MeshSignedDistanceGrid.ComputeModes.NarrowBandOnly;
            levelSet.Compute();
            var meshIso = new DenseGridTrilinearImplicit(levelSet.Grid, levelSet.GridOrigin, levelSet.CellSize);


            ImplicitOffset3d offsetMeshIso = new ImplicitOffset3d()
            {
                A = meshIso, Offset = 2.0
            };

            double           r       = 15.0;
            ImplicitSphere3d sphere1 = new ImplicitSphere3d()
            {
                Origin = Vector3d.Zero,
                Radius = r
            };
            ImplicitSphere3d sphere2 = new ImplicitSphere3d()
            {
                Origin = r * Vector3d.AxisX,
                Radius = r
            };
            ImplicitAxisAlignedBox3d aabox1 = new ImplicitAxisAlignedBox3d()
            {
                AABox = new AxisAlignedBox3d(r * 0.5 * Vector3d.One, r, r * 0.75, r * 0.5)
            };
            ImplicitBox3d box1 = new ImplicitBox3d()
            {
                Box = new Box3d(new Frame3f(r * 0.5 * Vector3d.One, Vector3d.One.Normalized),
                                new Vector3d(r, r * 0.75, r * 0.5))
            };
            ImplicitLine3d line1 = new ImplicitLine3d()
            {
                Segment = new Segment3d(Vector3d.Zero, r * Vector3d.One),
                Radius  = 3.0
            };
            ImplicitHalfSpace3d half1 = new ImplicitHalfSpace3d()
            {
                Origin = Vector3d.Zero, Normal = Vector3d.One.Normalized
            };

            ImplicitUnion3d union = new ImplicitUnion3d()
            {
                A = sphere1, B = line1
            };
            ImplicitDifference3d difference = new ImplicitDifference3d()
            {
                A = meshIso, B = aabox1
            };
            ImplicitIntersection3d intersect = new ImplicitIntersection3d()
            {
                A = meshIso, B = half1
            };
            ImplicitNaryUnion3d nunion = new ImplicitNaryUnion3d()
            {
                Children = new List <BoundedImplicitFunction3d>()
                {
                    offsetMeshIso, sphere1, sphere2
                }
            };
            ImplicitNaryDifference3d ndifference = new ImplicitNaryDifference3d()
            {
                A    = offsetMeshIso,
                BSet = new List <BoundedImplicitFunction3d>()
                {
                    sphere1, sphere2
                }
            };
            ImplicitBlend3d blend = new ImplicitBlend3d()
            {
                A = sphere1, B = sphere2
            };

            BoundedImplicitFunction3d root = intersect;

            AxisAlignedBox3d bounds = root.Bounds();
            int           numcells  = 64;
            MarchingCubes c         = new MarchingCubes();

            c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps;
            c.RootModeSteps = 5;
            c.Implicit      = root;
            c.Bounds        = bounds;
            c.CubeSize      = bounds.MaxDim / numcells;
            c.Bounds.Expand(3 * c.CubeSize);

            c.Generate();

            MeshNormals.QuickCompute(c.Mesh);
            TestUtil.WriteTestOutputMesh(c.Mesh, "marching_cubes_implicit.obj");
        }
        public virtual void Generate()
        {
            AxisAlignedBox3d graphBox = Graph.CachedBounds;

            graphBox.Expand(2 * PostRadius);

            double cellSize = (SamplerCellSizeHint == 0) ? (PostRadius / 5) : SamplerCellSizeHint;
            ImplicitFieldSampler3d sampler = new ImplicitFieldSampler3d(graphBox, cellSize);

            ActualCellSize = cellSize;

            // sample segments into graph
            ImplicitLine3d line = new ImplicitLine3d()
            {
                Radius = PostRadius
            };

            foreach (int eid in Graph.EdgeIndices())
            {
                Index2i  ev = Graph.GetEdgeV(eid);
                Vector3d v0 = Graph.GetVertex(ev.a);
                Vector3d v1 = Graph.GetVertex(ev.b);
                double   r  = PostRadius;

                int upper_vid = (v0.y > v1.y) ? ev.a : ev.b;
                if (TipVertices.Contains(upper_vid))
                {
                    r = TipRadius;
                }

                line.Segment = new Segment3d(v0, v1);
                line.Radius  = r;
                sampler.Sample(line, line.Radius / 2);
            }

            foreach (int vid in GroundVertices)
            {
                Vector3d v = Graph.GetVertex(vid);
                sampler.Sample(new ImplicitSphere3d()
                {
                    Origin = v - (PostRadius / 2) * Vector3d.AxisY, Radius = GroundRadius
                });
            }


            ImplicitHalfSpace3d cutPlane = new ImplicitHalfSpace3d()
            {
                Origin = Vector3d.Zero, Normal = Vector3d.AxisY
            };
            ImplicitDifference3d cut = new ImplicitDifference3d()
            {
                A = sampler.ToImplicit(), B = cutPlane
            };

            MarchingCubes mc = new MarchingCubes()
            {
                Implicit = cut, Bounds = graphBox, CubeSize = PostRadius / 3
            };

            mc.Bounds.Min.y  = -2 * mc.CubeSize;
            mc.Bounds.Min.x -= 2 * mc.CubeSize; mc.Bounds.Min.z -= 2 * mc.CubeSize;
            mc.Bounds.Max.x += 2 * mc.CubeSize; mc.Bounds.Max.z += 2 * mc.CubeSize;
            mc.CancelF       = this.Cancelled;
            mc.Generate();

            ResultMesh = mc.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;
        }