/// <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");
        }
Beispiel #2
0
        private static DMesh3 BooleanIntersection(DMesh3 mesh1, DMesh3 mesh2)
        {
            BoundedImplicitFunction3d meshA = meshToImplicitF(mesh1, 64, 0.2f);
            BoundedImplicitFunction3d meshB = meshToImplicitF(mesh2, 64, 0.2f);

            //take the intersection of the meshes minus the tools
            ImplicitIntersection3d mesh = new ImplicitIntersection3d()
            {
                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);
        }
Beispiel #3
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            DMesh3_goo        gooA = null;
            List <DMesh3_goo> gooB = new List <DMesh3_goo>();
            int numCells           = 64;

            DA.GetData(0, ref gooA);
            DA.GetDataList(1, gooB);
            DA.GetData(2, ref numCells);

            DMesh3        A = new DMesh3(gooA.Value);
            List <DMesh3> B = gooB.Select(x => x.Value).ToList();

            ImplicitNaryDifference3d diff2 = new ImplicitNaryDifference3d();

            diff2.A    = g3ghUtil.MeshToImplicit(A, numCells, 0.2f);
            diff2.BSet = B.Select(x => g3ghUtil.MeshToImplicit(x, numCells, 0.2f)).ToList();

            g3.MarchingCubes c = new g3.MarchingCubes();
            c.Implicit      = diff2;
            c.RootMode      = g3.MarchingCubes.RootfindingModes.Bisection;
            c.RootModeSteps = 5;
            c.Bounds        = diff2.Bounds();
            c.CubeSize      = c.Bounds.MaxDim / numCells;
            c.Bounds.Expand(3 * c.CubeSize);
            c.Generate();

            MeshNormals.QuickCompute(c.Mesh);

            DA.SetData(0, c.Mesh);
        }
        private UnityMesh CreateMesh(List <Vector3d> lPath)
        {
            DMesh3 dMesh = meshGen.CreateMesh(lPath, qPoly.ToList(), tmpSeam);

            // Defer normal calculation if we reduce smoothing later.
            if (triangleReductionFactor > 1f)
            {
                dMesh.ReduceTriangles(triangleReductionFactor, !reduceSmoothing);
            }
            else if (!reduceSmoothing)
            {
                MeshNormals.QuickCompute(dMesh);
            }

            UnityMesh uMesh = dMesh.ToUnityMesh();

            uMesh.seam = meshGen.Seam; // TODO

            if (reduceSmoothing)
            {
                uMesh.IncreaseVertexCount(smoothingThresholdAngle);
            }

            return(uMesh);
        }
Beispiel #5
0
        public DMesh3 BooleanUnion(DMesh3 mesh1, DMesh3 mesh2)
        {
            BoundedImplicitFunction3d meshA = meshToImplicitF(mesh1, 128, 0.2f);
            BoundedImplicitFunction3d meshB = meshToImplicitF(mesh2, 128, 0.2f);

            //take the difference of the bolus mesh minus the tools
            var mesh = new ImplicitUnion3d()
            {
                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 / 96;
            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);
        }
        void update_warp()
        {
            if (warp_dirty == false)
            {
                return;
            }

            DMesh3 mesh = PreviewSO.Mesh;

            foreach (int vid in mesh.VertexIndices())
            {
                mesh.SetVertex(vid, VertexPositions[vid]);
            }

            Frame3f f = bendPlaneGizmoSO.GetLocalFrame(CoordSpace.SceneCoords);

            f = SceneTransforms.SceneToObject(PreviewSO, f);
            BendWarp warp = new BendWarp()
            {
                Mesh      = mesh,
                BendPlane = f,
                BendAngle = bend_angle
            };

            warp.Apply();

            MeshNormals.QuickCompute(mesh);

            PreviewSO.NotifyMeshEdited(true);

            warp_dirty = false;
        }
Beispiel #7
0
        //experimental
        public List <DMesh3> SliceMold(DMesh3 mesh_to_slice, int number_of_slices)
        {
            var meshes = new List <MeshGeometry3D>();

            //convert mesh to DMesh
            DMesh3 mesh = mesh_to_slice;

            //create cube for slicing
            double z_height       = mesh.GetBounds().Max.z - mesh.GetBounds().Min.z;
            double slice_interval = (double)(z_height / number_of_slices);
            double x_size         = mesh.GetBounds().Depth;
            double y_size         = mesh.GetBounds().Width;
            double low_z          = mesh.GetBounds().Min.z;


            //boolean intersection each mesh
            var sliced_meshes = new List <DMesh3>();

            for (int i = 0; i < number_of_slices; i++)
            {
                //create box
                Vector3d centre = new Vector3d(0, 0, low_z + slice_interval / 2 + i * (slice_interval));
                Vector3d extend = new Vector3d(
                    x_size,
                    y_size,
                    slice_interval / 2);

                ImplicitBox3d box = new ImplicitBox3d()
                {
                    Box = new Box3d(centre, extend)
                };

                //boolean overlap
                BoundedImplicitFunction3d meshA = meshToImplicitF(mesh, 64, 0.2f);

                //take the difference of the bolus mesh minus the tools
                ImplicitIntersection3d mesh_result = new ImplicitIntersection3d {
                    A = meshA, B = box
                };

                //calculate the boolean mesh
                MarchingCubes c = new MarchingCubes();
                c.Implicit      = mesh_result;
                c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps;
                c.RootModeSteps = 5;
                c.Bounds        = mesh_result.Bounds();
                c.CubeSize      = c.Bounds.MaxDim / 256;
                c.Bounds.Expand(3 * c.CubeSize);
                c.Generate();
                MeshNormals.QuickCompute(c.Mesh);

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

                sliced_meshes.Add(c.Mesh);
            }

            return(sliced_meshes);
        }
