Example #1
0
        public void Check()
        {
            MeshUtils.Edge e;

            MeshUtils.Face fPrev = _fHead, f;
            for (fPrev = _fHead; (f = fPrev._next) != _fHead; fPrev = f)
            {
                e = f._anEdge;
                do
                {
                    Debug.Assert(e._Sym != e);
                    Debug.Assert(e._Sym._Sym == e);
                    Debug.Assert(e._Lnext._Onext._Sym == e);
                    Debug.Assert(e._Onext._Sym._Lnext == e);
                    Debug.Assert(e._Lface == f);
                    e = e._Lnext;
                } while (e != f._anEdge);
            }
            Debug.Assert(f._prev == fPrev && f._anEdge == null);

            MeshUtils.Vertex vPrev = _vHead, v;
            for (vPrev = _vHead; (v = vPrev._next) != _vHead; vPrev = v)
            {
                Debug.Assert(v._prev == vPrev);
                e = v._anEdge;
                do
                {
                    Debug.Assert(e._Sym != e);
                    Debug.Assert(e._Sym._Sym == e);
                    Debug.Assert(e._Lnext._Onext._Sym == e);
                    Debug.Assert(e._Onext._Sym._Lnext == e);
                    Debug.Assert(e._Org == v);
                    e = e._Onext;
                } while (e != v._anEdge);
            }
            Debug.Assert(v._prev == vPrev && v._anEdge == null);

            MeshUtils.Edge ePrev = _eHead;
            for (ePrev = _eHead; (e = ePrev._next) != _eHead; ePrev = e)
            {
                Debug.Assert(e._Sym._next == ePrev._Sym);
                Debug.Assert(e._Sym != e);
                Debug.Assert(e._Sym._Sym == e);
                Debug.Assert(e._Org != null);
                Debug.Assert(e._Dst != null);
                Debug.Assert(e._Lnext._Onext._Sym == e);
                Debug.Assert(e._Onext._Sym._Lnext == e);
            }
            Debug.Assert(e._Sym._next == ePrev._Sym &&
                         e._Sym == _eHeadSym &&
                         e._Sym._Sym == e &&
                         e._Org == null && e._Dst == null &&
                         e._Lface == null && e._Rface == null);
        }
Example #2
0
    /// <summary>
    /// Destroys a face and removes it from the global face list. All edges of
    /// fZap will have a NULL pointer as their left face. Any edges which
    /// also have a NULL pointer as their right face are deleted entirely
    /// (along with any isolated vertices this produces).
    /// An entire mesh can be deleted by zapping its faces, one at a time,
    /// in any order. Zapped faces cannot be used in further mesh operations!
    /// </summary>
    public static void ZapFace(IPool pool, MeshUtils.Face fZap)
    {
        MeshUtils.Edge eStart = fZap._anEdge;

        // walk around face, deleting edges whose right face is also NULL
        MeshUtils.Edge eNext = eStart._Lnext;
        MeshUtils.Edge e;
        do
        {
            e     = eNext;
            eNext = e._Lnext;

            e._Lface = null;
            switch (e._Rface)
            {
            case null:
            {
                // delete the edge -- see TESSmeshDelete above

                if (e._Onext == e)
                {
                    MeshUtils.KillVertex(pool, e._Org, null);
                }
                else
                {
                    // Make sure that e._Org points to a valid half-edge
                    e._Org._anEdge = e._Onext;
                    MeshUtils.Splice(e, e._Oprev);
                }
                MeshUtils.Edge eSym = e._Sym;
                if (eSym._Onext == eSym)
                {
                    MeshUtils.KillVertex(pool, eSym._Org, null);
                }
                else
                {
                    // Make sure that eSym._Org points to a valid half-edge
                    eSym._Org._anEdge = eSym._Onext;
                    MeshUtils.Splice(eSym, eSym._Oprev);
                }
                MeshUtils.KillEdge(pool, e);
                break;
            }
            }
        } while (e != eStart);

        /* delete from circular doubly-linked list */
        MeshUtils.Face fPrev = fZap._prev;
        MeshUtils.Face fNext = fZap._next;
        fNext._prev = fPrev;
        fPrev._next = fNext;

        pool.Return(fZap);
    }
