Esempio n. 1
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 {
                DMesh3   inputmesh    = MeshSource.GetDMeshUnsafe();
                ISpatial inputSpatial = MeshSource.HasSpatial ? MeshSource.GetSpatial() : null;

                DMeshAABBTree3 spatial = (inputSpatial != null && inputSpatial is DMeshAABBTree3) ?
                                         inputSpatial as DMeshAABBTree3 : get_cached_spatial(inputmesh);
                DMesh3 meshIn = new DMesh3(inputmesh);

                MeshRepairOrientation repair = new MeshRepairOrientation(meshIn, spatial);
                repair.OrientComponents();
                repair.SolveGlobalOrientation();

                if (invert_result)
                {
                    meshIn.ReverseOrientation(true);
                }

                ResultMesh = meshIn;
                base.complete_update();
            } catch (Exception e) {
                PostOnOperatorException(e);
                ResultMesh = base.make_failure_output(MeshSource.GetDMeshUnsafe());
                base.complete_update();
            }
        }
Esempio n. 2
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;
        }
Esempio n. 3
0
        protected virtual DMesh3 compute_sharp_edge_flow()
        {
            DMesh3   sourceMesh   = MeshSource.GetDMeshUnsafe();
            ISpatial inputSpatial = MeshSource.GetSpatial();

            DMesh3   targetMesh    = TargetSource.GetDMeshUnsafe();
            ISpatial targetSpatial = TargetSource.GetSpatial();

            DMesh3 meshIn = new DMesh3(sourceMesh);

            if (is_invalidated())
            {
                return(null);
            }

            RemesherPro remesher = new RemesherPro(meshIn);

            remesher.SetTargetEdgeLength(TargetEdgeLength);
            remesher.PreventNormalFlips = this.PreventNormalFlips;
            remesher.EnableFlips        = this.EnableFlips;
            remesher.EnableSplits       = this.EnableSplits;
            remesher.EnableCollapses    = this.EnableCollapses;
            remesher.EnableSmoothing    = this.EnableSmoothing;
            remesher.SmoothSpeedT       = this.SmoothingSpeed;

            TransformedMeshProjectionTarget target =
                new TransformedMeshProjectionTarget(targetMesh, targetSpatial)
            {
                SourceToTargetXForm = source_to_target,
                TargetToSourceXForm = target_to_source
            };

            remesher.SetProjectionTarget(target);

            if (sourceMesh.CachedIsClosed == false)
            {
                if (remesher.Constraints == null)
                {
                    remesher.SetExternalConstraints(new MeshConstraints());
                }

                if (BoundaryMode == BoundaryModes.FreeBoundaries)
                {
                    MeshConstraintUtil.PreserveBoundaryLoops(remesher.Constraints, meshIn);
                }
                else if (BoundaryMode == BoundaryModes.FixedBoundaries)
                {
                    MeshConstraintUtil.FixAllBoundaryEdges(remesher.Constraints, meshIn);
                }
                else if (BoundaryMode == BoundaryModes.ConstrainedBoundaries)
                {
                    MeshConstraintUtil.FixAllBoundaryEdges_AllowSplit(remesher.Constraints, meshIn, 0);
                }
            }
            if (is_invalidated())
            {
                return(null);
            }

            remesher.Progress = new ProgressCancel(is_invalidated);
            remesher.SharpEdgeReprojectionRemesh(RemeshRounds, ProjectionRounds);

            if (is_invalidated())
            {
                return(null);
            }
            return(meshIn);
        }
