/// <summary>********************* Strips and Fans decomposition *****************</summary> /* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle * fans, strips, and separate triangles. A substantial effort is made * to use as few rendering primitives as possible (ie. to make the fans * and strips as large as possible). * * The rendering output is provided as callbacks (see the api). */ public static void __gl_renderMesh(GLUtessellatorImpl tess, Mogre.Utils.GluTesselator.GLUmesh mesh) { Mogre.Utils.GluTesselator.GLUface f; /* Make a list of separate triangles so we can render them all at once */ tess.lonelyTriList = null; for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { f.marked = false; } for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { /* We examine all faces in an arbitrary order. Whenever we find * an unprocessed face F, we output a group of faces including F * whose size is maximum. */ if (f.inside && !f.marked) { RenderMaximumFaceGroup(tess, f); //assert(f.marked); } } if (tess.lonelyTriList != null) { RenderLonelyTriangles(tess, tess.lonelyTriList); tess.lonelyTriList = null; } }
/* __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); }
/* __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); }
/// <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); }
/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices, * and no loops (what we usually call a "face"). */ public static Mogre.Utils.GluTesselator.GLUmesh __gl_meshNewMesh() { Mogre.Utils.GluTesselator.GLUvertex v; Mogre.Utils.GluTesselator.GLUface f; Mogre.Utils.GluTesselator.GLUhalfEdge e; Mogre.Utils.GluTesselator.GLUhalfEdge eSym; Mogre.Utils.GluTesselator.GLUmesh mesh = new Mogre.Utils.GluTesselator.GLUmesh(); v = mesh.vHead; f = mesh.fHead; e = mesh.eHead; eSym = mesh.eHeadSym; v.next = v.prev = v; v.anEdge = null; v.data = null; f.next = f.prev = f; f.anEdge = null; f.data = 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; return(mesh); }
/// <summary>********************* Boundary contour decomposition *****************</summary> /* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one * contour for each face marked "inside". The rendering output is * provided as callbacks (see the api). */ public static void __gl_renderBoundary(GLUtessellatorImpl tess, Mogre.Utils.GluTesselator.GLUmesh mesh) { Mogre.Utils.GluTesselator.GLUface f; Mogre.Utils.GluTesselator.GLUhalfEdge e; for (f = mesh.fHead.next; f != mesh.fHead; f = f.next) { if (f.inside) { tess.callBeginOrBeginData(GL.GL_LINE_LOOP); e = f.anEdge; do { tess.callVertexOrVertexData(e.Org.data); e = e.Lnext; }while (e != f.anEdge); tess.callEndOrEndData(); } } }
/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh. */ public static void __gl_meshDeleteMesh(Mogre.Utils.GluTesselator.GLUmesh mesh) { Mogre.Utils.GluTesselator.GLUface f, fNext; Mogre.Utils.GluTesselator.GLUvertex v, vNext; Mogre.Utils.GluTesselator.GLUhalfEdge e, eNext; for (f = mesh.fHead.next; f != mesh.fHead; f = fNext) { fNext = f.next; } for (v = mesh.vHead.next; v != mesh.vHead; v = vNext) { vNext = v.next; } for (e = mesh.eHead.next; e != mesh.eHead; e = eNext) { /* One call frees both e and e.Sym (see EdgePair above) */ eNext = e.next; } }
/* __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); }
/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices, * and no loops (what we usually call a "face"). */ public static Mogre.Utils.GluTesselator.GLUmesh __gl_meshNewMesh() { Mogre.Utils.GluTesselator.GLUvertex v; Mogre.Utils.GluTesselator.GLUface f; Mogre.Utils.GluTesselator.GLUhalfEdge e; Mogre.Utils.GluTesselator.GLUhalfEdge eSym; Mogre.Utils.GluTesselator.GLUmesh mesh = new Mogre.Utils.GluTesselator.GLUmesh(); v = mesh.vHead; f = mesh.fHead; e = mesh.eHead; eSym = mesh.eHeadSym; v.next = v.prev = v; v.anEdge = null; v.data = null; f.next = f.prev = f; f.anEdge = null; f.data = 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; return mesh; }