예제 #1
0
        public static void test_voxel_surface()
        {
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_solid.obj");
            DMesh3         mesh    = TestUtil.LoadTestInputMesh("holey_bunny_2.obj");
            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, autoBuild: true);

            AxisAlignedBox3d bounds         = mesh.CachedBounds;
            int    numcells                 = 64;
            double cellsize                 = bounds.MaxDim / numcells;
            MeshSignedDistanceGrid levelSet = new MeshSignedDistanceGrid(mesh, cellsize);

            levelSet.UseParallel = true;
            levelSet.Compute();

            Bitmap3 bmp = new Bitmap3(levelSet.Dimensions);

            foreach (Vector3i idx in bmp.Indices())
            {
                float f = levelSet[idx.x, idx.y, idx.z];
                bmp.Set(idx, (f < 0) ? true : false);
            }


            //AxisAlignedBox3d bounds = mesh.CachedBounds;
            //int numcells = 32;
            //double cellsize = bounds.MaxDim / numcells;
            //ShiftGridIndexer3 indexer = new ShiftGridIndexer3(bounds.Min-2*cellsize, cellsize);

            //Bitmap3 bmp = new Bitmap3(new Vector3i(numcells, numcells, numcells));
            //foreach (Vector3i idx in bmp.Indices()) {
            //    Vector3d v = indexer.FromGrid(idx);
            //    bmp.Set(idx, spatial.IsInside(v));
            //}

            //spatial.WindingNumber(Vector3d.Zero);
            //Bitmap3 bmp = new Bitmap3(new Vector3i(numcells+3, numcells+3, numcells+3));
            //gParallel.ForEach(bmp.Indices(), (idx) => {
            //    Vector3d v = indexer.FromGrid(idx);
            //    bmp.SafeSet(idx, spatial.WindingNumber(v) > 0.8);
            //});


            VoxelSurfaceGenerator voxGen = new VoxelSurfaceGenerator();

            voxGen.Voxels       = bmp;
            voxGen.ColorSourceF = (idx) => {
                return(new Colorf((float)idx.x, (float)idx.y, (float)idx.z) * (1.0f / numcells));
            };
            voxGen.Generate();
            DMesh3 voxMesh = voxGen.Meshes[0];

            Util.WriteDebugMesh(voxMesh, "c:\\scratch\\temp.obj");

            TestUtil.WriteTestOutputMesh(voxMesh, "voxel_surf.obj", true, true);
        }
예제 #2
0
        public MeshICP ICP(DMesh3Builder mesh)
        {
            DMeshAABBTree3 tree = new DMeshAABBTree3(mesh.Meshes[1], autoBuild: true);

            MeshICP calc = new MeshICP(mesh.Meshes[0], tree);

            calc.Solve();
            calc.Solve(bUpdate: true);

            return(calc);
        }
예제 #3
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;
            });
        }
예제 #4
0
        public static DMeshAABBTree3 MeshSDFShouldUseSpatial(DMeshAABBTree3 treeIn, int exact_cells, double cell_size, double avg_edge_len)
        {
            double metric   = cell_size / avg_edge_len;
            double w_metric = exact_cells * metric;

            if (exact_cells < 2 || w_metric < 0.25)
            {
                return(null);
            }
            return(treeIn);
        }
