Example #1
0
        internal static FaceCount MaximumFan(Mogre.Utils.GluTesselator.GLUhalfEdge eOrig)
        {
            /* eOrig.Lface is the face we want to render.  We want to find the size
             * of a maximal fan around eOrig.Org.  To do this we just walk around
             * the origin vertex as far as possible in both directions.
             */
            FaceCount newFace = new FaceCount(0, null, renderFan);

            Mogre.Utils.GluTesselator.GLUface     trail = null;
            Mogre.Utils.GluTesselator.GLUhalfEdge e;

            for (e = eOrig; !Marked(e.Lface); e = e.Onext)
            {
                trail = AddToTrail(e.Lface, trail);
                ++newFace.size;
            }
            for (e = eOrig; !Marked(e.Sym.Lface); e = e.Sym.Lnext)
            {
                trail = AddToTrail(e.Sym.Lface, trail);
                ++newFace.size;
            }
            newFace.eStart = e;
            /*LINTED*/
            FreeTrail(trail);
            return(newFace);
        }
Example #2
0
        /* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left
         * face of all edges in the face loop to which eOrig belongs.  "fNext" gives
         * a place to insert the new face in the global face list.  We insert
         * the new face *before* fNext so that algorithms which walk the face
         * list will not see the newly created faces.
         */
        internal static void  MakeFace(Mogre.Utils.GluTesselator.GLUface newFace, Mogre.Utils.GluTesselator.GLUhalfEdge eOrig, Mogre.Utils.GluTesselator.GLUface fNext)
        {
            Mogre.Utils.GluTesselator.GLUhalfEdge e;
            Mogre.Utils.GluTesselator.GLUface     fPrev;
            Mogre.Utils.GluTesselator.GLUface     fNew = newFace;

            //assert(fNew != null);

            /* insert in circular doubly-linked list before fNext */
            fPrev      = fNext.prev;
            fNew.prev  = fPrev;
            fPrev.next = fNew;
            fNew.next  = fNext;
            fNext.prev = fNew;

            fNew.anEdge = eOrig;
            fNew.data   = null;
            fNew.trail  = null;
            fNew.marked = false;

            /* The new face is marked "inside" if the old one was.  This is a
             * convenience for the common case where a face has been split in two.
             */
            fNew.inside = fNext.inside;

            /* fix other edges on this face loop */
            e = eOrig;
            do
            {
                e.Lface = fNew;
                e       = e.Lnext;
            }while (e != eOrig);
        }
Example #3
0
        /* __gl_meshDelete( eDel ) removes the edge eDel.  There are several cases:
         * if (eDel.Lface != eDel.Rface), we join two loops into one; the loop
         * eDel.Lface is deleted.  Otherwise, we are splitting one loop into two;
         * the newly created loop will contain eDel.Dst.  If the deletion of eDel
         * would create isolated vertices, those are deleted as well.
         *
         * This function could be implemented as two calls to __gl_meshSplice
         * plus a few calls to memFree, but this would allocate and delete
         * unnecessary vertices and faces.
         */
        internal static bool __gl_meshDelete(Mogre.Utils.GluTesselator.GLUhalfEdge eDel)
        {
            Mogre.Utils.GluTesselator.GLUhalfEdge eDelSym = eDel.Sym;
            bool joiningLoops = false;

            /* First step: disconnect the origin vertex eDel.Org.  We make all
             * changes to get a consistent mesh in this "intermediate" state.
             */
            if (eDel.Lface != eDel.Sym.Lface)
            {
                /* We are joining two loops into one -- remove the left face */
                joiningLoops = true;
                KillFace(eDel.Lface, eDel.Sym.Lface);
            }

            if (eDel.Onext == eDel)
            {
                KillVertex(eDel.Org, null);
            }
            else
            {
                /* Make sure that eDel.Org and eDel.Sym.Lface point to valid half-edges */
                eDel.Sym.Lface.anEdge = eDel.Sym.Lnext;
                eDel.Org.anEdge       = eDel.Onext;

                Splice(eDel, eDel.Sym.Lnext);
                if (!joiningLoops)
                {
                    Mogre.Utils.GluTesselator.GLUface newFace = new Mogre.Utils.GluTesselator.GLUface();

                    /* We are splitting one loop into two -- create a new loop for eDel. */
                    MakeFace(newFace, eDel, eDel.Lface);
                }
            }

            /* Claim: the mesh is now in a consistent state, except that eDel.Org
             * may have been deleted.  Now we disconnect eDel.Dst.
             */
            if (eDelSym.Onext == eDelSym)
            {
                KillVertex(eDelSym.Org, null);
                KillFace(eDelSym.Lface, null);
            }
            else
            {
                /* Make sure that eDel.Dst and eDel.Lface point to valid half-edges */
                eDel.Lface.anEdge  = eDelSym.Sym.Lnext;
                eDelSym.Org.anEdge = eDelSym.Onext;
                Splice(eDelSym, eDelSym.Sym.Lnext);
            }

            /* Any isolated vertices or faces have already been freed. */
            KillEdge(eDel);

            return(true);
        }