Example #3
0
        /// <summary>
        /// Destroys a face and removes it from the global face list. All edges of
        /// fZap will have a NULL pointer as their left face. Any edges which
        /// also have a NULL pointer as their right face are deleted entirely
        /// (along with any isolated vertices this produces).
        /// An entire mesh can be deleted by zapping its faces, one at a time,
        /// in any order. Zapped faces cannot be used in further mesh operations!
        /// </summary>
        public void ZapFace(MeshUtils.Face fZap)
        {
            var eStart = fZap._anEdge;

            // walk around face, deleting edges whose right face is also NULL
            var eNext = eStart._Lnext;

            MeshUtils.Edge e, eSym;
            do
            {
                e     = eNext;
                eNext = e._Lnext;

                e._Lface = null;
                if (e._Rface == null)
                {
                    // delete the edge -- see TESSmeshDelete above

                    if (e._Onext == e)
                    {
                        MeshUtils.KillVertex(e._Org, null);
                    }
                    else
                    {
                        // Make sure that e._Org points to a valid half-edge
                        e._Org._anEdge = e._Onext;
                        MeshUtils.Splice(e, e._Oprev);
                    }
                    eSym = e._Sym;
                    if (eSym._Onext == eSym)
                    {
                        MeshUtils.KillVertex(eSym._Org, null);
                    }
                    else
                    {
                        // Make sure that eSym._Org points to a valid half-edge
                        eSym._Org._anEdge = eSym._Onext;
                        MeshUtils.Splice(eSym, eSym._Oprev);
                    }
                    MeshUtils.KillEdge(e);
                }
            } while (e != eStart);

            /* delete from circular doubly-linked list */
            var fPrev = fZap._prev;
            var fNext = fZap._next;

            fNext._prev = fPrev;
            fPrev._next = fNext;

            fZap.Free();
        }
Example #4
0
        public override void Reset()
        {
            MeshUtils.Face f = _fHead._next;
            while (true)
            {
                MeshUtils.Face fNext = f._next;
                f.Free();
                if (f == _fHead)
                {
                    break;
                }
                f = fNext;
            }

            MeshUtils.Vertex v = _vHead._next;
            while (true)
            {
                MeshUtils.Vertex vNext = v._next;
                v.Free();
                if (v == _vHead)
                {
                    break;
                }
                v = vNext;
            }

            for (int i = 0; i < _allEdgePairs.Count; i++)
            {
                MeshUtils.EdgePair pair = _allEdgePairs[i];

                MeshUtils.Edge e = pair._e;
                if (!e.IsReturnedToPool()) // (can be Free in KillEdge)
                {
                    e.Free();
                }

                MeshUtils.Edge eSym = pair._eSym;
                if (!eSym.IsReturnedToPool()) // (can be Free in KillEdge)
                {
                    eSym.Free();
                }

                pair.Free();
            }
            _allEdgePairs.Clear();

            _vHead = null;
            _fHead = null;
            _eHead = _eHeadSym = null;
        }
        /// <summary>
        /// TessellateMonoRegion( face ) tessellates a monotone region
        /// (what else would it do??)  The region must consist of a single
        /// loop of half-edges (see mesh.h) oriented CCW.  "Monotone" in this
        /// case means that any vertical line intersects the interior of the
        /// region in a single interval.  
        /// 
        /// Tessellation consists of adding interior edges (actually pairs of
        /// half-edges), to split the region into non-overlapping triangles.
        /// 
        /// The basic idea is explained in Preparata and Shamos (which I don't
        /// have handy right now), although their implementation is more
        /// complicated than this one.  The are two edge chains, an upper chain
        /// and a lower chain.  We process all vertices from both chains in order,
        /// from right to left.
        /// 
        /// The algorithm ensures that the following invariant holds after each
        /// vertex is processed: the untessellated region consists of two
        /// chains, where one chain (say the upper) is a single edge, and
        /// the other chain is concave.  The left vertex of the single edge
        /// is always to the left of all vertices in the concave chain.
        /// 
        /// Each step consists of adding the rightmost unprocessed vertex to one
        /// of the two chains, and forming a fan of triangles from the rightmost
        /// of two chain endpoints.  Determining whether we can add each triangle
        /// to the fan is a simple orientation test.  By making the fan as large
        /// as possible, we restore the invariant (check it yourself).
        /// </summary>
        private void TessellateMonoRegion(MeshUtils.Face face)
        {
            // All edges are oriented CCW around the boundary of the region.
            // First, find the half-edge whose origin vertex is rightmost.
            // Since the sweep goes from left to right, face->anEdge should
            // be close to the edge we want.
            var up = face._anEdge;
            Debug.Assert(up._Lnext != up && up._Lnext._Lnext != up);

            while (Geom.VertLeq(up._Dst, up._Org)) up = up._Lprev;
            while (Geom.VertLeq(up._Org, up._Dst)) up = up._Lnext;

            var lo = up._Lprev;

            while (up._Lnext != lo)
            {
                if (Geom.VertLeq(up._Dst, lo._Org))
                {
                    // up.Dst is on the left. It is safe to form triangles from lo.Org.
                    // The EdgeGoesLeft test guarantees progress even when some triangles
                    // are CW, given that the upper and lower chains are truly monotone.
                    while (lo._Lnext != up && (Geom.EdgeGoesLeft(lo._Lnext)
                        || Geom.EdgeSign(lo._Org, lo._Dst, lo._Lnext._Dst) <= 0.0f))
                    {
                        lo = _mesh.Connect(lo._Lnext, lo)._Sym;
                    }
                    lo = lo._Lprev;
                }
                else
                {
                    // lo.Org is on the left.  We can make CCW triangles from up.Dst.
                    while (lo._Lnext != up && (Geom.EdgeGoesRight(up._Lprev)
                        || Geom.EdgeSign(up._Dst, up._Org, up._Lprev._Org) >= 0.0f))
                    {
                        up = _mesh.Connect(up, up._Lprev)._Sym;
                    }
                    up = up._Lnext;
                }
            }

            // Now lo.Org == up.Dst == the leftmost vertex.  The remaining region
            // can be tessellated in a fan from this leftmost vertex.
            Debug.Assert(lo._Lnext != up);
            while (lo._Lnext._Lnext != up)
            {
                lo = _mesh.Connect(lo._Lnext, lo)._Sym;
            }
        }