예제 #5
0
        public static void test_AABBTree_TriTriIntr()
        {
            System.Console.WriteLine("test_AABBTree_TriTriIntr()");

            Sphere3Generator_NormalizedCube gen = new Sphere3Generator_NormalizedCube()
            {
                Radius = 1, EdgeVertices = 25
            };
            DMesh3  sphereMesh = gen.Generate().MakeDMesh();
            Reducer reducer    = new Reducer(sphereMesh); reducer.ReduceToTriangleCount(77);

            int    hit_count = 0;
            Random r         = new Random(31337);

            for (int iter = 0; iter < 5000; ++iter)
            {
                DMesh3     sphere1 = new DMesh3(sphereMesh), sphere2 = new DMesh3(sphereMesh);
                Vector3d[] pts = TestUtil.RandomPoints3(3, r, Vector3d.Zero, 10);   // at 10, about half of the spheres intersect
                Vector3d   p1 = pts[0], p2 = pts[1];
                double     r1 = 5, r2 = 10;
                double     eps = (r1 + r2) * 0.5 * 0.001;
                MeshTransforms.Scale(sphere1, r1);
                MeshTransforms.Translate(sphere1, p1);
                MeshTransforms.Scale(sphere2, r2);
                MeshTransforms.Translate(sphere2, p2);

                DMeshAABBTree3 tree1 = new DMeshAABBTree3(sphere1, true);
                DMeshAABBTree3 tree2 = new DMeshAABBTree3(sphere2, true);

                bool spheres_intersect = p1.Distance(p2) < (r1 + r2 + 2 * eps);
                if (spheres_intersect && p1.Distance(p2) + Math.Min(r1, r2) < Math.Max(r1, r2) * 0.9)
                {
                    spheres_intersect = false;
                }

                Index2i hitBrute  = MeshQueries.FindIntersectingTriangles_LinearSearch(sphere1, sphere2);
                bool    bHitBrute = hitBrute != Index2i.Max;
                if (bHitBrute)
                {
                    hit_count++;
                }

                // [RMS] not reliable because of tesselation
                //Util.gDevAssert(bHitBrute == spheres_intersect);

                bool bHitTree1 = tree1.TestIntersection(tree2);
                bool bHitTree2 = tree2.TestIntersection(tree1);

                Util.gDevAssert(bHitBrute == bHitTree1 && bHitTree1 == bHitTree2);
            }

            System.Console.WriteLine(hit_count.ToString());
        }
예제 #6
0
        public static void test_AABBTree_TriTriDist()
        {
            System.Console.WriteLine("test_AABBTree_TriTriDist()");

            Sphere3Generator_NormalizedCube gen = new Sphere3Generator_NormalizedCube()
            {
                Radius = 1, EdgeVertices = 6
            };
            DMesh3  sphereMesh = gen.Generate().MakeDMesh();
            Reducer reducer    = new Reducer(sphereMesh); reducer.ReduceToTriangleCount(77);


            Random r = new Random(31337);

            for (int iter = 0; iter < 1000; ++iter)
            {
                DMesh3     sphere1 = new DMesh3(sphereMesh), sphere2 = new DMesh3(sphereMesh);
                Vector3d[] pts = TestUtil.RandomPoints3(3, r, Vector3d.Zero, 100);
                Vector3d   p1 = pts[0], p2 = pts[1];
                double     r1 = 5, r2 = 10;
                MeshTransforms.Scale(sphere1, r1);
                MeshTransforms.Translate(sphere1, p1);
                MeshTransforms.Scale(sphere2, r2);
                MeshTransforms.Translate(sphere2, p2);

                DMeshAABBTree3 tree1 = new DMeshAABBTree3(sphere1, true);
                DMeshAABBTree3 tree2 = new DMeshAABBTree3(sphere2, true);

                double sphere_dist = p1.Distance(p2) - (r1 + r2);

                double  distBrute             = double.MaxValue;
                Index2i nearestBrute          = MeshQueries.FindNearestTriangles_LinearSearch(sphere1, sphere2, out distBrute);
                DistTriangle3Triangle3 qBrute = MeshQueries.TrianglesDistance(sphere1, nearestBrute.a, sphere2, nearestBrute.b);

                double  distTree             = double.MaxValue;
                Index2i nearestTree          = tree1.FindNearestTriangles(tree2, null, out distTree);
                DistTriangle3Triangle3 qTree = MeshQueries.TrianglesDistance(sphere1, nearestTree.a, sphere2, nearestTree.b);

                double  distTree2    = double.MaxValue;
                Index2i nearestTree2 = tree2.FindNearestTriangles(tree1, null, out distTree2);

                // pairs are unstable if we are on an edge
                if (qBrute.Triangle0BaryCoords.x < 0.99 && qBrute.Triangle0BaryCoords.y < 0.99 && qBrute.Triangle0BaryCoords.z < 0.99 &&
                    qBrute.Triangle1BaryCoords.x < 0.99 && qBrute.Triangle1BaryCoords.y < 0.99 && qBrute.Triangle1BaryCoords.z < 0.99)
                {
                    Util.gDevAssert(nearestBrute.a == nearestTree.a && nearestBrute.b == nearestTree.b);
                    Util.gDevAssert(nearestBrute.b == nearestTree2.a && nearestBrute.a == nearestTree.b);
                }

                Util.gDevAssert(Math.Abs(distBrute - distTree) < MathUtil.Epsilonf &&
                                Math.Abs(distBrute - distTree2) < MathUtil.Epsilonf);
            }
        }