Example #4
0
        /* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
         */
        public static void  __gl_meshCheckMesh(Mogre.Utils.GluTesselator.GLUmesh mesh)
        {
            Mogre.Utils.GluTesselator.GLUface     fHead = mesh.fHead;
            Mogre.Utils.GluTesselator.GLUvertex   vHead = mesh.vHead;
            Mogre.Utils.GluTesselator.GLUhalfEdge eHead = mesh.eHead;
            Mogre.Utils.GluTesselator.GLUface     f, fPrev;
            Mogre.Utils.GluTesselator.GLUvertex   v, vPrev;
            Mogre.Utils.GluTesselator.GLUhalfEdge e, ePrev;

            fPrev = fHead;
            for (fPrev = fHead; (f = fPrev.next) != fHead; fPrev = f)
            {
                //assert(f.prev == fPrev);
                e = f.anEdge;
                do
                {
                    //assert(e.Sym != e);
                    //assert(e.Sym.Sym == e);
                    //assert(e.Lnext.Onext.Sym == e);
                    //assert(e.Onext.Sym.Lnext == e);
                    //assert(e.Lface == f);
                    e = e.Lnext;
                }while (e != f.anEdge);
            }
            //assert(f.prev == fPrev && f.anEdge == null && f.data == null);

            vPrev = vHead;
            for (vPrev = vHead; (v = vPrev.next) != vHead; vPrev = v)
            {
                //assert(v.prev == vPrev);
                e = v.anEdge;
                do
                {
                    //assert(e.Sym != e);
                    //assert(e.Sym.Sym == e);
                    //assert(e.Lnext.Onext.Sym == e);
                    //assert(e.Onext.Sym.Lnext == e);
                    //assert(e.Org == v);
                    e = e.Onext;
                }while (e != v.anEdge);
            }
            //assert(v.prev == vPrev && v.anEdge == null && v.data == null);

            ePrev = eHead;
            for (ePrev = eHead; (e = ePrev.next) != eHead; ePrev = e)
            {
                //assert(e.Sym.next == ePrev.Sym);
                //assert(e.Sym != e);
                //assert(e.Sym.Sym == e);
                //assert(e.Org != null);
                //assert(e.Sym.Org != null);
                //assert(e.Lnext.Onext.Sym == e);
                //assert(e.Onext.Sym.Lnext == e);
            }
            //assert(e.Sym.next == ePrev.Sym && e.Sym == mesh.eHeadSym && e.Sym.Sym == e && e.Org == null && e.Sym.Org == null && e.Lface == null && e.Sym.Lface == null);
        }
Example #5
0
        /* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
         */
        internal static void  __gl_meshDeleteMeshZap(Mogre.Utils.GluTesselator.GLUmesh mesh)
        {
            Mogre.Utils.GluTesselator.GLUface fHead = mesh.fHead;

            while (fHead.next != fHead)
            {
                __gl_meshZapFace(fHead.next);
            }
            //assert(mesh.vHead.next == mesh.vHead);
        }