Beispiel #8
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            List <DMesh3_goo> goo = new List <DMesh3_goo>();
            int numCells          = 64;

            DA.GetDataList(0, goo);
            DA.GetData(1, ref numCells);

            ImplicitNaryUnion3d diff2 = new ImplicitNaryUnion3d();

            diff2.Children = goo.Select(x => g3ghUtil.MeshToImplicit(x.Value, numCells, 0.2f)).ToList();

            g3.MarchingCubes c = new g3.MarchingCubes();
            c.Implicit      = diff2;
            c.RootMode      = g3.MarchingCubes.RootfindingModes.Bisection;
            c.RootModeSteps = 5;
            c.Bounds        = diff2.Bounds();
            c.CubeSize      = c.Bounds.MaxDim / numCells;
            c.Bounds.Expand(3 * c.CubeSize);
            c.Generate();

            MeshNormals.QuickCompute(c.Mesh);

            DA.SetData(0, c.Mesh);
        }
    // Use this for initialization
    void Start()
    {
        meshGO = GameObject.Find("sample_mesh");
        Mesh unityMesh = meshGO.GetComponent <MeshFilter>().mesh;

        startMesh = g3UnityUtils.UnityMeshToDMesh(unityMesh);
        double height = startMesh.CachedBounds.Height;

        // find path to sample file
        if (LoadSampleMesh)
        {
            string curPath  = Application.dataPath;
            string filePath = Path.Combine(curPath, Path.Combine("..\\sample_files", SampleFileName));

            // load sample file, convert to unity coordinate system, translate and scale to origin
            startMesh = StandardMeshReader.ReadMesh(filePath);
            if (startMesh == null)
            {
                startMesh = new Sphere3Generator_NormalizedCube().Generate().MakeDMesh();
            }

            if (FlipLeftRight)
            {
                MeshTransforms.FlipLeftRightCoordSystems(startMesh);
            }
            MeshTransforms.Scale(startMesh, height / startMesh.CachedBounds.Height);
            MeshTransforms.Translate(startMesh, -startMesh.CachedBounds.Center);
            MeshNormals.QuickCompute(startMesh);
            g3UnityUtils.SetGOMesh(meshGO, startMesh);
        }
    }
            public override fMesh MakeGeometry(AxisGizmoFlags widget)
            {
                switch (widget)
                {
                case AxisGizmoFlags.AxisTranslateY:
                    if (MyAxisTranslateY == null)
                    {
                        Radial3DArrowGenerator arrowGen = new Radial3DArrowGenerator()
                        {
                            HeadLength = 2.0f, TipRadius = 0.1f, StickLength = 1.5f, Clockwise = true
                        };
                        DMesh3 mesh = arrowGen.Generate().MakeDMesh();
                        MeshNormals.QuickCompute(mesh);
                        MeshTransforms.Translate(mesh, 0.5 * Vector3d.AxisY);
                        DMesh3 flip = new DMesh3(mesh);
                        MeshTransforms.Rotate(flip, Vector3d.Zero, Quaterniond.AxisAngleD(Vector3d.AxisX, 180));
                        MeshEditor.Append(mesh, flip);
                        MyAxisTranslateY = new fMesh(mesh);
                    }
                    return(MyAxisTranslateY);

                default:
                    return(null);
                }
            }
        public virtual void Update()
        {
            base.begin_update();

            if (MeshSource == null)
            {
                throw new Exception("MeshDeformationOp: must set valid MeshSource to compute!");
            }

            IMesh meshIn = MeshSource.GetIMesh();

            DMesh3 mesh = new DMesh3(meshIn, MeshHints.None);

            MeshNormals.QuickCompute(mesh);

            foreach (int vid in mesh.VertexIndices())
            {
                Vector3d v      = mesh.GetVertex(vid);
                Vector3f n      = mesh.GetVertexNormal(vid);
                Vector3d newPos = deformF(v, n, vid);
                mesh.SetVertex(vid, newPos);
            }

            MeshNormals.QuickCompute(mesh);

            DisplacedMesh = mesh;

            base.complete_update();
        }
        void compute_inner_wall()
        {
            if (DebugStep <= 0)
            {
                SocketMesh = new DMesh3(TrimmedMesh);
                return;
            }

            InnerMesh = new DMesh3(TrimmedMesh);

            // compute flare band
            Func <int, double> flareOffsetF = (vid) => { return(0); };

            if (flare_offset > 0 && flare_band_width > 0)
            {
                MeshBoundaryLoops loops = new MeshBoundaryLoops(InnerMesh);
                if (loops.Count != 1)
                {
                    goto done_inner_wall;
                }

                DijkstraGraphDistance dist = DijkstraGraphDistance.MeshVertices(InnerMesh);
                dist.TrackOrder = true;
                foreach (int vid in loops[0].Vertices)
                {
                    dist.AddSeed(vid, 0);
                }
                dist.ComputeToMaxDistance(1.25f * (float)flare_band_width);

                flareOffsetF = (viD) => {
                    float d = dist.GetDistance(viD);
                    if (d < flare_band_width)
                    {
                        double t = d / flare_band_width;
                        t = 1 - t * t;
                        t = t * t * t;
                        return(t * flare_offset);
                    }
                    return(0);
                };
            }


            gParallel.ForEach(InnerMesh.VertexIndices(), (vid) => {
                Vector3d v    = InnerMesh.GetVertex(vid);
                Vector3d n    = InnerMesh.GetVertexNormal(vid);
                double offset = inner_offset + flareOffsetF(vid);
                InnerMesh.SetVertex(vid, v + offset * n);
            });


done_inner_wall:
            MeshNormals.QuickCompute(InnerMesh);
        }