예제 #7
0
 public void MyInit(DMesh3 mesh, bool isImported = false)
 {
     this.mesh = mesh;
     spatial   = new DMeshAABBTree3(mesh);
     spatial.Build();
     this.isImported = isImported;
     if (isImported)
     {
         originalMesh = new DMesh3(mesh);
     }
     center = transform.TransformPoint(mesh.GetBounds().Center.toVector3());
 }
예제 #8
0
        public virtual void Update()
        {
            base.begin_update();
            int start_timestamp = this.CurrentInputTimestamp;

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

            try {
                ResultMesh = null;

                DMesh3 meshIn = MeshSource.GetDMeshUnsafe();
                input_spatial = MeshSource.GetSpatial() as DMeshAABBTree3;
                if (meshIn.ShapeTimestamp != input_mesh_cache_timestamp)
                {
                    cached_is_closed = meshIn.IsClosed();
                    MeshQueries.EdgeLengthStats(meshIn, out input_mesh_edge_stats.x, out input_mesh_edge_stats.y, out input_mesh_edge_stats.z);
                    if (input_spatial == null)
                    {
                        input_spatial = new DMeshAABBTree3(meshIn, false);
                    }
                    input_mesh_cache_timestamp = meshIn.ShapeTimestamp;
                }

                if (closing_type == ClosingTypes.LevelSet)
                {
                    update_level_set();
                }
                else if (closing_type == ClosingTypes.WindingNumberGrid)
                {
                    if (cached_is_closed)
                    {
                        update_winding();
                    }
                    else
                    {
                        update_winding_fast();
                    }
                }
                else
                {
                    update_winding_exact();
                }

                base.complete_update();
            } catch (Exception e) {
                PostOnOperatorException(e);
                ResultMesh = base.make_failure_output(MeshSource.GetDMeshUnsafe());
                base.complete_update();
            }
        }
예제 #9
0
        public static double?DistanceToTree(this DMeshAABBTree3 tree, Ray3d ray)
        {
            var hit_tid = tree.FindNearestHitTriangle(ray);

            if (hit_tid == DMesh3.InvalidID)
            {
                return(null);
            }
            var intr = MeshQueries.TriangleIntersection(tree.Mesh, hit_tid, ray);

            return(ray.Origin.Distance(ray.PointAt(intr.RayParameter)));
        }
예제 #10
0
    //If the position is too close to shell, returns the direction to move away from it to try again. Returns null if not too close
    internal Vector3d?GetAwayFromShellDirection(CuttingInfo info, DMeshAABBTree3 tree, Vector3d position)
    {
        tree.TriangleFilterF = i => tree.Mesh.GetTriangleGroup(i) != info.data.ColorNum;

        int near_tid = tree.FindNearestTriangle(position, info.data.minDepth); //TODO scale the max dist by SDF or so

        if (near_tid != DMesh3.InvalidID)
        {
            return(-tree.Mesh.GetTriNormal(near_tid));
        }

        return(null);
    }
예제 #11
0
        public void SetMesh(DMesh3 meshIn, bool buildSpatial, bool bTakeOwnership)
        {
            mesh = (bTakeOwnership) ? meshIn : new DMesh3(meshIn);

            spatial = null;
            if (buildSpatial)
            {
                spatial = new DMeshAABBTree3(mesh);
                spatial.Build();
            }

            PostOnOperatorModified();
        }