Example #6
0
        internal static void  RenderMaximumFaceGroup(GLUtessellatorImpl tess, Mogre.Utils.GluTesselator.GLUface fOrig)
        {
            /* We want to find the largest triangle fan or strip of unmarked faces
             * which includes the given face fOrig.  There are 3 possible fans
             * passing through fOrig (one centered at each vertex), and 3 possible
             * strips (one for each CCW permutation of the vertices).  Our strategy
             * is to try all of these, and take the primitive which uses the most
             * triangles (a greedy approach).
             */
            Mogre.Utils.GluTesselator.GLUhalfEdge e = fOrig.anEdge;
            FaceCount max     = new FaceCount();
            FaceCount newFace = new FaceCount();

            max.size   = 1;
            max.eStart = e;
            max.render = renderTriangle;

            if (!tess.flagBoundary)
            {
                newFace = MaximumFan(e);
                if (newFace.size > max.size)
                {
                    max = newFace;
                }
                newFace = MaximumFan(e.Lnext);
                if (newFace.size > max.size)
                {
                    max = newFace;
                }
                newFace = MaximumFan(e.Onext.Sym);
                if (newFace.size > max.size)
                {
                    max = newFace;
                }

                newFace = MaximumStrip(e);
                if (newFace.size > max.size)
                {
                    max = newFace;
                }
                newFace = MaximumStrip(e.Lnext);
                if (newFace.size > max.size)
                {
                    max = newFace;
                }
                newFace = MaximumStrip(e.Onext.Sym);
                if (newFace.size > max.size)
                {
                    max = newFace;
                }
            }
            max.render.render(tess, max.eStart, max.size);
        }
Example #7
0
        /* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
         * mesh connectivity and topology.  It changes the mesh so that
         *	eOrg->Onext <- OLD( eDst->Onext )
         *	eDst->Onext <- OLD( eOrg->Onext )
         * where OLD(...) means the value before the meshSplice operation.
         *
         * This can have two effects on the vertex structure:
         *  - if eOrg->Org != eDst->Org, the two vertices are merged together
         *  - if eOrg->Org == eDst->Org, the origin is split into two vertices
         * In both cases, eDst->Org is changed and eOrg->Org is untouched.
         *
         * Similarly (and independently) for the face structure,
         *  - if eOrg->Lface == eDst->Lface, one loop is split into two
         *  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
         * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
         *
         * Some special cases:
         * If eDst == eOrg, the operation has no effect.
         * If eDst == eOrg->Lnext, the new face will have a single edge.
         * If eDst == eOrg->Lprev, the old face will have a single edge.
         * If eDst == eOrg->Onext, the new vertex will have a single edge.
         * If eDst == eOrg->Oprev, the old vertex will have a single edge.
         */
        public static bool __gl_meshSplice(Mogre.Utils.GluTesselator.GLUhalfEdge eOrg, Mogre.Utils.GluTesselator.GLUhalfEdge eDst)
        {
            bool joiningLoops    = false;
            bool joiningVertices = false;

            if (eOrg == eDst)
            {
                return(true);
            }

            if (eDst.Org != eOrg.Org)
            {
                /* We are merging two disjoint vertices -- destroy eDst->Org */
                joiningVertices = true;
                KillVertex(eDst.Org, eOrg.Org);
            }
            if (eDst.Lface != eOrg.Lface)
            {
                /* We are connecting two disjoint loops -- destroy eDst.Lface */
                joiningLoops = true;
                KillFace(eDst.Lface, eOrg.Lface);
            }

            /* Change the edge structure */
            Splice(eDst, eOrg);

            if (!joiningVertices)
            {
                Mogre.Utils.GluTesselator.GLUvertex newVertex = new Mogre.Utils.GluTesselator.GLUvertex();

                /* We split one vertex into two -- the new vertex is eDst.Org.
                 * Make sure the old vertex points to a valid half-edge.
                 */
                MakeVertex(newVertex, eDst, eOrg.Org);
                eOrg.Org.anEdge = eOrg;
            }
            if (!joiningLoops)
            {
                Mogre.Utils.GluTesselator.GLUface newFace = new Mogre.Utils.GluTesselator.GLUface();

                /* We split one loop into two -- the new loop is eDst.Lface.
                 * Make sure the old face points to a valid half-edge.
                 */
                MakeFace(newFace, eDst, eOrg.Lface);
                eOrg.Lface.anEdge = eOrg;
            }

            return(true);
        }