Beispiel #13
0
 public virtual void BakeDisplacements(DMeshSO so, VertexChangeBuilder changeBuilder)
 {
     so.EditAndUpdateMesh((mesh) => {
         foreach (int vid in ModifiedV)
         {
             changeBuilder.SetPosition(vid, Displacements[vid]);
         }
         gParallel.ForEach(ModifiedV, (vid) => {
             MeshNormals.QuickCompute(Mesh, vid);
         });
     }, GeometryEditTypes.VertexDeformation);
 }
Beispiel #14
0
        // generateMeshF() meshes the input implicit function at
        // the given cell resolution, and writes out the resulting mesh
        DMesh3 generatMeshF(BoundedImplicitFunction3d root, int numcells)
        {
            MarchingCubes c = new MarchingCubes();

            c.Implicit      = root;
            c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps; // cube-edge convergence method
            c.RootModeSteps = 5;                                        // number of iterations
            c.Bounds        = root.Bounds();
            c.CubeSize      = c.Bounds.MaxDim / numcells;
            c.Bounds.Expand(3 * c.CubeSize);  // leave a buffer of cells
            c.Generate();
            MeshNormals.QuickCompute(c.Mesh); // generate normals
            return(c.Mesh);                   // write mesh
        }
Beispiel #15
0
        private DMesh3 GenerateMeshBase(BoundedImplicitFunction3d root, AxisAlignedBox3d filterBox)
        {
            MarchingCubes c = new MarchingCubes();

            c.Implicit      = root;
            c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps; // cube-edge convergence method
            c.RootModeSteps = 5;                                        // number of iterations
            c.Bounds        = filterBox;                                //_sideFilterBox;
            c.CubeSize      = _cubeSize / 4.0;
            c.Generate();
            MeshNormals.QuickCompute(c.Mesh);                           // generate normals

            return(c.Mesh);
        }
Beispiel #16
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            return(Task.Run(() =>
            {
                using (RebuildLock())
                {
                    using (new CenterAndHeightMaintainer(this))
                    {
#if true
                        ISdf shape = new Sphere()
                        {
                            Radius = Size
                        };

                        if (Shape == Shapes.Box)
                        {
                            shape = new Box()
                            {
                                Size = new Vector3(Size, Size, Size)
                            };
                        }

                        var bounds = shape.Bounds;
                        bounds.Expand(.1);
                        if (Iterations > 7)
                        {
                            Iterations = 7;
                        }
                        var root = Octree.BuildOctree(shape.Sdf, bounds.MinXYZ, bounds.Size, Iterations, Threshold);

                        Mesh = Octree.GenerateMeshFromOctree(root);
#else
                        var c = new MarchingCubes();
                        c.Generate();
                        MeshNormals.QuickCompute(c.Mesh);                         // generate normals
                        Mesh = c.Mesh.ToMesh();
#endif
                    }
                }

                Invalidate(InvalidateType.DisplayValues);

                Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Mesh));
                return Task.CompletedTask;
            }));
        }
Beispiel #17
0
        public static void test_normals()
        {
            // check that frames are ok
            DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj");

            foreach (int tid in mesh.TriangleIndices())
            {
                Vector3f n = (Vector3f)mesh.GetTriNormal(tid);
                for (int j = 0; j < 3; ++j)
                {
                    Frame3f f = mesh.GetTriFrame(tid, j);
                    if (Math.Abs(f.X.Dot(f.Y)) > MathUtil.ZeroTolerancef ||
                        Math.Abs(f.X.Dot(f.Z)) > MathUtil.ZeroTolerancef ||
                        Math.Abs(f.Y.Dot(f.Z)) > MathUtil.ZeroTolerancef)
                    {
                        throw new Exception("argh");
                    }
                    Vector3f fn = f.Z;
                    if (fn.Dot(n) < 0.99)
                    {
                        throw new Exception("shit");
                    }
                }
            }

            MeshNormals.QuickCompute(mesh);

            foreach (int vid in mesh.VertexIndices())
            {
                Vector3f n = mesh.GetVertexNormal(vid);
                for (int j = 1; j <= 2; ++j)
                {
                    Frame3f  f  = mesh.GetVertexFrame(vid, (j == 1) ? true : false);
                    Vector3f fn = f.GetAxis(j);
                    if (Math.Abs(f.X.Dot(f.Y)) > MathUtil.ZeroTolerancef ||
                        Math.Abs(f.X.Dot(f.Z)) > MathUtil.ZeroTolerancef ||
                        Math.Abs(f.Y.Dot(f.Z)) > MathUtil.ZeroTolerancef)
                    {
                        throw new Exception("argh");
                    }
                    if (fn.Dot(n) < 0.99)
                    {
                        throw new Exception("shit2");
                    }
                }
            }
        }
Beispiel #18
0
        public static DMesh3 GenerateMeshF(BoundedImplicitFunction3d mesh, int num_cells)
        {
            MarchingCubes c = new MarchingCubes();

            c.Implicit      = mesh;
            c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps; // cube-edge convergence method
            c.RootModeSteps = 5;                                        // number of iterations
            c.Bounds        = mesh.Bounds();
            c.CubeSize      = c.Bounds.MaxDim / num_cells;
            c.Bounds.Expand(3 * c.CubeSize);                            // leave a buffer of cells
            c.Generate();
            MeshNormals.QuickCompute(c.Mesh);                           // generate normals

            DMesh3 outputMesh = c.Mesh;

            return(outputMesh);
        }
        protected override void Recompute(DGArguments args)
        {
            OffsetMesh.Copy(CachedValue <DMesh3>(0, args));
            double dist = CachedValue <double>(1, args);

            if (!OffsetMesh.HasVertexNormals)
            {
                MeshNormals.QuickCompute(OffsetMesh);
            }

            foreach (int vid in OffsetMesh.VertexIndices())
            {
                Vector3d v = OffsetMesh.GetVertex(vid);
                Vector3d n = OffsetMesh.GetVertexNormal(vid);
                v += dist * n;
                OffsetMesh.SetVertex(vid, v);
            }
        }
