Ejemplo n.º 1
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();
            }
        }
Ejemplo n.º 2
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();
            }
        }
Ejemplo n.º 3
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            DMesh3_goo dMsh_goo = null;
            double     w        = 1;

            DA.GetData(0, ref dMsh_goo);
            DA.GetData(1, ref w);

            DMesh3 dMsh_copy = new DMesh3(dMsh_goo.Value, true);
            LaplacianMeshSmoother smoother = new LaplacianMeshSmoother(dMsh_copy);

            foreach (int vid in dMsh_copy.VertexIndices())
            {
                if (smoother.IsConstrained(vid) == false)
                {
                    smoother.SetConstraint(vid, dMsh_copy.GetVertex(vid), w);
                }
            }

            bool success = smoother.SolveAndUpdateMesh();
            bool isValid = dMsh_copy.CheckValidity();

            if (!success)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Laplacian smooth seems to have failed. Please check...");
            }

            if (!isValid)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Mesh seems to have been corrupted during smoothing. Please check...");
            }

            DA.SetData(0, dMsh_copy);
        }
Ejemplo n.º 4
0
        public bool Compute()
        {
            PlanarMesh   = BuildPlanarMesh(false);
            InflatedMesh = ComputeInflation(PlanarMesh);

            DMesh3 remeshed = GenerateRemesh(InflatedMesh);

            Flatten(remeshed);

            ResultMesh = ComputeInflation(remeshed);

            MeshBoundaryLoops loops = new MeshBoundaryLoops(ResultMesh);

            DMesh3 otherSide = new DMesh3(ResultMesh);

            foreach (int vid in otherSide.VertexIndices())
            {
                Vector3d v = otherSide.GetVertex(vid);
                v.z = -v.z;
                otherSide.SetVertex(vid, v);
            }
            otherSide.ReverseOrientation();

            MeshEditor editor = new MeshEditor(ResultMesh);

            int[] mapVArray;
            editor.AppendMesh(otherSide, out mapVArray);
            IndexMap mapV = new IndexMap(mapVArray);

            foreach (EdgeLoop loop in loops)
            {
                int[] otherLoop = (int[])loop.Vertices.Clone();
                IndexUtil.Apply(otherLoop, mapV);
                editor.StitchLoop(loop.Vertices, otherLoop);
            }


            Remesher remesh = new Remesher(ResultMesh);

            remesh.SetTargetEdgeLength(TargetEdgeLength);
            remesh.SmoothSpeedT = 0.25f;
            for (int k = 0; k < 10; ++k)
            {
                remesh.BasicRemeshPass();
            }
            ResultMesh = new DMesh3(ResultMesh, true);


            LaplacianMeshSmoother smoother = new LaplacianMeshSmoother(ResultMesh);

            foreach (int vid in ResultMesh.VertexIndices())
            {
                smoother.SetConstraint(vid, ResultMesh.GetVertex(vid), 0.5f, false);
            }
            smoother.SolveAndUpdateMesh();


            return(true);
        }
Ejemplo n.º 5
0
        public virtual void Update()
        {
            if (MeshSource == null)
            {
                throw new Exception("EnclosedRegionOffsetOp: must set valid MeshSource to compute!");
            }
            if (MeshSource.HasSpatial == false)
            {
                throw new Exception("EnclosedRegionOffsetOp: MeshSource must have spatial data structure!");
            }

            IMesh imesh = MeshSource.GetIMesh();

            if (imesh.HasVertexNormals == false)
            {
                throw new Exception("EnclosedRegionOffsetOp: input mesh does not have surface normals...");
            }
            if (imesh is DMesh3 == false)
            {
                throw new Exception("RegionOffsetOp: in current implementation, input mesh must be a DMesh3. Ugh.");
            }
            DMesh3   mesh    = imesh as DMesh3;
            ISpatial spatial = MeshSource.GetSpatial();

            DCurve3           curve = new DCurve3(CurveSource.GetICurve());
            MeshFacesFromLoop loop  = new MeshFacesFromLoop(mesh, curve, spatial);

            // extract submesh
            RegionOperator op      = new RegionOperator(mesh, loop.InteriorTriangles);
            DMesh3         submesh = op.Region.SubMesh;

            // find boundary verts and nbr ring
            HashSet <int> boundaryV    = new HashSet <int>(MeshIterators.BoundaryEdgeVertices(submesh));
            HashSet <int> boundaryNbrs = new HashSet <int>();

            foreach (int vid in boundaryV)
            {
                foreach (int nbrvid in submesh.VtxVerticesItr(vid))
                {
                    if (boundaryV.Contains(nbrvid) == false)
                    {
                        boundaryNbrs.Add(nbrvid);
                    }
                }
            }

            // [TODO] maybe should be not using vertex normal here?
            // use an averaged normal, or a constant for patch?

            // offset mesh if requested
            if (Math.Abs(offset_distance) > 0.0001)
            {
                foreach (int vid in submesh.VertexIndices())
                {
                    if (boundaryV.Contains(vid))
                    {
                        continue;
                    }
                    // if inner ring is non-zero, then it gets preserved below, and
                    // creates a crease...
                    //double dist = boundaryNbrs.Contains(vid) ? (offset_distance / 2) : offset_distance;
                    double dist = boundaryNbrs.Contains(vid) ? 0 : offset_distance;
                    submesh.SetVertex(vid,
                                      submesh.GetVertex(vid) + (float)dist * submesh.GetVertexNormal(vid));
                }
            }


            //double t = MathUtil.Clamp(1.0 - SmoothAlpha, 0.1, 1.0);
            double t = 1.0 - SmoothAlpha;

            t = t * t;
            double boundary_t = 5.0;
            double ring_t     = 1.0;

            // smooth submesh, with boundary-ring constraints
            LaplacianMeshSmoother smoother = new LaplacianMeshSmoother(submesh);

            foreach (int vid in submesh.VertexIndices())
            {
                if (boundaryV.Contains(vid))
                {
                    smoother.SetConstraint(vid, submesh.GetVertex(vid), boundary_t, true);
                }
                else if (boundaryNbrs.Contains(vid))
                {
                    smoother.SetConstraint(vid, submesh.GetVertex(vid), ring_t);
                }
                else
                {
                    smoother.SetConstraint(vid, submesh.GetVertex(vid), t);
                }
            }
            smoother.SolveAndUpdateMesh();


            // turn into displacement vectors
            Displacement.Clear();
            Displacement.Resize(mesh.MaxVertexID);
            foreach (int subvid in op.Region.SubMesh.VertexIndices())
            {
                Vector3d subv    = op.Region.SubMesh.GetVertex(subvid);
                int      basevid = op.Region.SubToBaseV[subvid];
                Vector3d basev   = op.Region.BaseMesh.GetVertex(basevid);
                Displacement[basevid] = subv - basev;
            }


            result_valid = true;
        }