예제 #12
0
        void on_mesh_changed(bool bInvalidateSpatial = true, bool bInvalidateDecomp = true)
        {
            if (bInvalidateSpatial)
            {
                spatial = null;
            }

            // discard existing mesh GOs
            if (bInvalidateDecomp)
            {
                viewMeshes.InvalidateViewMeshes();
            }
        }
예제 #13
0
        public static Vector3d NearestPoint(this DMeshAABBTree3 tree, Vector3d point)
        {
            var tid = tree.FindNearestTriangle(point);

            if (tid == DMesh3.InvalidID)
            {
                return(new Vector3d());
            }

            var dist = MeshQueries.TriangleDistance(tree.Mesh, tid, point);

            return(dist.TriangleClosest);
        }
예제 #14
0
        public static void TestIsoCurve()
        {
            var              meshSO  = OG.Scan.SO;
            DMesh3           mesh    = new DMesh3(meshSO.Mesh);
            DMeshAABBTree3   spatial = new DMeshAABBTree3(mesh, true);
            AxisAlignedBox3d bounds  = mesh.CachedBounds;

            Frame3f plane = new Frame3f(bounds.Center);

            Func <Vector3d, double> planeSignedDistanceF = (v) => {
                return((v - plane.Origin).Dot(plane.Y));
            };

            Func <Vector3d, double> sphereDistF = (v) => {
                double d = v.Distance(plane.Origin);
                return(d - 50.0);
            };

            MeshIsoCurves iso = new MeshIsoCurves(mesh, sphereDistF);

            iso.Compute();

            DGraph3Util.Curves curves = DGraph3Util.ExtractCurves(iso.Graph);

            foreach (DCurve3 c in curves.Loops)
            {
                List <Vector3d> verts = new List <Vector3d>(c.Vertices);
                for (int i = 0; i < verts.Count; ++i)
                {
                    verts[i] = verts[i] + 0.5 * mesh.GetTriNormal(spatial.FindNearestTriangle(verts[i]));
                }
                DebugUtil.EmitDebugCurve("curve", verts.ToArray(), true, 1, Colorf.Red, Colorf.Red, meshSO.RootGameObject, false);
            }

            foreach (DCurve3 c in curves.Paths)
            {
                List <Vector3d> verts = new List <Vector3d>(c.Vertices);
                for (int i = 0; i < verts.Count; ++i)
                {
                    verts[i] = verts[i] + 0.5 * mesh.GetTriNormal(spatial.FindNearestTriangle(verts[i]));
                }
                DebugUtil.EmitDebugCurve("curve", verts.ToArray(), false, 1, Colorf.Blue, Colorf.Blue, meshSO.RootGameObject, false);
            }

            //foreach ( Segment3d seg in iso.Graph.Segments()) {
            //    Vector3d a = seg.P0 + 1.0 * mesh.GetTriNormal(spatial.FindNearestTriangle(seg.P0));
            //    Vector3d b = seg.P1 + 1.0 * mesh.GetTriNormal(spatial.FindNearestTriangle(seg.P1));

            //    DebugUtil.EmitDebugLine("seg", a, b, 1.0f, Colorf.Red, meshSO.RootGameObject, false);
            //}
        }
예제 #15
0
        protected override void OnPointUpdated(ControlPoint pt, Frame3f prevFrameS, bool isFirst)
        {
            DMesh3         mesh    = InputMeshSO.Mesh;
            DMeshAABBTree3 spatial = InputMeshSO.Spatial;

            Vector3f ptO    = SceneTransforms.SceneToObjectP(InputMeshSO, pt.currentFrameS.Origin);
            Frame3f  frameO = MeshQueries.NearestPointFrame(mesh, spatial, ptO, true);

            Vector3d dir = -frameO.Z;

            if (hole_direction != HoleDirections.Normal)
            {
                Vector3f axis = Vector3f.AxisX;
                if (hole_direction == HoleDirections.AxisY)
                {
                    axis = Vector3f.AxisY;
                }
                else if (hole_direction == HoleDirections.AxisZ)
                {
                    axis = Vector3f.AxisZ;
                }
                axis = SceneTransforms.SceneToObjectN(InputMeshSO, axis);
                dir  = (dir.Dot(axis) < 0) ? -axis : axis;
            }
            //dir.Normalize();

            LastUpdateRay = new Ray3d(frameO.Origin, dir);

            List <int> hitTris  = new List <int>();
            int        hit_tris = spatial.FindAllHitTriangles(LastUpdateRay, hitTris);
            double     max_t    = 0;

            foreach (int tid in hitTris)
            {
                Vector3d n = mesh.GetTriNormal(tid);
                if (n.Dot(LastUpdateRay.Direction) < 0)
                {
                    continue;
                }
                IntrRay3Triangle3 rayhit = MeshQueries.TriangleIntersection(InputMeshSO.Mesh, tid, LastUpdateRay);
                max_t = rayhit.RayParameter;
                break;
            }
            if (max_t <= 0)
            {
                return;
            }

            LastThroughDepth = max_t;
            update_current_hole_type();
        }