Beispiel #20
0
        public bool Compute()
        {
            DMesh3 copy = new DMesh3(Mesh);

            //Frame3f PlaneO = SceneTransforms.SceneToObject(TargetSO, PlaneS);
            Vector3f PlaneNormal = Plane.GetAxis(nPlaneAxis);

            MeshPlaneCut cut = new MeshPlaneCut(copy, Plane.Origin, PlaneNormal);

            cut.Cut();

            Loops = new DCurve3[cut.CutLoops.Count];
            for (int li = 0; li < cut.CutLoops.Count; ++li)
            {
                EdgeLoop edgeloop = cut.CutLoops[li];
                DCurve3  loop     = MeshUtil.ExtractLoopV(copy, edgeloop.Vertices);

                // [TODO] collapse degenerate points...

                if (NormalOffset > 0)
                {
                    for (int i = 0; i < loop.VertexCount; ++i)
                    {
                        Vector3f n = Vector3f.Zero;
                        if (copy.HasVertexNormals)
                        {
                            n = (Vector3f)copy.GetVertexNormal(edgeloop.Vertices[i]);
                        }
                        else
                        {
                            n = (Vector3f)MeshNormals.QuickCompute(Mesh, edgeloop.Vertices[i]);
                        }

                        n -= n.Dot(PlaneNormal) * PlaneNormal;
                        n.Normalize();
                        loop[i] += NormalOffset * (Vector3d)n;
                    }
                }

                Loops[li] = loop;
            }

            return(Loops.Length > 0);
        }
        private static DMesh3 GenerateMeshF(BoundedImplicitFunction3d root, int numcells)
        {
            var bounds = root.Bounds();

            var c = new MarchingCubes()
            {
                Implicit      = root,
                RootMode      = MarchingCubes.RootfindingModes.LerpSteps,                 // cube-edge convergence method
                RootModeSteps = 5,                                                        // number of iterations
                Bounds        = bounds,
                CubeSize      = bounds.MaxDim / numcells,
            };

            c.Bounds.Expand(3 * c.CubeSize);                                        // leave a buffer of cells
            c.Generate();

            MeshNormals.QuickCompute(c.Mesh);                                       // generate normals
            return(c.Mesh);
        }
Beispiel #22
0
    void MeshReplace()
    {
        Mesh newMesh = new Mesh();

        //The triangles tend to come out reversed, so we need to fix them
        DMesh3 dmesh3 = DMesh3Builder.Build <float, int, float>(verticies, faces);

        MeshNormals.QuickCompute(dmesh3);
        dmesh3.ReverseOrientation(false);

        newMesh.vertices  = verticies.ToVectors().ToArray();
        newMesh.triangles = dmesh3.TrianglesBuffer.ToArray();
        for (int i = 0; i < mesh.uv.Length; i++)
        {
            newMesh.uv[i] = mesh.uv[i];
        }
        newMesh.MarkDynamic();
        GetComponent <MeshFilter>().mesh = newMesh;
    }
Beispiel #23
0
        public static void TestMarchingCubes()
        {
            MarchingCubes mc = new MarchingCubes();

            LocalProfiler p = new LocalProfiler();

            p.Start("GENERATE");
            mc.ParallelCompute = true;
            mc.Generate();
            p.Stop("GENERATE");
            DebugUtil.Log(2, p.AllTimes());

            MeshNormals.QuickCompute(mc.Mesh);

            DebugUtil.WriteDebugMesh(mc.Mesh, "c:\\scratch\\MARCHING_CUBES.obj");

            DMeshSO meshSO = new DMeshSO();

            meshSO.Create(mc.Mesh, CC.ActiveScene.DefaultMeshSOMaterial);
            CC.ActiveScene.AddSceneObject(meshSO, false);
        }