Example #6
0
File: Mesh.cs Project: 894880010/MP
 public override void OnFree()
 {
     for (MeshUtils.Face f = _fHead._next, fNext = _fHead; f != _fHead; f = fNext)
     {
         fNext = f._next;
         f.Free();
     }
     for (MeshUtils.Vertex v = _vHead._next, vNext = _vHead; v != _vHead; v = vNext)
     {
         vNext = v._next;
         v.Free();
     }
     for (MeshUtils.Edge e = _eHead._next, eNext = _eHead; e != _eHead; e = eNext)
     {
         eNext = e._next;
         e.Free();
     }
 }
Example #7
0
    public void MergeConvexFaces(IPool pool, int maxVertsPerFace)
    {
        for (MeshUtils.Face f = _fHead._next; f != _fHead; f = f._next)
        {
            switch (f._inside)
            {
            // Skip faces which are outside the result
            case false:
                continue;
            }

            MeshUtils.Edge   eCur   = f._anEdge;
            MeshUtils.Vertex vStart = eCur._Org;

            while (true)
            {
                MeshUtils.Edge eNext = eCur._Lnext;
                MeshUtils.Edge eSym  = eCur._Sym;

                if (eSym is { _Lface._inside: true })
Example #8
0
        public void Reset(IPool pool)
        {
            for (MeshUtils.Face f = _fHead, fNext = _fHead; f._next != null; f = fNext)
            {
                fNext = f._next;
                pool.Return(f);
            }
            for (MeshUtils.Vertex v = _vHead, vNext = _vHead; v._next != null; v = vNext)
            {
                vNext = v._next;
                pool.Return(v);
            }
            for (MeshUtils.Edge e = _eHead, eNext = _eHead; e._next != null; e = eNext)
            {
                eNext = e._next;
                pool.Return(e._Sym);
                pool.Return(e);
            }

            _vHead = null;
            _fHead = null;
            _eHead = _eHeadSym = null;
        }
Example #9
0
        public void Init(IPool pool)
        {
            var v = _vHead = pool.Get <MeshUtils.Vertex>();
            var f = _fHead = pool.Get <MeshUtils.Face>();

            var pair = MeshUtils.EdgePair.Create(pool);
            var e    = _eHead = pair._e;
            var eSym = _eHeadSym = pair._eSym;

            v._next   = v._prev = v;
            v._anEdge = null;

            f._next   = f._prev = f;
            f._anEdge = null;
            f._trail  = null;
            f._marked = false;
            f._inside = false;

            e._next         = e;
            e._Sym          = eSym;
            e._Onext        = null;
            e._Lnext        = null;
            e._Org          = null;
            e._Lface        = null;
            e._winding      = 0;
            e._activeRegion = null;

            eSym._next         = eSym;
            eSym._Sym          = e;
            eSym._Onext        = null;
            eSym._Lnext        = null;
            eSym._Org          = null;
            eSym._Lface        = null;
            eSym._winding      = 0;
            eSym._activeRegion = null;
        }
Example #10
0
        // ReSharper restore InconsistentNaming
        public Mesh()
        {
            var v = _vHead = new MeshUtils.Vertex();
            var f = _fHead = new MeshUtils.Face();

            var pair = MeshUtils.EdgePair.Create();
            var e = _eHead = pair._e;
            var eSym = _eHeadSym = pair._eSym;

            v._next = v._prev = v;
            v._anEdge = null;

            f._next = f._prev = f;
            f._anEdge = null;
            f._trail = null;
            f._marked = false;
            f._inside = false;

            e._next = e;
            e._Sym = eSym;
            e._Onext = null;
            e._Lnext = null;
            e._Org = null;
            e._Lface = null;
            e._winding = 0;
            e._activeRegion = null;

            eSym._next = eSym;
            eSym._Sym = e;
            eSym._Onext = null;
            eSym._Lnext = null;
            eSym._Org = null;
            eSym._Lface = null;
            eSym._winding = 0;
            eSym._activeRegion = null;
        }
Example #11
0
File: Mesh.cs Project: 894880010/MP
 public override void Reset()
 {
     _vHead = null;
     _fHead = null;
     _eHead = _eHeadSym = null;
 }