Ejemplo n.º 6
0
        DMesh3 ComputeInflation(DMesh3 planarMesh)
        {
            DMesh3 mesh = new DMesh3(planarMesh);

            DijkstraGraphDistance dist = new DijkstraGraphDistance(
                mesh.MaxVertexID, false,
                (vid) => { return(mesh.IsVertex(vid)); },
                (a, b) => { return((float)mesh.GetVertex(a).Distance(mesh.GetVertex(b))); },
                mesh.VtxVerticesItr);

            foreach (int vid in MeshIterators.BoundaryVertices(mesh))
            {
                dist.AddSeed(vid, 0);
            }

            dist.Compute();
            float max_dist = dist.MaxDistance;

            float[] distances = new float[mesh.MaxVertexID];
            foreach (int vid in mesh.VertexIndices())
            {
                distances[vid] = dist.GetDistance(vid);
            }


            List <int> local_maxima = new List <int>();

            foreach (int vid in MeshIterators.InteriorVertices(mesh))
            {
                float d         = distances[vid];
                bool  is_maxima = true;
                foreach (int nbrid in mesh.VtxVerticesItr(vid))
                {
                    if (distances[nbrid] > d)
                    {
                        is_maxima = false;
                    }
                }
                if (is_maxima)
                {
                    local_maxima.Add(vid);
                }
            }

            // smooth distances   (really should use cotan here!!)
            float smooth_alpha  = 0.1f;
            int   smooth_rounds = 5;

            foreach (int ri in Interval1i.Range(smooth_rounds))
            {
                foreach (int vid in mesh.VertexIndices())
                {
                    float cur       = distances[vid];
                    float centroid  = 0;
                    int   nbr_count = 0;
                    foreach (int nbrid in mesh.VtxVerticesItr(vid))
                    {
                        centroid += distances[nbrid];
                        nbr_count++;
                    }
                    centroid      /= nbr_count;
                    distances[vid] = (1 - smooth_alpha) * cur + (smooth_alpha) * centroid;
                }
            }

            Vector3d normal = Vector3d.AxisZ;

            foreach (int vid in mesh.VertexIndices())
            {
                if (dist.IsSeed(vid))
                {
                    continue;
                }
                float h = distances[vid];

                // [RMS] there are different options here...
                h = 2 * (float)Math.Sqrt(h);

                float    offset = h;
                Vector3d d      = mesh.GetVertex(vid);
                mesh.SetVertex(vid, d + (Vector3d)(offset * normal));
            }


            DMesh3 compacted   = new DMesh3();
            var    compactInfo = compacted.CompactCopy(mesh);

            IndexUtil.Apply(local_maxima, compactInfo.MapV);
            mesh = compacted;
            MeshVertexSelection boundary_sel = new MeshVertexSelection(mesh);
            HashSet <int>       boundaryV    = new HashSet <int>(MeshIterators.BoundaryVertices(mesh));

            boundary_sel.Select(boundaryV);
            boundary_sel.ExpandToOneRingNeighbours();

            LaplacianMeshSmoother smoother = new LaplacianMeshSmoother(mesh);

            foreach (int vid in boundary_sel)
            {
                if (boundaryV.Contains(vid))
                {
                    smoother.SetConstraint(vid, mesh.GetVertex(vid), 100.0f, true);
                }
                else
                {
                    smoother.SetConstraint(vid, mesh.GetVertex(vid), 10.0f, false);
                }
            }
            foreach (int vid in local_maxima)
            {
                smoother.SetConstraint(vid, mesh.GetVertex(vid), 50, false);
            }

            bool ok = smoother.SolveAndUpdateMesh();

            Util.gDevAssert(ok);


            List <int>          intVerts = new List <int>(MeshIterators.InteriorVertices(mesh));
            MeshIterativeSmooth smooth   = new MeshIterativeSmooth(mesh, intVerts.ToArray(), true);

            smooth.SmoothType = MeshIterativeSmooth.SmoothTypes.Cotan;
            smooth.Rounds     = 10;
            smooth.Alpha      = 0.1f;
            smooth.Smooth();

            return(mesh);
        }