Beispiel #24
0
        public static DMesh3 ReduceTriangles(this DMesh3 dMesh,
                                             int triangleCount,
                                             bool computeNormals      = true,
                                             bool fixAllBoundaryEdges = true)
        {
            Reducer reducer = new Reducer(dMesh);

            if (fixAllBoundaryEdges)
            {
                reducer.SetExternalConstraints(meshConstraints);
                MeshConstraintUtil.FixAllBoundaryEdges(reducer.Constraints, dMesh);
            }
            reducer.ReduceToTriangleCount(triangleCount);

            if (computeNormals)
            {
                MeshNormals.QuickCompute(dMesh);
            }

            return(dMesh);
        }
        public static void test_marching_cubes()
        {
            MarchingCubes c = new MarchingCubes();

            LocalProfiler profiler = new LocalProfiler();

            profiler.Start("Generate");

            c.ParallelCompute = true;
            c.Generate();

            profiler.Stop("Generate");

            System.Console.WriteLine("Tris: {0} Times: {1}", c.Mesh.TriangleCount, profiler.AllTimes());

            Reducer r = new Reducer(c.Mesh);

            r.ReduceToEdgeLength(c.CubeSize * 0.25);

            System.Console.WriteLine("after reduce: {0}", c.Mesh.TriangleCount);

            MeshNormals.QuickCompute(c.Mesh);
            TestUtil.WriteTestOutputMesh(c.Mesh, "marching_cubes.obj");
        }
        public static void test_marching_cubes_demos()
        {
            // generateMeshF() meshes the input implicit function at
            // the given cell resolution, and writes out the resulting mesh
            Action <BoundedImplicitFunction3d, int, string> generateMeshF = (root, numcells, path) => {
                MarchingCubes c = new MarchingCubes();
                c.Implicit      = root;
                c.RootMode      = MarchingCubes.RootfindingModes.LerpSteps; // cube-edge convergence method
                c.RootModeSteps = 5;                                        // number of iterations
                c.Bounds        = root.Bounds();
                c.CubeSize      = c.Bounds.MaxDim / numcells;
                c.Bounds.Expand(3 * c.CubeSize);                                   // leave a buffer of cells
                c.Generate();
                MeshNormals.QuickCompute(c.Mesh);                                  // generate normals
                StandardMeshWriter.WriteMesh(path, c.Mesh, WriteOptions.Defaults); // write mesh
            };

            // meshToImplicitF() generates a narrow-band distance-field and
            // returns it as an implicit surface, that can be combined with other implicits
            Func <DMesh3, int, double, BoundedImplicitFunction3d> meshToImplicitF = (meshIn, numcells, max_offset) => {
                double meshCellsize             = meshIn.CachedBounds.MaxDim / numcells;
                MeshSignedDistanceGrid levelSet = new MeshSignedDistanceGrid(meshIn, meshCellsize);
                levelSet.ExactBandWidth = (int)(max_offset / meshCellsize) + 1;
                levelSet.Compute();
                return(new DenseGridTrilinearImplicit(levelSet.Grid, levelSet.GridOrigin, levelSet.CellSize));
            };

            // meshToBlendImplicitF() computes the full distance-field grid for the input
            // mesh. The bounds are expanded quite a bit to allow for blending,
            // probably more than necessary in most cases
            Func <DMesh3, int, BoundedImplicitFunction3d> meshToBlendImplicitF = (meshIn, numcells) => {
                double meshCellsize             = meshIn.CachedBounds.MaxDim / numcells;
                MeshSignedDistanceGrid levelSet = new MeshSignedDistanceGrid(meshIn, meshCellsize);
                levelSet.ExpandBounds = meshIn.CachedBounds.Diagonal * 0.25;        // need some values outside mesh
                levelSet.ComputeMode  = MeshSignedDistanceGrid.ComputeModes.FullGrid;
                levelSet.Compute();
                return(new DenseGridTrilinearImplicit(levelSet.Grid, levelSet.GridOrigin, levelSet.CellSize));
            };



            // generate union/difference/intersection of sphere and cube

            ImplicitSphere3d sphere = new ImplicitSphere3d()
            {
                Origin = Vector3d.Zero, Radius = 1.0
            };
            ImplicitBox3d box = new ImplicitBox3d()
            {
                Box = new Box3d(new Frame3f(Vector3f.AxisX), 0.5 * Vector3d.One)
            };

            generateMeshF(new ImplicitUnion3d()
            {
                A = sphere, B = box
            }, 128, "c:\\demo\\union.obj");
            generateMeshF(new ImplicitDifference3d()
            {
                A = sphere, B = box
            }, 128, "c:\\demo\\difference.obj");
            generateMeshF(new ImplicitIntersection3d()
            {
                A = sphere, B = box
            }, 128, "c:\\demo\\intersection.obj");


            // generate bunny offset surfaces

            //double offset = 0.2f;
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj");
            //MeshTransforms.Scale(mesh, 3.0 / mesh.CachedBounds.MaxDim);
            //BoundedImplicitFunction3d meshImplicit = meshToImplicitF(mesh, 64, offset);

            //generateMeshF(meshImplicit, 128, "c:\\demo\\mesh.obj");
            //generateMeshF(new ImplicitOffset3d() { A = meshImplicit, Offset = offset }, 128, "c:\\demo\\mesh_outset.obj");
            //generateMeshF(new ImplicitOffset3d() { A = meshImplicit, Offset = -offset }, 128, "c:\\demo\\mesh_inset.obj");


            // compare offset of sharp and smooth union

            //var smooth_union = new ImplicitSmoothDifference3d() { A = sphere, B = box };
            //generateMeshF(smooth_union, 128, "c:\\demo\\smooth_union.obj");
            //generateMeshF(new ImplicitOffset3d() { A = smooth_union, Offset = 0.2 }, 128, "c:\\demo\\smooth_union_offset.obj");

            //var union = new ImplicitUnion3d() { A = sphere, B = box };
            //generateMeshF(new ImplicitOffset3d() { A = union, Offset = offset }, 128, "c:\\demo\\union_offset.obj");


            // blending

            //ImplicitSphere3d sphere1 = new ImplicitSphere3d() {
            //    Origin = Vector3d.Zero, Radius = 1.0
            //};
            //ImplicitSphere3d sphere2 = new ImplicitSphere3d() {
            //    Origin = 1.5 * Vector3d.AxisX, Radius = 1.0
            //};
            //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 1.0 }, 128, "c:\\demo\\blend_1.obj");
            //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 4.0 }, 128, "c:\\demo\\blend_4.obj");
            //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 16.0 }, 128, "c:\\demo\\blend_16.obj");
            //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 64.0 }, 128, "c:\\demo\\blend_64.obj");
            //sphere1.Radius = sphere2.Radius = 2.0f;
            //sphere2.Origin = 1.5 * sphere1.Radius * Vector3d.AxisX;
            //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 1.0 }, 128, "c:\\demo\\blend_2x_1.obj");
            //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 4.0 }, 128, "c:\\demo\\blend_2x_4.obj");
            //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 16.0 }, 128, "c:\\demo\\blend_2x_16.obj");
            //generateMeshF(new ImplicitBlend3d() { A = sphere1, B = sphere2, Blend = 64.0 }, 128, "c:\\demo\\blend_2x_64.obj");


            // mesh blending

            //DMesh3 mesh1 = TestUtil.LoadTestInputMesh("bunny_solid.obj");
            //MeshTransforms.Scale(mesh1, 3.0 / mesh1.CachedBounds.MaxDim);
            //DMesh3 mesh2 = new DMesh3(mesh1);
            //MeshTransforms.Rotate(mesh2, mesh2.CachedBounds.Center, Quaternionf.AxisAngleD(Vector3f.OneNormalized, 45.0f));

            //var meshImplicit1 = meshToImplicitF(mesh1, 64, 0);
            //var meshImplicit2 = meshToImplicitF(mesh2, 64, 0);
            //generateMeshF(new ImplicitBlend3d() { A = meshImplicit1, B = meshImplicit2, Blend = 0.0 }, 256, "c:\\demo\\blend_mesh_union.obj");
            //generateMeshF(new ImplicitBlend3d() { A = meshImplicit1, B = meshImplicit2, Blend = 10.0 }, 256, "c:\\demo\\blend_mesh_bad.obj");

            //var meshFullImplicit1 = meshToBlendImplicitF(mesh1, 64);
            //var meshFullImplicit2 = meshToBlendImplicitF(mesh2, 64);
            //generateMeshF(new ImplicitBlend3d() { A = meshFullImplicit1, B = meshFullImplicit2, Blend = 0.0 }, 256, "c:\\demo\\blend_mesh_union.obj");
            //generateMeshF(new ImplicitBlend3d() { A = meshFullImplicit1, B = meshFullImplicit2, Blend = 1.0 }, 256, "c:\\demo\\blend_mesh_1.obj");
            //generateMeshF(new ImplicitBlend3d() { A = meshFullImplicit1, B = meshFullImplicit2, Blend = 10.0 }, 256, "c:\\demo\\blend_mesh_10.obj");
            //generateMeshF(new ImplicitBlend3d() { A = meshFullImplicit1, B = meshFullImplicit2, Blend = 50.0 }, 256, "c:\\demo\\blend_mesh_100.obj");


            //DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj");
            //MeshTransforms.Scale(mesh, 3.0 / mesh.CachedBounds.MaxDim);
            //MeshTransforms.Translate(mesh, -mesh.CachedBounds.Center);
            //Reducer r = new Reducer(mesh);
            //r.ReduceToTriangleCount(100);

            //double radius = 0.1;
            //List<BoundedImplicitFunction3d> Lines = new List<BoundedImplicitFunction3d>();
            //foreach (Index4i edge_info in mesh.Edges()) {
            //    var segment = new Segment3d(mesh.GetVertex(edge_info.a), mesh.GetVertex(edge_info.b));
            //    Lines.Add(new ImplicitLine3d() { Segment = segment, Radius = radius });
            //}
            //ImplicitNaryUnion3d unionN = new ImplicitNaryUnion3d() { Children = Lines };
            //generateMeshF(unionN, 128, "c:\\demo\\mesh_edges.obj");

            //radius = 0.05;
            //List<BoundedImplicitFunction3d> Elements = new List<BoundedImplicitFunction3d>();
            //foreach (int eid in mesh.EdgeIndices()) {
            //    var segment = new Segment3d(mesh.GetEdgePoint(eid, 0), mesh.GetEdgePoint(eid, 1));
            //    Elements.Add(new ImplicitLine3d() { Segment = segment, Radius = radius });
            //}
            //foreach (Vector3d v in mesh.Vertices())
            //    Elements.Add(new ImplicitSphere3d() { Origin = v, Radius = 2 * radius });
            //generateMeshF(new ImplicitNaryUnion3d() { Children = Elements }, 256, "c:\\demo\\mesh_edges_and_vertices.obj");


            //double lattice_radius = 0.05;
            //double lattice_spacing = 0.4;
            //double shell_thickness = 0.05;
            //int mesh_resolution = 64;   // set to 256 for image quality

            //var shellMeshImplicit = meshToImplicitF(mesh, 128, shell_thickness);
            //double max_dim = mesh.CachedBounds.MaxDim;
            //AxisAlignedBox3d bounds = new AxisAlignedBox3d(mesh.CachedBounds.Center, max_dim / 2);
            //bounds.Expand(2 * lattice_spacing);
            //AxisAlignedBox2d element = new AxisAlignedBox2d(lattice_spacing);
            //AxisAlignedBox2d bounds_xy = new AxisAlignedBox2d(bounds.Min.xy, bounds.Max.xy);
            //AxisAlignedBox2d bounds_xz = new AxisAlignedBox2d(bounds.Min.xz, bounds.Max.xz);
            //AxisAlignedBox2d bounds_yz = new AxisAlignedBox2d(bounds.Min.yz, bounds.Max.yz);

            //List<BoundedImplicitFunction3d> Tiling = new List<BoundedImplicitFunction3d>();
            //foreach (Vector2d uv in TilingUtil.BoundedRegularTiling2(element, bounds_xy, 0)) {
            //    Segment3d seg = new Segment3d(new Vector3d(uv.x, uv.y, bounds.Min.z), new Vector3d(uv.x, uv.y, bounds.Max.z));
            //    Tiling.Add(new ImplicitLine3d() { Segment = seg, Radius = lattice_radius });
            //}
            //foreach (Vector2d uv in TilingUtil.BoundedRegularTiling2(element, bounds_xz, 0)) {
            //    Segment3d seg = new Segment3d(new Vector3d(uv.x, bounds.Min.y, uv.y), new Vector3d(uv.x, bounds.Max.y, uv.y));
            //    Tiling.Add(new ImplicitLine3d() { Segment = seg, Radius = lattice_radius });
            //}
            //foreach (Vector2d uv in TilingUtil.BoundedRegularTiling2(element, bounds_yz, 0)) {
            //    Segment3d seg = new Segment3d(new Vector3d(bounds.Min.x, uv.x, uv.y), new Vector3d(bounds.Max.x, uv.x, uv.y));
            //    Tiling.Add(new ImplicitLine3d() { Segment = seg, Radius = lattice_radius });
            //}
            //ImplicitNaryUnion3d lattice = new ImplicitNaryUnion3d() { Children = Tiling };
            //generateMeshF(lattice, 128, "c:\\demo\\lattice.obj");

            //ImplicitIntersection3d lattice_clipped = new ImplicitIntersection3d() { A = lattice, B = shellMeshImplicit };
            //generateMeshF(lattice_clipped, mesh_resolution, "c:\\demo\\lattice_clipped.obj");

            //var shell = new ImplicitDifference3d() {
            //    A = shellMeshImplicit, B = new ImplicitOffset3d() { A = shellMeshImplicit, Offset = -shell_thickness }
            //};
            //var shell_cut = new ImplicitDifference3d() {
            //    A = shell, B = new ImplicitAxisAlignedBox3d() { AABox = new AxisAlignedBox3d(Vector3d.Zero, max_dim / 2, 0.4, max_dim / 2) }
            //};
            //generateMeshF(new ImplicitUnion3d() { A = lattice_clipped, B = shell_cut }, mesh_resolution, "c:\\demo\\lattice_result.obj");
        }