Example #8
0
        /// <summary>***************** Other Operations *********************</summary>

        /* __gl_meshZapFace( fZap ) 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!
         */
        internal static void  __gl_meshZapFace(Mogre.Utils.GluTesselator.GLUface fZap)
        {
            Mogre.Utils.GluTesselator.GLUhalfEdge eStart = fZap.anEdge;
            Mogre.Utils.GluTesselator.GLUhalfEdge e, eNext, eSym;
            Mogre.Utils.GluTesselator.GLUface     fPrev, fNext;

            /* walk around face, deleting edges whose right face is also null */
            eNext = eStart.Lnext;
            do
            {
                e     = eNext;
                eNext = e.Lnext;

                e.Lface = null;
                if (e.Sym.Lface == null)
                {
                    /* delete the edge -- see __gl_MeshDelete above */

                    if (e.Onext == e)
                    {
                        KillVertex(e.Org, null);
                    }
                    else
                    {
                        /* Make sure that e.Org points to a valid half-edge */
                        e.Org.anEdge = e.Onext;
                        Splice(e, e.Sym.Lnext);
                    }
                    eSym = e.Sym;
                    if (eSym.Onext == eSym)
                    {
                        KillVertex(eSym.Org, null);
                    }
                    else
                    {
                        /* Make sure that eSym.Org points to a valid half-edge */
                        eSym.Org.anEdge = eSym.Onext;
                        Splice(eSym, eSym.Sym.Lnext);
                    }
                    KillEdge(e);
                }
            }while (e != eStart);

            /* delete from circular doubly-linked list */
            fPrev      = fZap.prev;
            fNext      = fZap.next;
            fNext.prev = fPrev;
            fPrev.next = fNext;
        }
Example #9
0
 private static void  FreeTrail(Mogre.Utils.GluTesselator.GLUface t)
 {
     if (true)
     {
         while (t != null)
         {
             t.marked = false;
             t        = t.trail;
         }
     }
     else
     {
         /* absorb trailing semicolon */
     }
 }
Example #10
0
        /// <summary>*************** Basic Edge Operations *********************</summary>

        /* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face).
         * The loop consists of the two new half-edges.
         */
        public static Mogre.Utils.GluTesselator.GLUhalfEdge __gl_meshMakeEdge(Mogre.Utils.GluTesselator.GLUmesh mesh)
        {
            Mogre.Utils.GluTesselator.GLUvertex   newVertex1 = new Mogre.Utils.GluTesselator.GLUvertex();
            Mogre.Utils.GluTesselator.GLUvertex   newVertex2 = new Mogre.Utils.GluTesselator.GLUvertex();
            Mogre.Utils.GluTesselator.GLUface     newFace    = new Mogre.Utils.GluTesselator.GLUface();
            Mogre.Utils.GluTesselator.GLUhalfEdge e;

            e = MakeEdge(mesh.eHead);
            if (e == null)
            {
                return(null);
            }

            MakeVertex(newVertex1, e, mesh.vHead);
            MakeVertex(newVertex2, e.Sym, mesh.vHead);
            MakeFace(newFace, e, mesh.fHead);
            return(e);
        }
Example #11
0
        /* KillFace( fDel ) destroys a face and removes it from the global face
         * list.  It updates the face loop to point to a given new face.
         */
        internal static void  KillFace(Mogre.Utils.GluTesselator.GLUface fDel, Mogre.Utils.GluTesselator.GLUface newLface)
        {
            Mogre.Utils.GluTesselator.GLUhalfEdge e, eStart = fDel.anEdge;
            Mogre.Utils.GluTesselator.GLUface     fPrev, fNext;

            /* change the left face of all affected edges */
            e = eStart;
            do
            {
                e.Lface = newLface;
                e       = e.Lnext;
            }while (e != eStart);

            /* delete from circular doubly-linked list */
            fPrev      = fDel.prev;
            fNext      = fDel.next;
            fNext.prev = fPrev;
            fPrev.next = fNext;
        }