예제 #16
0
        //
        // internals
        //
        void on_mesh_changed(bool bInvalidateSpatial = true, bool bInvalidateDecomp = true)
        {
            if (bInvalidateSpatial)
            {
                spatial = null;
            }

            // discard existing mesh GOs
            if (bInvalidateDecomp)
            {
                ClearAllComponents();
                decomp = null;
            }
        }
예제 #17
0
        public void AddMesh(DMesh3 mesh, object identifier, DMeshAABBTree3 spatial = null)
        {
            var comp = new ComponentMesh(mesh, identifier, spatial);

            if (spatial == null)
            {
                if (comp.IsClosed || AllowOpenContainers)
                {
                    comp.Spatial = new DMeshAABBTree3(mesh, true);
                }
            }

            Components.Add(comp);
        }
예제 #18
0
            internal bool Randomize(g3.DMesh3 mesh, DMeshAABBTree3 tree, Random r, double max, double moveTries, double average)
            {
                bool result = false;

                for (int i = 0; i < moveTries; i++)
                {
                    result |= this.RandomAdjust(mesh, tree, r, max, moveTries, average);

                    //foreach (var n in neighbors)
                    //    result |= n.RandomAdjust(mesh, tree, r, max, moveTries, average);
                }

                return(result);
            }
예제 #19
0
        public static DMesh3 MakeRemeshedCappedCylinder(double fResFactor = 1.0)
        {
            DMesh3 mesh = MakeCappedCylinder(false, 128);

            MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new g3.Vector3f(1, 2, 1));

            // construct mesh projection target
            DMesh3         meshCopy = new DMesh3(mesh);
            DMeshAABBTree3 tree     = new DMeshAABBTree3(meshCopy);

            tree.Build();
            MeshProjectionTarget target = new MeshProjectionTarget()
            {
                Mesh    = meshCopy,
                Spatial = tree
            };
            MeshConstraints cons     = new MeshConstraints();
            EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;

            foreach (int eid in mesh.EdgeIndices())
            {
                double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
                if (fAngle > 30.0f)
                {
                    cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags));
                    Index2i ev      = mesh.GetEdgeV(eid);
                    int     nSetID0 = (mesh.GetVertex(ev[0]).y > 1) ? 1 : 2;
                    int     nSetID1 = (mesh.GetVertex(ev[1]).y > 1) ? 1 : 2;
                    cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0));
                    cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1));
                }
            }
            Remesher r = new Remesher(mesh);

            r.SetExternalConstraints(cons);
            r.SetProjectionTarget(target);
            r.Precompute();
            r.EnableFlips     = r.EnableSplits = r.EnableCollapses = true;
            r.MinEdgeLength   = 0.1f * fResFactor;
            r.MaxEdgeLength   = 0.2f * fResFactor;
            r.EnableSmoothing = true;
            r.SmoothSpeedT    = 0.5f;
            for (int k = 0; k < 20; ++k)
            {
                r.BasicRemeshPass();
            }
            return(mesh);
        }