Beispiel #27
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            DMesh3_goo goo             = null;
            double     lattice_radius  = 0.05;
            double     lattice_spacing = 0.4;
            double     shell_thickness = 0.05;
            int        mesh_resolution = 64;

            DA.GetData(0, ref goo);
            DA.GetData(1, ref lattice_radius);
            DA.GetData(2, ref lattice_spacing);
            DA.GetData(3, ref shell_thickness);
            DA.GetData(4, ref mesh_resolution);

            DMesh3 mesh = new DMesh3(goo.Value);

            var              shellMeshImplicit = g3ghUtil.MeshToImplicit(mesh, 128, shell_thickness);
            double           max_dim           = mesh.CachedBounds.MaxDim;
            AxisAlignedBox3d bounds            = new AxisAlignedBox3d(mesh.CachedBounds.Center, max_dim / 2);

            bounds.Expand(2 * lattice_spacing);
            AxisAlignedBox2d element   = new AxisAlignedBox2d(lattice_spacing);
            AxisAlignedBox2d bounds_xy = new AxisAlignedBox2d(bounds.Min.xy, bounds.Max.xy);
            AxisAlignedBox2d bounds_xz = new AxisAlignedBox2d(bounds.Min.xz, bounds.Max.xz);
            AxisAlignedBox2d bounds_yz = new AxisAlignedBox2d(bounds.Min.yz, bounds.Max.yz);

            List <BoundedImplicitFunction3d> Tiling = new List <BoundedImplicitFunction3d>();

            foreach (g3.Vector2d uv in TilingUtil.BoundedRegularTiling2(element, bounds_xy, 0))
            {
                Segment3d seg = new Segment3d(new g3.Vector3d(uv.x, uv.y, bounds.Min.z), new g3.Vector3d(uv.x, uv.y, bounds.Max.z));
                Tiling.Add(new ImplicitLine3d()
                {
                    Segment = seg, Radius = lattice_radius
                });
            }
            foreach (g3.Vector2d uv in TilingUtil.BoundedRegularTiling2(element, bounds_xz, 0))
            {
                Segment3d seg = new Segment3d(new g3.Vector3d(uv.x, bounds.Min.y, uv.y), new g3.Vector3d(uv.x, bounds.Max.y, uv.y));
                Tiling.Add(new ImplicitLine3d()
                {
                    Segment = seg, Radius = lattice_radius
                });
            }
            foreach (g3.Vector2d uv in TilingUtil.BoundedRegularTiling2(element, bounds_yz, 0))
            {
                Segment3d seg = new Segment3d(new g3.Vector3d(bounds.Min.x, uv.x, uv.y), new g3.Vector3d(bounds.Max.x, uv.x, uv.y));
                Tiling.Add(new ImplicitLine3d()
                {
                    Segment = seg, Radius = lattice_radius
                });
            }

            ImplicitNaryUnion3d lattice = new ImplicitNaryUnion3d()
            {
                Children = Tiling
            };
            ImplicitIntersection3d lattice_clipped = new ImplicitIntersection3d()
            {
                A = lattice, B = shellMeshImplicit
            };

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


            DA.SetData(0, c.Mesh);
        }