Example #12
0
        /* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg.Sym.Org
         * to eDst.Org, and returns the corresponding half-edge eNew.
         * If eOrg.Lface == eDst.Lface, this splits one loop into two,
         * and the newly created loop is eNew.Lface.  Otherwise, two disjoint
         * loops are merged into one, and the loop eDst.Lface is destroyed.
         *
         * If (eOrg == eDst), the new face will have only two edges.
         * If (eOrg.Lnext == eDst), the old face is reduced to a single edge.
         * If (eOrg.Lnext.Lnext == eDst), the old face is reduced to two edges.
         */
        internal static Mogre.Utils.GluTesselator.GLUhalfEdge __gl_meshConnect(Mogre.Utils.GluTesselator.GLUhalfEdge eOrg, Mogre.Utils.GluTesselator.GLUhalfEdge eDst)
        {
            Mogre.Utils.GluTesselator.GLUhalfEdge eNewSym;
            bool joiningLoops = false;

            Mogre.Utils.GluTesselator.GLUhalfEdge eNew = MakeEdge(eOrg);

            eNewSym = eNew.Sym;

            if (eDst.Lface != eOrg.Lface)
            {
                /* We are connecting two disjoint loops -- destroy eDst.Lface */
                joiningLoops = true;
                KillFace(eDst.Lface, eOrg.Lface);
            }

            /* Connect the new edge appropriately */
            Splice(eNew, eOrg.Lnext);
            Splice(eNewSym, eDst);

            /* Set the vertex and face information */
            eNew.Org    = eOrg.Sym.Org;
            eNewSym.Org = eDst.Org;
            eNew.Lface  = eNewSym.Lface = eOrg.Lface;

            /* Make sure the old face points to a valid half-edge */
            eOrg.Lface.anEdge = eNewSym;

            if (!joiningLoops)
            {
                Mogre.Utils.GluTesselator.GLUface newFace = new Mogre.Utils.GluTesselator.GLUface();

                /* We split one loop into two -- the new loop is eNew.Lface */
                MakeFace(newFace, eNew, eOrg.Lface);
            }
            return(eNew);
        }
Example #13
0
        internal static void  CheckOrientation(GLUtessellatorImpl tess)
        {
            double area;

            Mogre.Utils.GluTesselator.GLUface     f, fHead = tess.mesh.fHead;
            Mogre.Utils.GluTesselator.GLUvertex   v, vHead = tess.mesh.vHead;
            Mogre.Utils.GluTesselator.GLUhalfEdge e;

            /* When we compute the normal automatically, we choose the orientation
             * so that the the sum of the signed areas of all contours is non-negative.
             */
            area = 0;
            for (f = fHead.next; f != fHead; f = f.next)
            {
                e = f.anEdge;
                if (e.winding <= 0)
                {
                    continue;
                }
                do
                {
                    area += (e.Org.s - e.Sym.Org.s) * (e.Org.t + e.Sym.Org.t);
                    e     = e.Lnext;
                }while (e != f.anEdge);
            }
            if (area < 0)
            {
                /* Reverse the orientation by flipping all the t-coordinates */
                for (v = vHead.next; v != vHead; v = v.next)
                {
                    v.t = -v.t;
                }
                tess.tUnit[0] = -tess.tUnit[0];
                tess.tUnit[1] = -tess.tUnit[1];
                tess.tUnit[2] = -tess.tUnit[2];
            }
        }
Example #14
0
        internal static void  RenderLonelyTriangles(GLUtessellatorImpl tess, Mogre.Utils.GluTesselator.GLUface f)
        {
            /* Now we render all the separate triangles which could not be
             * grouped into a triangle fan or strip.
             */
            Mogre.Utils.GluTesselator.GLUhalfEdge e;
            int newState;
            int edgeState = -1;              /* force edge state output for first vertex */

            tess.callBeginOrBeginData(GL.GL_TRIANGLES);

            for (; f != null; f = f.trail)
            {
                /* Loop once for each edge (there will always be 3 edges) */

                e = f.anEdge;
                do
                {
                    if (tess.flagBoundary)
                    {
                        /* Set the "edge state" to true just before we output the
                         * first vertex of each edge on the polygon boundary.
                         */
                        newState = (!e.Sym.Lface.inside)?1:0;
                        if (edgeState != newState)
                        {
                            edgeState = newState;
                            tess.callEdgeFlagOrEdgeFlagData(edgeState != 0);
                        }
                    }
                    tess.callVertexOrVertexData(e.Org.data);

                    e = e.Lnext;
                }while (e != f.anEdge);
            }
            tess.callEndOrEndData();
        }