Esempio n. 4
0
        protected virtual DMesh3 compute_bounded_distance()
        {
            DMesh3   sourceMesh   = MeshSource.GetDMeshUnsafe();
            ISpatial inputSpatial = MeshSource.GetSpatial();

            DMesh3   targetMesh    = TargetSource.GetDMeshUnsafe();
            ISpatial targetSpatial = TargetSource.GetSpatial();

            double max_dist = (TargetMaxDistance == double.MaxValue) ? double.MaxValue : TargetMaxDistance;

            DMesh3 meshIn = new DMesh3(sourceMesh);

            bool target_closed           = targetMesh.IsClosed();
            MeshVertexSelection roiV     = new MeshVertexSelection(meshIn);
            SpinLock            roi_lock = new SpinLock();

            gParallel.ForEach(meshIn.VertexIndices(), (vid) => {
                Vector3d pos       = meshIn.GetVertex(vid);
                Vector3d posTarget = TransformToTarget.TransformP(pos);
                double dist        = MeshQueries.NearestPointDistance(targetMesh, targetSpatial, posTarget, max_dist);
                bool inside        = (target_closed && targetSpatial.IsInside(posTarget));
                if (dist < max_dist || inside)
                {
                    bool taken = false;
                    roi_lock.Enter(ref taken);
                    roiV.Select(vid);
                    roi_lock.Exit();
                }
            });
            if (is_invalidated())
            {
                return(null);
            }

            MeshFaceSelection roi_faces = new MeshFaceSelection(meshIn, roiV, 1);

            roi_faces.ExpandToOneRingNeighbours(3);
            roi_faces.LocalOptimize();
            if (is_invalidated())
            {
                return(null);
            }

            RegionOperator op      = new RegionOperator(meshIn, roi_faces);
            DMesh3         meshROI = op.Region.SubMesh;

            if (is_invalidated())
            {
                return(null);
            }

            RemesherPro remesher = new RemesherPro(meshROI);

            remesher.SetTargetEdgeLength(TargetEdgeLength);
            remesher.PreventNormalFlips = this.PreventNormalFlips;
            remesher.EnableFlips        = this.EnableFlips;
            remesher.EnableSplits       = this.EnableSplits;
            remesher.EnableCollapses    = this.EnableCollapses;
            remesher.EnableSmoothing    = this.EnableSmoothing;
            remesher.SmoothSpeedT       = this.SmoothingSpeed;

            BoundedProjectionTarget target = new BoundedProjectionTarget()
            {
                Source = sourceMesh, SourceSpatial = inputSpatial,
                Target = targetMesh, TargetSpatial = targetSpatial,
                SourceToTargetXForm = source_to_target,
                TargetToSourceXForm = target_to_source,
                MaxDistance         = max_dist,
                Smoothness          = transition_smoothness
            };

            remesher.SetProjectionTarget(target);

            if (remesher.Constraints == null)
            {
                remesher.SetExternalConstraints(new MeshConstraints());
            }
            MeshConstraintUtil.FixAllBoundaryEdges(remesher.Constraints, meshROI);
            if (is_invalidated())
            {
                return(null);
            }

            remesher.Progress = new ProgressCancel(is_invalidated);
            remesher.FastestRemesh(RemeshRounds);
            if (is_invalidated())
            {
                return(null);
            }

            op.BackPropropagate();

            return(meshIn);
        }
        protected override void Update_GenerateMap()
        {
            base.begin_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("EnclosedRegionOffsetOp: 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);

            // [RMS] this is all f'n ugly!

            MeshVertexSelection selection = new MeshVertexSelection(mesh);

            selection.SelectTriangleVertices(loop.InteriorTriangles);


            // [TODO] do this inline w/ loop below? but then no maxdist!
            Dictionary <int, double> dists = new Dictionary <int, double>();
            double max_dist = 0;

            foreach (int vid in selection)
            {
                Vector3d v = mesh.GetVertex(vid);
                int      inearseg; double nearsegt;
                double   min_dist_sqr = curve.DistanceSquared(v, out inearseg, out nearsegt);
                min_dist_sqr = Math.Sqrt(min_dist_sqr);
                max_dist     = Math.Max(min_dist_sqr, max_dist);
                dists[vid]   = min_dist_sqr;
            }


            lock (Displacement) {
                Displacement.Clear();
                Displacement.Resize(mesh.MaxVertexID);

                // todo: can do this in parallel...
                foreach (int vid in selection)
                {
                    //Vector3d v = mesh.GetVertex(vid);

                    // [TODO]...
                    double dist    = max_dist - dists[vid];
                    double falloff = Falloff.FalloffT(dist / max_dist);

                    Vector3d n = mesh.GetVertexNormal(vid);
                    n = n - n.Dot(normal) * normal;
                    n.Normalize();

                    Displacement[vid] = falloff * offset_distance * n;
                }
            }

            // smooth it?

            base.complete_update();
        }