Beispiel #28
0
        public bool Apply()
        {
            bool do_checks = false;

            if (do_checks)
            {
                Mesh.CheckValidity();
            }


            /*
             * Remove parts of the mesh we don't want before we bother with anything else
             * TODO: maybe we need to repair orientation first? if we want to use MWN...
             */
            do_remove_inside();
            if (Cancelled())
            {
                return(false);
            }

            int repeat_count = 0;

repeat_all:

            /*
             * make sure orientation of connected components is consistent
             * TODO: what about mobius strip problems?
             */
            repair_orientation(false);
            if (Cancelled())
            {
                return(false);
            }

            /*
             *  Do safe close-cracks to handle easy cases
             */

            repair_cracks(true, RepairTolerance);
            if (Mesh.IsClosed())
            {
                goto all_done;
            }
            if (Cancelled())
            {
                return(false);
            }

            /*
             * Collapse tiny edges and then try easy cases again, and
             * then allow for handling of ambiguous cases
             */

            collapse_all_degenerate_edges(RepairTolerance * 0.5, true);
            if (Cancelled())
            {
                return(false);
            }
            repair_cracks(true, 2 * RepairTolerance);
            if (Cancelled())
            {
                return(false);
            }
            repair_cracks(false, 2 * RepairTolerance);
            if (Cancelled())
            {
                return(false);
            }
            if (Mesh.IsClosed())
            {
                goto all_done;
            }

            /*
             * Possibly we have joined regions with different orientation (is it?), fix that
             * TODO: mobius strips again
             */
            repair_orientation(false);
            if (Cancelled())
            {
                return(false);
            }

            if (do_checks)
            {
                Mesh.CheckValidity();
            }

            // get rid of any remaining single-triangles before we start filling holes
            remove_loners();

            /*
             * Ok, fill simple holes.
             */
            int nRemainingBowties = 0;
            int nHoles; bool bSawSpans;

            fill_trivial_holes(out nHoles, out bSawSpans);
            if (Cancelled())
            {
                return(false);
            }
            if (Mesh.IsClosed())
            {
                goto all_done;
            }

            /*
             * Now fill harder holes. If we saw spans, that means boundary loops could
             * not be resolved in some cases, do we disconnect bowties and try again.
             */
            fill_any_holes(out nHoles, out bSawSpans);
            if (Cancelled())
            {
                return(false);
            }
            if (bSawSpans)
            {
                disconnect_bowties(out nRemainingBowties);
                fill_any_holes(out nHoles, out bSawSpans);
            }
            if (Cancelled())
            {
                return(false);
            }
            if (Mesh.IsClosed())
            {
                goto all_done;
            }

            /*
             * We may have a closed mesh now but it might still have bowties (eg
             * tetrahedra sharing vtx case). So disconnect those.
             */
            disconnect_bowties(out nRemainingBowties);
            if (Cancelled())
            {
                return(false);
            }

            /*
             * If the mesh is not closed, we will do one more round to try again.
             */
            if (repeat_count == 0 && Mesh.IsClosed() == false)
            {
                repeat_count++;
                goto repeat_all;
            }

            /*
             * Ok, we didn't get anywhere on our first repeat. If we are still not
             * closed, we will try deleting boundary triangles and repeating.
             * Repeat this N times.
             */
            if (repeat_count <= ErosionIterations && Mesh.IsClosed() == false)
            {
                repeat_count++;
                MeshFaceSelection bdry_faces = new MeshFaceSelection(Mesh);
                foreach (int eid in MeshIterators.BoundaryEdges(Mesh))
                {
                    bdry_faces.SelectEdgeTris(eid);
                }
                MeshEditor.RemoveTriangles(Mesh, bdry_faces, true);
                goto repeat_all;
            }

all_done:

            /*
             * Remove tiny edges
             */
            if (MinEdgeLengthTol > 0)
            {
                collapse_all_degenerate_edges(MinEdgeLengthTol, false);
            }
            if (Cancelled())
            {
                return(false);
            }

            /*
             * finally do global orientation
             */
            repair_orientation(true);
            if (Cancelled())
            {
                return(false);
            }

            if (do_checks)
            {
                Mesh.CheckValidity();
            }

            /*
             * Might as well compact output mesh...
             */
            Mesh = new DMesh3(Mesh, true);
            MeshNormals.QuickCompute(Mesh);

            return(true);
        }
        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");
        }