Example #15
0
        /* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
         * both meshes, and returns the new mesh (the old meshes are destroyed).
         */
        internal static Mogre.Utils.GluTesselator.GLUmesh __gl_meshUnion(Mogre.Utils.GluTesselator.GLUmesh mesh1, Mogre.Utils.GluTesselator.GLUmesh mesh2)
        {
            Mogre.Utils.GluTesselator.GLUface     f1 = mesh1.fHead;
            Mogre.Utils.GluTesselator.GLUvertex   v1 = mesh1.vHead;
            Mogre.Utils.GluTesselator.GLUhalfEdge e1 = mesh1.eHead;
            Mogre.Utils.GluTesselator.GLUface     f2 = mesh2.fHead;
            Mogre.Utils.GluTesselator.GLUvertex   v2 = mesh2.vHead;
            Mogre.Utils.GluTesselator.GLUhalfEdge e2 = mesh2.eHead;

            /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */
            if (f2.next != f2)
            {
                f1.prev.next = f2.next;
                f2.next.prev = f1.prev;
                f2.prev.next = f1;
                f1.prev      = f2.prev;
            }

            if (v2.next != v2)
            {
                v1.prev.next = v2.next;
                v2.next.prev = v1.prev;
                v2.prev.next = v1;
                v1.prev      = v2.prev;
            }

            if (e2.next != e2)
            {
                e1.Sym.next.Sym.next = e2.next;
                e2.next.Sym.next     = e1.Sym.next;
                e2.Sym.next.Sym.next = e1;
                e1.Sym.next          = e2.Sym.next;
            }

            return(mesh1);
        }
Example #16
0
        /* __gl_meshDelete( eDel ) removes the edge eDel.  There are several cases:
        * if (eDel.Lface != eDel.Rface), we join two loops into one; the loop
        * eDel.Lface is deleted.  Otherwise, we are splitting one loop into two;
        * the newly created loop will contain eDel.Dst.  If the deletion of eDel
        * would create isolated vertices, those are deleted as well.
        *
        * This function could be implemented as two calls to __gl_meshSplice
        * plus a few calls to memFree, but this would allocate and delete
        * unnecessary vertices and faces.
        */
        internal static bool __gl_meshDelete(Mogre.Utils.GluTesselator.GLUhalfEdge eDel)
        {
            Mogre.Utils.GluTesselator.GLUhalfEdge eDelSym = eDel.Sym;
            bool joiningLoops = false;

            /* First step: disconnect the origin vertex eDel.Org.  We make all
            * changes to get a consistent mesh in this "intermediate" state.
            */
            if (eDel.Lface != eDel.Sym.Lface)
            {
                /* We are joining two loops into one -- remove the left face */
                joiningLoops = true;
                KillFace(eDel.Lface, eDel.Sym.Lface);
            }

            if (eDel.Onext == eDel)
            {
                KillVertex(eDel.Org, null);
            }
            else
            {
                /* Make sure that eDel.Org and eDel.Sym.Lface point to valid half-edges */
                eDel.Sym.Lface.anEdge = eDel.Sym.Lnext;
                eDel.Org.anEdge = eDel.Onext;

                Splice(eDel, eDel.Sym.Lnext);
                if (!joiningLoops)
                {
                    Mogre.Utils.GluTesselator.GLUface newFace = new Mogre.Utils.GluTesselator.GLUface();

                    /* We are splitting one loop into two -- create a new loop for eDel. */
                    MakeFace(newFace, eDel, eDel.Lface);
                }
            }

            /* Claim: the mesh is now in a consistent state, except that eDel.Org
            * may have been deleted.  Now we disconnect eDel.Dst.
            */
            if (eDelSym.Onext == eDelSym)
            {
                KillVertex(eDelSym.Org, null);
                KillFace(eDelSym.Lface, null);
            }
            else
            {
                /* Make sure that eDel.Dst and eDel.Lface point to valid half-edges */
                eDel.Lface.anEdge = eDelSym.Sym.Lnext;
                eDelSym.Org.anEdge = eDelSym.Onext;
                Splice(eDelSym, eDelSym.Sym.Lnext);
            }

            /* Any isolated vertices or faces have already been freed. */
            KillEdge(eDel);

            return true;
        }
Example #17
0
 private static GLUface AddToTrail(Mogre.Utils.GluTesselator.GLUface f, Mogre.Utils.GluTesselator.GLUface t)
 {
     f.trail  = t;
     f.marked = true;
     return(f);
 }
