Beispiel #1
0
        public virtual bool Extrude(int group_id = -1)
        {
            // duplicate loop vertices
            int NV = Loop.Vertices.Length;

            NewLoop          = new EdgeLoop(Mesh);
            NewLoop.Vertices = new int[NV];

            for (int i = 0; i < NV; ++i)
            {
                int vid = Loop.Vertices[i];
                NewLoop.Vertices[i] = Mesh.AppendVertex(Mesh, vid);
            }

            // move to offset positions
            for (int i = 0; i < NV; ++i)
            {
                Vector3D v     = Mesh.GetVertex(Loop.Vertices[i]);
                Vector3F n     = Mesh.GetVertexNormal(Loop.Vertices[i]);
                Vector3D new_v = PositionF(v, n, i);
                Mesh.SetVertex(NewLoop.Vertices[i], new_v);
            }

            // stitch interior
            MeshEditor edit = new MeshEditor(Mesh);

            NewTriangles = edit.StitchLoop(Loop.Vertices, NewLoop.Vertices, group_id);

            return(true);
        }
Beispiel #2
0
        public virtual bool Smooth()
        {
            int NV = Loop.Vertices.Length;

            double a          = math.MathUtil.Clamp(Alpha, 0, 1);
            double num_rounds = math.MathUtil.Clamp(Rounds, 0, 10000);

            for (int round = 0; round < num_rounds; ++round)
            {
                // compute
                gParallel.ForEach(Interval1i.Range(NV), (i) => {
                    int vid       = Loop.Vertices[(i + 1) % NV];
                    Vector3D prev = Mesh.GetVertex(Loop.Vertices[i]);
                    Vector3D cur  = Mesh.GetVertex(vid);
                    Vector3D next = Mesh.GetVertex(Loop.Vertices[(i + 2) % NV]);

                    Vector3D centroid   = (prev + next) * 0.5;
                    SmoothedPostions[i] = (1 - a) * cur + (a) * centroid;
                });

                // bake
                gParallel.ForEach(Interval1i.Range(NV), (i) => {
                    int vid      = Loop.Vertices[(i + 1) % NV];
                    Vector3D pos = SmoothedPostions[i];

                    if (ProjectF != null)
                    {
                        pos = ProjectF(pos, vid);
                    }

                    Mesh.SetVertex(vid, pos);
                });
            }

            return(true);
        }
Beispiel #3
0
        public virtual bool Cut()
        {
            double invalidDist = double.MinValue;

            // compute signs
            int MaxVID = Mesh.MaxVertexID;

            double[] signs = new double[MaxVID];
            gParallel.ForEach(Interval1i.Range(MaxVID), (vid) => {
                if (Mesh.IsVertex(vid))
                {
                    Vector3D v = Mesh.GetVertex(vid);
                    signs[vid] = (v - PlaneOrigin).Dot(PlaneNormal);
                }
                else
                {
                    signs[vid] = invalidDist;
                }
            });

            HashSet <int> ZeroEdges    = new HashSet <int>();
            HashSet <int> ZeroVertices = new HashSet <int>();
            HashSet <int> OnCutEdges   = new HashSet <int>();

            // have to skip processing of new edges. If edge id
            // is > max at start, is new. Otherwise if in NewEdges list, also new.
            int           MaxEID   = Mesh.MaxEdgeID;
            HashSet <int> NewEdges = new HashSet <int>();

            // cut existing edges with plane, using edge split
            for (int eid = 0; eid < MaxEID; ++eid)
            {
                if (Mesh.IsEdge(eid) == false)
                {
                    continue;
                }
                if (eid >= MaxEID || NewEdges.Contains(eid))
                {
                    continue;
                }

                Index2i ev = Mesh.GetEdgeV(eid);
                double  f0 = signs[ev.a];
                double  f1 = signs[ev.b];

                // If both signs are 0, this edge is on-contour
                // If one sign is 0, that vertex is on-contour
                int n0 = (Math.Abs(f0) < math.MathUtil.Epsilon) ? 1 : 0;
                int n1 = (Math.Abs(f1) < math.MathUtil.Epsilon) ? 1 : 0;
                if (n0 + n1 > 0)
                {
                    if (n0 + n1 == 2)
                    {
                        ZeroEdges.Add(eid);
                    }
                    else
                    {
                        ZeroVertices.Add((n0 == 1) ? ev[0] : ev[1]);
                    }
                    continue;
                }

                // no crossing
                if (f0 * f1 > 0)
                {
                    continue;
                }

                NGonsCore.geometry3Sharp.mesh.DMesh3.EdgeSplitInfo splitInfo;
                MeshResult result = Mesh.SplitEdge(eid, out splitInfo);
                if (result != MeshResult.Ok)
                {
                    throw new Exception("MeshPlaneCut.Cut: failed in SplitEdge");
                    //return false;
                }

                // SplitEdge just bisects edge - use plane intersection instead
                double   t      = f0 / (f0 - f1);
                Vector3D newPos = (1 - t) * Mesh.GetVertex(ev.a) + (t) * Mesh.GetVertex(ev.b);
                Mesh.SetVertex(splitInfo.vNew, newPos);

                NewEdges.Add(splitInfo.eNewBN);
                NewEdges.Add(splitInfo.eNewCN);  OnCutEdges.Add(splitInfo.eNewCN);
                if (splitInfo.eNewDN != NGonsCore.geometry3Sharp.mesh.DMesh3.InvalidID)
                {
                    NewEdges.Add(splitInfo.eNewDN);
                    OnCutEdges.Add(splitInfo.eNewDN);
                }
            }

            // remove one-rings of all positive-side vertices.
            for (int i = 0; i < signs.Length; ++i)
            {
                if (signs[i] > 0 && Mesh.IsVertex(i))
                {
                    Mesh.RemoveVertex(i, true, false);
                }
            }

            // ok now we extract boundary loops, but restricted
            // to either the zero-edges we found, or the edges we created! bang!!
            Func <int, bool> CutEdgeFilterF = (eid) => {
                if (OnCutEdges.Contains(eid) || ZeroEdges.Contains(eid))
                {
                    return(true);
                }
                return(false);
            };

            try {
                MeshBoundaryLoops loops = new MeshBoundaryLoops(Mesh, false);
                loops.EdgeFilterF = CutEdgeFilterF;
                loops.Compute();

                CutLoops       = loops.Loops;
                CutLoopsFailed = false;
            } catch {
                CutLoops       = new List <EdgeLoop>();
                CutLoopsFailed = true;
            }

            return(true);
        }         // Cut()