Beispiel #30
0
        protected virtual void compute_shell_extrude()
        {
            DMesh3 mesh = new DMesh3(MeshSource.GetDMeshUnsafe());

            MeshNormals.QuickCompute(mesh);

            if (shell_direction == ShellDirections.Symmetric)
            {
                double thickness = shell_thickness * 0.5;

                DMesh3          outerMesh    = new DMesh3(mesh);
                MeshExtrudeMesh outerExtrude = new MeshExtrudeMesh(outerMesh);
                outerExtrude.ExtrudedPositionF = (v, n, vid) => {
                    return(v + thickness * (Vector3d)n);
                };
                if (outerExtrude.Extrude() == false)
                {
                    throw new Exception("MeshShellOp.compute_shell_extrude: outer Extrude() returned false!");
                }
                MeshEditor.RemoveTriangles(outerMesh, outerExtrude.InitialTriangles);

                MeshExtrudeMesh innerExtrude = new MeshExtrudeMesh(mesh);
                innerExtrude.IsPositiveOffset  = false;
                innerExtrude.ExtrudedPositionF = (v, n, vid) => {
                    return(v - thickness * (Vector3d)n);
                };
                if (innerExtrude.Extrude() == false)
                {
                    throw new Exception("MeshShellOp.compute_shell_extrude: inner Extrude() returned false!");
                }
                MeshEditor.RemoveTriangles(mesh, innerExtrude.InitialTriangles);

                MeshEditor.Append(mesh, outerMesh);

                if (cached_is_closed == false)
                {
                    // cheating!
                    MergeCoincidentEdges merge = new MergeCoincidentEdges(mesh);
                    merge.Apply();
                }
            }
            else
            {
                double thickness = (shell_direction == ShellDirections.Outer) ?
                                   shell_thickness : -shell_thickness;

                MeshExtrudeMesh extrude = new MeshExtrudeMesh(mesh);
                extrude.IsPositiveOffset = (shell_direction == ShellDirections.Outer);

                extrude.ExtrudedPositionF = (v, n, vid) => {
                    return(v + thickness * (Vector3d)n);
                };

                if (extrude.Extrude() == false)
                {
                    throw new Exception("MeshShellOp.compute_shell_extrude: Extrude() returned false!");
                }

                if (shell_surface_only && cached_is_closed)
                {
                    MeshEditor.RemoveTriangles(mesh, extrude.InitialTriangles);
                    if (shell_direction == ShellDirections.Inner)
                    {
                        mesh.ReverseOrientation();
                    }
                    if (shell_direction == ShellDirections.Inner || shell_direction == ShellDirections.Outer)
                    {
                        mesh.AttachMetadata("is_partial", new object());
                    }
                }
            }

            if (is_invalidated())
            {
                return;
            }

            ResultMesh = mesh;
        }