예제 #20
0
        public Task BuildTreeAsync(Vector3[] positions, Vector3[] normals, int[] indices)
        {
            return(Task.Run(() => {
                var norm = ConvertToVector3f(normals);
                DMeshLocal = DMesh3Builder.Build(ConvertToVector3f(positions), indices, norm);

                TreeLocal = new DMeshAABBTree3(DMeshLocal);
                TreeLocal.Build();

                box = new BoundingBox(DMeshLocal.GetBounds());

                IsBuilt = true;

                return this;
            }));
        }
예제 #21
0
        public virtual void Update()
        {
            base.begin_update();
            int start_timestamp = this.CurrentInputTimestamp;

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

            try {
                ResultMesh = null;

                DMesh3 meshIn = MeshSource.GetDMeshUnsafe();
                input_spatial = MeshSource.GetSpatial() as DMeshAABBTree3;
                if (meshIn.ShapeTimestamp != input_mesh_cache_timestamp)
                {
                    cached_is_closed = meshIn.IsClosed();
                    MeshQueries.EdgeLengthStats(meshIn, out input_mesh_edge_stats.x, out input_mesh_edge_stats.y, out input_mesh_edge_stats.z);
                    if (input_spatial == null)
                    {
                        input_spatial = new DMeshAABBTree3(meshIn, false);
                    }
                    input_mesh_cache_timestamp = meshIn.ShapeTimestamp;
                }

                if (shell_type == ShellTypes.DistanceField)
                {
                    compute_shell_distancefield();
                }
                else
                {
                    compute_shell_extrude();
                }

                if (ResultMesh.TriangleCount == 0)
                {
                    ResultMesh = base.make_failure_output(null);
                }

                base.complete_update();
            } catch (Exception e) {
                PostOnOperatorException(e);
                ResultMesh = base.make_failure_output(MeshSource.GetDMeshUnsafe());
                base.complete_update();
            }
        }
예제 #22
0
        DMesh3 compute_partial_hole(Vector3d start, Vector3d end, double tol)
        {
            DMesh3         origMesh    = MeshSource.GetDMeshUnsafe();
            DMeshAABBTree3 origSpatial = MeshSource.GetSpatial() as DMeshAABBTree3;

            DMesh3 cutMesh = new DMesh3(origMesh);

            Polygon2d polygon = Polygon2d.MakeCircle(hole_size / 2, hole_subdivisions);

            Vector3f axis = (Vector3f)(start - end).Normalized;

            int     start_tid   = origSpatial.FindNearestTriangle(start);
            Frame3f start_frame = origMesh.GetTriFrame(start_tid);

            start_frame.Origin = (Vector3f)start;
            start_frame.AlignAxis(2, axis);

            int end_tid = origSpatial.FindNearestTriangle(end);
            //Frame3f end_frame = origMesh.GetTriFrame(end_tid); end_frame.Origin = (Vector3f)end;
            Frame3f end_frame = start_frame; end_frame.Origin = (Vector3f)end;

            // [TODO] we don't need to Simplify here...is more robust?

            MeshInsertProjectedPolygon start_insert = new MeshInsertProjectedPolygon(cutMesh, polygon, start_frame, start_tid);
            bool start_ok = start_insert.Insert();

            if (start_ok == false)
            {
                throw new Exception("CutPolygonHoleOp.compute_partial_hole: start or end insertion failed!");
            }

            EdgeLoop outLoop = start_insert.InsertedLoop;

            MeshExtrudeLoop extrude = new MeshExtrudeLoop(cutMesh, outLoop);

            extrude.PositionF = (v, n, vid) => {
                cutMesh.GetVertex(vid);
                return(end_frame.ProjectToPlane((Vector3f)v, 2));
            };
            extrude.Extrude();

            SimpleHoleFiller filler = new SimpleHoleFiller(cutMesh, extrude.NewLoop);

            filler.Fill();

            return(cutMesh);
        }
