Exemplo n.º 1
0
        void smooth_and_remesh_preserve(MeshFaceSelection tris, bool bFinal)
        {
            if (EnableLaplacianSmooth)
            {
                LaplacianMeshSmoother.RegionSmooth(Mesh, tris, 2, 2, true);
            }

            if (RemeshAfterSmooth)
            {
                MeshProjectionTarget target = (bFinal) ? MeshProjectionTarget.Auto(Mesh, tris, 5) : null;

                RegionRemesher remesh2 = new RegionRemesher(Mesh, tris);
                remesh2.SetTargetEdgeLength(TargetEdgeLength);
                remesh2.SmoothSpeedT = 1.0;
                remesh2.SetProjectionTarget(target);
                if (ConfigureRemesherF != null)
                {
                    ConfigureRemesherF(remesh2, false);
                }
                for (int k = 0; k < 10; ++k)
                {
                    remesh2.BasicRemeshPass();
                }
                remesh2.BackPropropagate();

                FillTriangles = remesh2.CurrentBaseTriangles;
            }
            else
            {
                FillTriangles = tris.ToArray();
            }
        }
Exemplo n.º 2
0
        void smooth_and_remesh(MeshFaceSelection tris)
        {
            if (EnableLaplacianSmooth)
            {
                LaplacianMeshSmoother.RegionSmooth(Mesh, tris, 2, 2, false);
            }

            if (RemeshAfterSmooth)
            {
                tris.ExpandToOneRingNeighbours(2);
                tris.LocalOptimize(true, true);
                MeshProjectionTarget target = MeshProjectionTarget.Auto(Mesh, tris, 5);

                RegionRemesher remesh2 = new RegionRemesher(Mesh, tris);
                remesh2.SetTargetEdgeLength(TargetEdgeLength);
                remesh2.SmoothSpeedT = 1.0;
                remesh2.SetProjectionTarget(target);
                if (ConfigureRemesherF != null)
                {
                    ConfigureRemesherF(remesh2, false);
                }
                for (int k = 0; k < 10; ++k)
                {
                    remesh2.BasicRemeshPass();
                }
                remesh2.BackPropropagate();

                FillTriangles = remesh2.CurrentBaseTriangles;
            }
            else
            {
                FillTriangles = tris.ToArray();
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Cut a "partial" hole, ie we cut the mesh with the polygon once, and then
        /// extrude downwards to a planar version of the cut boundary.
        ///
        /// Currently only supports extruding downwards from topmost intersection.
        ///
        /// </summary>
        protected bool CutPartialHole(DMesh3 mesh, HoleInfo hi, Vector3d translate, bool bUpwards)
        {
            if (hi.IsVertical == false)
            {
                throw new Exception("unsupported!");
            }

            Vector3d basePoint = CombinedBounds.Center - CombinedBounds.Extents.y * Vector3d.AxisY + translate;

            // do we need to compute spatial DS for each hole? not super efficient...
            DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh, true);

            Vector3d direction = (bUpwards) ? Vector3d.AxisY : -Vector3d.AxisY;
            Vector3d center    = basePoint + new Vector3d(hi.XZOffset.x, 0, hi.XZOffset.y) - 10000 * direction;


            Ray3d ray     = new Ray3d(center, direction);
            int   hit_tid = spatial.FindNearestHitTriangle(ray);

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

            IntrRay3Triangle3 intersection = MeshQueries.TriangleIntersection(mesh, hit_tid, ray);
            Vector3d          inter_pos    = ray.PointAt(intersection.RayParameter);

            Frame3f projectFrame = new Frame3f(ray.Origin, ray.Direction);

            int nVerts = 32;

            if (hi.Vertices != 0)
            {
                nVerts = hi.Vertices;
            }
            double    angleShiftRad = hi.AxisAngleD * MathUtil.Deg2Rad;
            Polygon2d circle        = Polygon2d.MakeCircle(hi.Radius, nVerts, angleShiftRad);

            try {
                EdgeLoop loop = null;

                MeshInsertProjectedPolygon insert = new MeshInsertProjectedPolygon(mesh, circle, projectFrame, hit_tid)
                {
                    SimplifyInsertion = false
                };
                if (insert.Insert())
                {
                    loop = insert.InsertedLoop;

                    // [RMS] do we need to simplify for this one?
                    //if (loop.VertexCount > circle.VertexCount)
                    //    loop = simplify_loop(mesh, loop, circle.VertexCount);

                    MeshEditor editor = new MeshEditor(mesh);

                    Vector3d base_pos = inter_pos;
                    base_pos.y = basePoint.y + hi.PartialHoleBaseHeight;

                    int   N       = loop.VertexCount;
                    int[] newLoop = new int[N];
                    for (int k = 0; k < N; ++k)
                    {
                        newLoop[k] = mesh.AppendVertex(mesh, loop.Vertices[k]);
                        Vector3d cur_v = mesh.GetVertex(newLoop[k]);
                        cur_v.y = base_pos.y;
                        mesh.SetVertex(newLoop[k], cur_v);
                    }
                    int   base_vid = mesh.AppendVertex(base_pos);
                    int[] fan_tris = editor.AddTriangleFan_OrderedVertexLoop(base_vid, newLoop);
                    FaceGroupUtil.SetGroupID(mesh, fan_tris, hi.PartialHoleGroupID);
                    int[] stitch_tris = editor.StitchLoop(loop.Vertices, newLoop);

                    // need to remesh fan region because otherwise we get pathological cases
                    RegionRemesher remesh = new RegionRemesher(mesh, fan_tris);
                    remesh.SetTargetEdgeLength(2.0);
                    remesh.SmoothSpeedT       = 1.0;
                    remesh.PreventNormalFlips = true;
                    for (int k = 0; k < 25; ++k)
                    {
                        remesh.BasicRemeshPass();
                    }
                    //remesh.EnableCollapses = remesh.EnableFlips = remesh.EnableSplits = false;
                    //for (int k = 0; k < 20; ++k)
                    //    remesh.BasicRemeshPass();
                    remesh.BackPropropagate();

                    return(true);
                }
                else
                {
                    return(false);
                }
            } catch (Exception e) {
                f3.DebugUtil.Log("partial hole {0} failed!! {1}", hi.nHole, e.Message);
                return(false);
            }
        }
Exemplo n.º 4
0
        public bool Apply()
        {
            EdgeLoop useLoop = null;

            if (FillLoop == null)
            {
                MeshBoundaryLoops loops = new MeshBoundaryLoops(Mesh, true);
                if (loops.Count == 0)
                {
                    return(false);
                }

                if (BorderHintTris != null)
                {
                    useLoop = select_loop_tris_hint(loops);
                }
                if (useLoop == null && loops.MaxVerticesLoopIndex >= 0)
                {
                    useLoop = loops[loops.MaxVerticesLoopIndex];
                }
            }
            else
            {
                useLoop = FillLoop;
            }
            if (useLoop == null)
            {
                return(false);
            }

            // step 1: do stupid hole fill
            SimpleHoleFiller filler = new SimpleHoleFiller(Mesh, useLoop);

            if (filler.Fill() == false)
            {
                return(false);
            }

            if (useLoop.Vertices.Length <= 3)
            {
                FillTriangles = filler.NewTriangles;
                FillVertices  = new int[0];
                return(true);
            }

            MeshFaceSelection tris = new MeshFaceSelection(Mesh);

            tris.Select(filler.NewTriangles);

            // extrude initial fill surface (this is used in socketgen for example)
            if (OffsetDistance > 0)
            {
                MeshExtrudeFaces extrude = new MeshExtrudeFaces(Mesh, tris);
                extrude.ExtrudedPositionF = (v, n, vid) => {
                    return(v + OffsetDistance * OffsetDirection);
                };
                if (!extrude.Extrude())
                {
                    return(false);
                }
                tris.Select(extrude.JoinTriangles);
            }

            // if we aren't trying to stay inside hole, expand out a bit,
            // which allows us to clean up ugly edges
            if (ConstrainToHoleInterior == false)
            {
                tris.ExpandToOneRingNeighbours(2);
                tris.LocalOptimize(true, true);
            }

            // remesh the initial coarse fill region
            if (RemeshBeforeSmooth)
            {
                RegionRemesher remesh = new RegionRemesher(Mesh, tris);
                remesh.SetTargetEdgeLength(TargetEdgeLength);
                remesh.EnableSmoothing = (SmoothAlpha > 0);
                remesh.SmoothSpeedT    = SmoothAlpha;
                if (ConfigureRemesherF != null)
                {
                    ConfigureRemesherF(remesh, true);
                }
                for (int k = 0; k < InitialRemeshPasses; ++k)
                {
                    remesh.BasicRemeshPass();
                }
                remesh.BackPropropagate();

                tris = new MeshFaceSelection(Mesh);
                tris.Select(remesh.CurrentBaseTriangles);
                if (ConstrainToHoleInterior == false)
                {
                    tris.LocalOptimize(true, true);
                }
            }

            if (ConstrainToHoleInterior)
            {
                for (int k = 0; k < SmoothSolveIterations; ++k)
                {
                    smooth_and_remesh_preserve(tris, k == SmoothSolveIterations - 1);
                    tris = new MeshFaceSelection(Mesh); tris.Select(FillTriangles);
                }
            }
            else
            {
                smooth_and_remesh(tris);
                tris = new MeshFaceSelection(Mesh); tris.Select(FillTriangles);
            }

            MeshVertexSelection fill_verts = new MeshVertexSelection(Mesh);

            fill_verts.SelectInteriorVertices(tris);
            FillVertices = fill_verts.ToArray();

            return(true);
        }
Exemplo n.º 5
0
        protected void do_flatten(DMesh3 mesh)
        {
            double   BAND_HEIGHT = flatten_band_height;
            Vector3d down_axis   = -Vector3d.AxisY;
            double   dot_thresh  = 0.2;

            AxisAlignedBox3d bounds  = mesh.CachedBounds;
            DMeshAABBTree3   spatial = new DMeshAABBTree3(mesh, true);

            Ray3d   ray     = new Ray3d(bounds.Center - 2 * bounds.Height * Vector3d.AxisY, Vector3d.AxisY);
            int     hit_tid = spatial.FindNearestHitTriangle(ray);
            Frame3f hitF;

            MeshQueries.RayHitPointFrame(mesh, spatial, ray, out hitF);
            Vector3d basePt = hitF.Origin;

            Frame3f basePlane = new Frame3f(basePt, Vector3f.AxisY);

            MeshConnectedComponents components = new MeshConnectedComponents(mesh)
            {
                FilterF = (tid) => {
                    if (mesh.GetTriangleGroup(tid) != LastExtrudeOuterGroupID)
                    {
                        return(false);
                    }
                    Vector3d n, c; double a;
                    mesh.GetTriInfo(tid, out n, out a, out c);
                    double h = Math.Abs(c.y - basePt.y);
                    if (h > BAND_HEIGHT)
                    {
                        return(false);
                    }
                    if (n.Dot(down_axis) < dot_thresh)
                    {
                        return(false);
                    }
                    return(true);
                },
                SeedFilterF = (tid) => {
                    return(tid == hit_tid);
                }
            };

            components.FindConnectedT();

            MeshFaceSelection all_faces = new MeshFaceSelection(mesh);

            foreach (var comp in components)
            {
                MeshVertexSelection vertices = new MeshVertexSelection(mesh);
                vertices.SelectTriangleVertices(comp.Indices);
                foreach (int vid in vertices)
                {
                    Vector3d v = mesh.GetVertex(vid);
                    v = basePlane.ProjectToPlane((Vector3f)v, 2);
                    mesh.SetVertex(vid, v);
                }
                all_faces.SelectVertexOneRings(vertices);
            }

            all_faces.ExpandToOneRingNeighbours(3, (tid) => {
                return(mesh.GetTriangleGroup(tid) == LastExtrudeOuterGroupID);
            });

            RegionRemesher r = new RegionRemesher(mesh, all_faces);

            r.SetProjectionTarget(MeshProjectionTarget.Auto(mesh));
            r.SetTargetEdgeLength(2.0f);
            r.SmoothSpeedT = 1.0f;
            for (int k = 0; k < 10; ++k)
            {
                r.BasicRemeshPass();
            }
            r.SetProjectionTarget(null);
            r.SmoothSpeedT = 1.0f;
            for (int k = 0; k < 10; ++k)
            {
                r.BasicRemeshPass();
            }
            r.BackPropropagate();
        }