Example #18
0
        internal static FaceCount MaximumStrip(Mogre.Utils.GluTesselator.GLUhalfEdge eOrig)
        {
            /* Here we are looking for a maximal strip that contains the vertices
             * eOrig.Org, eOrig.Dst, eOrig.Lnext.Dst (in that order or the
             * reverse, such that all triangles are oriented CCW).
             *
             * Again we walk forward and backward as far as possible.  However for
             * strips there is a twist: to get CCW orientations, there must be
             * an *even* number of triangles in the strip on one side of eOrig.
             * We walk the strip starting on a side with an even number of triangles;
             * if both side have an odd number, we are forced to shorten one side.
             */
            FaceCount newFace = new FaceCount(0, null, renderStrip);
            long      headSize = 0, tailSize = 0;

            Mogre.Utils.GluTesselator.GLUface     trail = null;
            Mogre.Utils.GluTesselator.GLUhalfEdge e, eTail, eHead;

            for (e = eOrig; !Marked(e.Lface); ++tailSize, e = e.Onext)
            {
                trail = AddToTrail(e.Lface, trail);
                ++tailSize;
                e = e.Lnext.Sym;
                if (Marked(e.Lface))
                {
                    break;
                }
                trail = AddToTrail(e.Lface, trail);
            }
            eTail = e;

            for (e = eOrig; !Marked(e.Sym.Lface); ++headSize, e = e.Sym.Onext.Sym)
            {
                trail = AddToTrail(e.Sym.Lface, trail);
                ++headSize;
                e = e.Sym.Lnext;
                if (Marked(e.Sym.Lface))
                {
                    break;
                }
                trail = AddToTrail(e.Sym.Lface, trail);
            }
            eHead = e;

            newFace.size = tailSize + headSize;
            if (IsEven(tailSize))
            {
                newFace.eStart = eTail.Sym;
            }
            else if (IsEven(headSize))
            {
                newFace.eStart = eHead;
            }
            else
            {
                /* Both sides have odd length, we must shorten one of them.  In fact,
                 * we must start from eHead to guarantee inclusion of eOrig.Lface.
                 */
                --newFace.size;
                newFace.eStart = eHead.Onext;
            }
            /*LINTED*/
            FreeTrail(trail);
            return(newFace);
        }
Example #19
0
 /* Macros which keep track of faces we have marked temporarily, and allow
  * us to backtrack when necessary.  With triangle fans, this is not
  * really necessary, since the only awkward case is a loop of triangles
  * around a single origin vertex.  However with strips the situation is
  * more complicated, and we need a general tracking method like the
  * one here.
  */
 private static bool Marked(Mogre.Utils.GluTesselator.GLUface f)
 {
     return(!f.inside || f.marked);
 }
Example #20
0
        /* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg.Sym.Org
        * to eDst.Org, and returns the corresponding half-edge eNew.
        * If eOrg.Lface == eDst.Lface, this splits one loop into two,
        * and the newly created loop is eNew.Lface.  Otherwise, two disjoint
        * loops are merged into one, and the loop eDst.Lface is destroyed.
        *
        * If (eOrg == eDst), the new face will have only two edges.
        * If (eOrg.Lnext == eDst), the old face is reduced to a single edge.
        * If (eOrg.Lnext.Lnext == eDst), the old face is reduced to two edges.
        */
        internal static Mogre.Utils.GluTesselator.GLUhalfEdge __gl_meshConnect(Mogre.Utils.GluTesselator.GLUhalfEdge eOrg, Mogre.Utils.GluTesselator.GLUhalfEdge eDst)
        {
            Mogre.Utils.GluTesselator.GLUhalfEdge eNewSym;
            bool joiningLoops = false;
            Mogre.Utils.GluTesselator.GLUhalfEdge eNew = MakeEdge(eOrg);

            eNewSym = eNew.Sym;

            if (eDst.Lface != eOrg.Lface)
            {
                /* We are connecting two disjoint loops -- destroy eDst.Lface */
                joiningLoops = true;
                KillFace(eDst.Lface, eOrg.Lface);
            }

            /* Connect the new edge appropriately */
            Splice(eNew, eOrg.Lnext);
            Splice(eNewSym, eDst);

            /* Set the vertex and face information */
            eNew.Org = eOrg.Sym.Org;
            eNewSym.Org = eDst.Org;
            eNew.Lface = eNewSym.Lface = eOrg.Lface;

            /* Make sure the old face points to a valid half-edge */
            eOrg.Lface.anEdge = eNewSym;

            if (!joiningLoops)
            {
                Mogre.Utils.GluTesselator.GLUface newFace = new Mogre.Utils.GluTesselator.GLUface();

                /* We split one loop into two -- the new loop is eNew.Lface */
                MakeFace(newFace, eNew, eOrg.Lface);
            }
            return eNew;
        }