예제 #23
0
        public static void test_local_param()
        {
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("plane_250v.obj");
            //DMesh3 mesh = TestUtil.LoadTestInputMesh("hemisphere_nicemesh_3k.obj");
            DMesh3 mesh = TestUtil.LoadTestInputMesh("bunny_open_base.obj");

            mesh.EnableVertexUVs(Vector2f.Zero);

            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh);

            spatial.Build();

            //int tid = spatial.FindNearestTriangle(Vector3d.Zero);
            //Frame3f seedF = new Frame3f(Vector3d.Zero, Vector3d.AxisY);
            int     tid   = 3137;
            Frame3f seedF = mesh.GetTriFrame(tid);

            Index3i seedNbrs = mesh.GetTriangle(tid);

            MeshLocalParam param = new MeshLocalParam(mesh.MaxVertexID,
                                                      mesh.GetVertexf, mesh.GetVertexNormal, mesh.VtxVerticesItr);

            param.ComputeToMaxDistance(seedF, seedNbrs, float.MaxValue);

            float fR = param.MaxUVDistance;

            param.TransformUV(0.5f / fR, 0.5f * Vector2f.One);

            param.ApplyUVs((vid, uv) => { mesh.SetVertexUV(vid, uv); });

            TestUtil.SetColorsFromScalarF(mesh, (vid) => { return(param.GetUV(vid).Distance(0.5f * Vector2f.One)); }, new Vector2f(0, 0.5f));

            OBJWriter        writer = new OBJWriter();
            var              s      = new System.IO.StreamWriter(Program.TEST_OUTPUT_PATH + "mesh_local_param.obj", false);
            List <WriteMesh> wm     = new List <WriteMesh>()
            {
                new WriteMesh(mesh)
            };
            WriteOptions opt = new WriteOptions()
            {
                bCombineMeshes  = false, bWriteGroups = false, bPerVertexColors = true, bPerVertexUVs = true,
                AsciiHeaderFunc = () => { return("mttllib checkerboard.mtl\r\nusemtl checkerboard\r\n"); }
            };

            writer.Write(s, wm, opt);
            s.Close();
        }
예제 #24
0
    public MeshImportFeature(byte[] data)
    {
        MemoryStream ms     = new MemoryStream(data);
        var          meshes = Parabox.STL.pb_Stl_Importer.Import(ms);

        mesh         = meshes[0];
        useThreshold = (mesh.GetIndexCount(0) < 5000);
        if (meshes.Length > 1)
        {
            Debug.LogWarning("Imported " + meshes.Length + " meshes, but used only one");
        }

        //meshCheck.setMesh(mesh);
        //mesh = meshCheck.ToUnityWatertightMesh();
        basis   = new ExpBasis();
        hitMesh = new DMeshAABBTree3(mesh.ToDMesh3(), true);
    }
예제 #25
0
    internal bool CheckPositionValid(DMesh3 mesh, Vector3d position, int colorToExclude)
    {
        var spatial = new DMeshAABBTree3(mesh);

        spatial.Build();

        spatial.TriangleFilterF = i => mesh.GetTriangleGroup(i) != colorToExclude;

        int near_tid = spatial.FindNearestTriangle(position, 9f);

        if (near_tid != DMesh3.InvalidID)
        {
            return(false);
        }

        return(true);
    }
예제 #26
0
        public Mesh Reduce(Mesh inMesh, int targetCount)
        {
            var mesh    = inMesh.ToDMesh3();
            var reducer = new Reducer(mesh);

            if (MaintainSurface)
            {
                var tree = new DMeshAABBTree3(new DMesh3(mesh));
                tree.Build();
                var target = new MeshProjectionTarget(tree.Mesh, tree);
                reducer.SetProjectionTarget(target);
                reducer.ProjectionMode = Reducer.TargetProjectionMode.Inline;
            }

            reducer.ReduceToTriangleCount(Math.Max(4, targetCount));

            return(reducer.Mesh.ToMesh());
        }
예제 #27
0
        DMeshAABBTree3 get_cached_spatial()
        {
            if (MeshSource.HasSpatial)
            {
                if (MeshSource.GetSpatial() is DMeshAABBTree3)
                {
                    return(MeshSource.GetSpatial() as DMeshAABBTree3);
                }
            }
            DMesh3 mesh = MeshSource.GetDMeshUnsafe();

            if (internal_spatial != null && spatial_timestamp == mesh.ShapeTimestamp)
            {
                return(internal_spatial);
            }
            internal_spatial  = new DMeshAABBTree3(mesh, true);
            spatial_timestamp = mesh.ShapeTimestamp;
            return(internal_spatial);
        }
예제 #28
0
    internal Vector3d?GetInsideShell(DMeshAABBTree3 tree, Vector3d position, int colorToExclude)
    {
        tree.TriangleFilterF = i => tree.Mesh.GetTriangleGroup(i) != colorToExclude;

        int near_tid = tree.FindNearestTriangle(position, 30f);

        if (near_tid != DMesh3.InvalidID)
        {
            //var nearTri = mesh.GetTriangle(near_tid);
            return(tree.Mesh.GetTriCentroid(near_tid) - position);
        }
        else
        {
            Debug.Log("Get Inside: Too far away");
            StaticFunctions.ErrorMessage("Extrusion/Depth setting of a color is too much, might extrude outside of shell");
        }

        return(null);
    }
예제 #29
0
    void Start()
    {
        if (model != null)
        {
            mesh          = model.sharedMesh;
            meshVertices  = mesh.vertices;
            meshTriangles = mesh.triangles;
            for (int i = 0; i < meshVertices.Length; i++)
            {
                meshVertices[i] = model.transform.TransformPoint(meshVertices[i]);
            }
            binarySpacePartition = new BSP(mesh, 14);

            if (diskMaterial)
            {
                int numDisksToDraw = Mathf.Min(binarySpacePartition.splittingDisks.Length, 15);
                diskMatrices = new Matrix4x4[numDisksToDraw];
                for (int i = 0; i < numDisksToDraw; i++)
                {
                    diskMatrices[i] = Matrix4x4.TRS(
                        binarySpacePartition.splittingDisks[i].average,
                        Quaternion.LookRotation(binarySpacePartition.splittingDisks[i].plane),
                        new Vector3(1f, 1f, 0.0001f) * Mathf.Sqrt(binarySpacePartition.splittingDisks[i].sqRadius));
                }
            }

#if G3_USING_UNITY
            DMesh3Builder dMeshBuilder = new DMesh3Builder();
            dMeshBuilder.AppendNewMesh(false, false, false, false);
            foreach (Vector3 vertex in meshVertices)
            {
                dMeshBuilder.AppendVertex(vertex.x, vertex.y, vertex.z);
            }
            for (int i = 0; i < meshTriangles.Length; i += 3)
            {
                dMeshBuilder.AppendTriangle(meshTriangles[i], meshTriangles[i + 1], meshTriangles[i + 2]);
            }
            g3MeshTree = new DMeshAABBTree3(dMeshBuilder.Meshes[0]);
            g3MeshTree.Build();
#endif
        }
    }
예제 #30
0
        public virtual bool FindNearest(Vector3d point, double maxDist, out SORayHit nearest, CoordSpace eInCoords)
        {
            nearest = null;
            if (enable_spatial == false)
            {
                return(false);
            }

            if (spatial == null)
            {
                spatial = new DMeshAABBTree3(mesh);
                spatial.Build();
            }

            // convert to local
            Vector3f local_pt = SceneTransforms.TransformTo((Vector3f)point, this, eInCoords, CoordSpace.ObjectCoords);

            if (mesh.CachedBounds.Distance(local_pt) > maxDist)
            {
                return(false);
            }

            int tid = spatial.FindNearestTriangle(local_pt);

            if (tid != DMesh3.InvalidID)
            {
                DistPoint3Triangle3 dist = MeshQueries.TriangleDistance(mesh, tid, local_pt);

                nearest          = new SORayHit();
                nearest.fHitDist = (float)Math.Sqrt(dist.DistanceSquared);

                Frame3f f_local = new Frame3f(dist.TriangleClosest, mesh.GetTriNormal(tid));
                Frame3f f       = SceneTransforms.TransformTo(f_local, this, CoordSpace.ObjectCoords, eInCoords);

                nearest.hitPos    = f.Origin;
                nearest.hitNormal = f.Z;
                nearest.hitGO     = RootGameObject;
                nearest.hitSO     = this;
                return(true);
            }
            return(false);
        }