Example #21
0
        /* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
        * mesh connectivity and topology.  It changes the mesh so that
        *	eOrg->Onext <- OLD( eDst->Onext )
        *	eDst->Onext <- OLD( eOrg->Onext )
        * where OLD(...) means the value before the meshSplice operation.
        *
        * This can have two effects on the vertex structure:
        *  - if eOrg->Org != eDst->Org, the two vertices are merged together
        *  - if eOrg->Org == eDst->Org, the origin is split into two vertices
        * In both cases, eDst->Org is changed and eOrg->Org is untouched.
        *
        * Similarly (and independently) for the face structure,
        *  - if eOrg->Lface == eDst->Lface, one loop is split into two
        *  - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
        * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
        *
        * Some special cases:
        * If eDst == eOrg, the operation has no effect.
        * If eDst == eOrg->Lnext, the new face will have a single edge.
        * If eDst == eOrg->Lprev, the old face will have a single edge.
        * If eDst == eOrg->Onext, the new vertex will have a single edge.
        * If eDst == eOrg->Oprev, the old vertex will have a single edge.
        */
        public static bool __gl_meshSplice(Mogre.Utils.GluTesselator.GLUhalfEdge eOrg, Mogre.Utils.GluTesselator.GLUhalfEdge eDst)
        {
            bool joiningLoops = false;
            bool joiningVertices = false;

            if (eOrg == eDst)
                return true;

            if (eDst.Org != eOrg.Org)
            {
                /* We are merging two disjoint vertices -- destroy eDst->Org */
                joiningVertices = true;
                KillVertex(eDst.Org, eOrg.Org);
            }
            if (eDst.Lface != eOrg.Lface)
            {
                /* We are connecting two disjoint loops -- destroy eDst.Lface */
                joiningLoops = true;
                KillFace(eDst.Lface, eOrg.Lface);
            }

            /* Change the edge structure */
            Splice(eDst, eOrg);

            if (!joiningVertices)
            {
                Mogre.Utils.GluTesselator.GLUvertex newVertex = new Mogre.Utils.GluTesselator.GLUvertex();

                /* We split one vertex into two -- the new vertex is eDst.Org.
                * Make sure the old vertex points to a valid half-edge.
                */
                MakeVertex(newVertex, eDst, eOrg.Org);
                eOrg.Org.anEdge = eOrg;
            }
            if (!joiningLoops)
            {
                Mogre.Utils.GluTesselator.GLUface newFace = new Mogre.Utils.GluTesselator.GLUface();

                /* We split one loop into two -- the new loop is eDst.Lface.
                * Make sure the old face points to a valid half-edge.
                */
                MakeFace(newFace, eDst, eOrg.Lface);
                eOrg.Lface.anEdge = eOrg;
            }

            return true;
        }
Example #22
0
        /// <summary>*************** Basic Edge Operations *********************</summary>
        /* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face).
        * The loop consists of the two new half-edges.
        */
        public static Mogre.Utils.GluTesselator.GLUhalfEdge __gl_meshMakeEdge(Mogre.Utils.GluTesselator.GLUmesh mesh)
        {
            Mogre.Utils.GluTesselator.GLUvertex newVertex1 = new Mogre.Utils.GluTesselator.GLUvertex();
            Mogre.Utils.GluTesselator.GLUvertex newVertex2 = new Mogre.Utils.GluTesselator.GLUvertex();
            Mogre.Utils.GluTesselator.GLUface newFace = new Mogre.Utils.GluTesselator.GLUface();
            Mogre.Utils.GluTesselator.GLUhalfEdge e;

            e = MakeEdge(mesh.eHead);
            if (e == null)
                return null;

            MakeVertex(newVertex1, e, mesh.vHead);
            MakeVertex(newVertex2, e.Sym, mesh.vHead);
            MakeFace(newFace, e, mesh.fHead);
            return e;
        }