From 8250e5f3e83ba225c6c9d238781bb4503cc1fa5f Mon Sep 17 00:00:00 2001 From: plagman Date: Sat, 20 Aug 2011 21:05:38 +0000 Subject: [PATCH] Polymer: add preliminary support for sector masks. When walking the sectors in displayrooms, detect floor/sector masks to place them in a mask queue. The queues are allocated on the heap, but a stack pointer is maintained by the displayrooms to allow it to play nice with mirror recursion. Right now the masks are drawn after all of drawmasks is finished; that means you can see sprites and wall masks through sector masks, but not the opposite. There is a slight attempt at blending far to near, but nothing too conclusive yet; that means that in some cases some sector masks won't be visible through other sector masks, but it should work for trivial cases. The next step would be to copy all the drawmasks logic into Polymer and have it (attempt to) properly interleave sector masks where they belong in the blending order. git-svn-id: https://svn.eduke32.com/eduke32@1980 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/build/include/polymer.h | 2 +- polymer/eduke32/build/src/engine.c | 14 ++-- polymer/eduke32/build/src/polymer.c | 90 ++++++++++++++++++++++--- 3 files changed, 86 insertions(+), 20 deletions(-) diff --git a/polymer/eduke32/build/include/polymer.h b/polymer/eduke32/build/include/polymer.h index 3f17a89ce..ffeb0f433 100644 --- a/polymer/eduke32/build/include/polymer.h +++ b/polymer/eduke32/build/include/polymer.h @@ -323,7 +323,7 @@ void PR_CALLBACK polymer_tesserror(GLenum error); void PR_CALLBACK polymer_tessedgeflag(GLenum error); void PR_CALLBACK polymer_tessvertex(void* vertex, void* sector); static int32_t polymer_buildfloor(int16_t sectnum); -static void polymer_drawsector(int16_t sectnum); +static void polymer_drawsector(int16_t sectnum, int32_t domasks); // WALLS static int32_t polymer_initwall(int16_t wallnum); static void polymer_updatewall(int16_t wallnum); diff --git a/polymer/eduke32/build/src/engine.c b/polymer/eduke32/build/src/engine.c index c24c0fcbb..561658957 100644 --- a/polymer/eduke32/build/src/engine.c +++ b/polymer/eduke32/build/src/engine.c @@ -8133,14 +8133,6 @@ void drawmasks(void) _equation maskeq, p1eq, p2eq; _point2d dot, dot2, middle, pos, spr; -#ifdef POLYMER - if ((rendmode == 4) && 0) - { - polymer_drawmasks(); - return; - } -#endif - for (i=spritesortcnt-1; i>=0; i--) tspriteptr[i] = &tsprite[i]; for (i=spritesortcnt-1; i>=0; i--) { @@ -8314,6 +8306,12 @@ killsprite: #endif } +#ifdef POLYMER + if (rendmode == 4) { + polymer_drawmasks(); + } +#endif + indrawroomsandmasks = 0; enddrawing(); //}}} } diff --git a/polymer/eduke32/build/src/polymer.c b/polymer/eduke32/build/src/polymer.c index 8ef78efbf..3614a2335 100644 --- a/polymer/eduke32/build/src/polymer.c +++ b/polymer/eduke32/build/src/polymer.c @@ -610,6 +610,9 @@ static int16_t querydelay[MAXSECTORS]; static GLuint queryid[MAXWALLS]; static int16_t drawingstate[MAXSECTORS]; +int16_t *cursectormasks; +int16_t *cursectormaskcount; + float horizang; int16_t viewangle; @@ -1020,7 +1023,7 @@ void polymer_drawrooms(int32_t daposx, int32_t daposy, int32_t da while (i >= 0) { polymer_updatesector(i); - polymer_drawsector(i); + polymer_drawsector(i, FALSE); polymer_scansprites(i, tsprite, &spritesortcnt); i--; } @@ -1064,15 +1067,30 @@ void polymer_drawmasks(void) { bglEnable(GL_ALPHA_TEST); bglEnable(GL_BLEND); - bglEnable(GL_POLYGON_OFFSET_FILL); +// bglEnable(GL_POLYGON_OFFSET_FILL); - while (--spritesortcnt) - { - tspriteptr[spritesortcnt] = &tsprite[spritesortcnt]; - polymer_drawsprite(spritesortcnt); +// while (--spritesortcnt) +// { +// tspriteptr[spritesortcnt] = &tsprite[spritesortcnt]; +// polymer_drawsprite(spritesortcnt); +// } + + // We (kind of) queue sector masks near to far, so drawing them in reverse + // order is the sane approach here. Of course impossible cases will arise. + while (*cursectormaskcount) { + polymer_drawsector(cursectormasks[--(*cursectormaskcount)], TRUE); } - bglDisable(GL_POLYGON_OFFSET_FILL); + // This should _always_ be called after a corresponding pr_displayrooms(). + // Both the top-level game drawrooms and the recursive internal passes + // should be accounted for here. If these free cause corruption, there's + // an accounting bug somewhere. + Bfree(cursectormaskcount); + cursectormaskcount = NULL; + Bfree(cursectormasks); + cursectormasks = NULL; + +// bglDisable(GL_POLYGON_OFFSET_FILL); bglDisable(GL_BLEND); bglDisable(GL_ALPHA_TEST); } @@ -1492,6 +1510,8 @@ static void polymer_displayrooms(int16_t dacursectnum) int16_t localmaskwallcnt; _prmirror mirrorlist[10]; int mirrorcount; + int16_t *localsectormasks; + int16_t *localsectormaskcount; int32_t gx, gy, gz, px, py, pz; GLdouble plane[4]; float coeff; @@ -1515,6 +1535,11 @@ static void polymer_displayrooms(int16_t dacursectnum) mirrorcount = 0; + localsectormasks = Bmalloc(sizeof(int16_t) * numsectors); + localsectormaskcount = Bcalloc(sizeof(int16_t), 1); + cursectormasks = localsectormasks; + cursectormaskcount = localsectormaskcount; + bglDisable(GL_DEPTH_TEST); bglColor4f(1.0f, 1.0f, 1.0f, 1.0f); polymer_drawsky(cursky, curskypal, curskyshade); @@ -1528,7 +1553,7 @@ static void polymer_displayrooms(int16_t dacursectnum) sec = §or[sectorqueue[front]]; polymer_pokesector(sectorqueue[front]); - polymer_drawsector(sectorqueue[front]); + polymer_drawsector(sectorqueue[front], FALSE); polymer_scansprites(sectorqueue[front], localtsprite, &localspritesortcnt); doquery = 0; @@ -1788,6 +1813,9 @@ static void polymer_displayrooms(int16_t dacursectnum) polymer_displayrooms(mirrorlist[i].sectnum); depth--; + cursectormasks = localsectormasks; + cursectormaskcount = localsectormaskcount; + globalposx = gx; globalposy = gy; globalposz = gz; @@ -2452,18 +2480,38 @@ static int32_t polymer_buildfloor(int16_t sectnum) return (1); } -static void polymer_drawsector(int16_t sectnum) +static void polymer_drawsector(int16_t sectnum, int32_t domasks) { sectortype *sec; _prsector* s; GLubyte oldcolor[4]; + int32_t draw; + int32_t queuedmask; if (pr_verbosity >= 3) OSD_Printf("PR : Drawing sector %i...\n", sectnum); sec = §or[sectnum]; s = prsectors[sectnum]; - if (!(sec->floorstat & 1025) || (searchit == 2)) { + queuedmask = FALSE; + + // If you're thinking of 'optimizing' the following logic, you'd better + // provide compelling evidence that the generated code is more efficient + // than what GCC can come up with on its own. + + draw = TRUE; + // Draw masks regardless; avoid all non-masks TROR links + if (sec->floorstat & 384) { + draw = domasks; + } else if (sec->floorstat & 1024) { + draw = FALSE; + } + // Parallaxed + if (sec->floorstat & 1) { + draw = FALSE; + } + + if (draw || (searchit == 2)) { if (searchit == 2) { memcpy(oldcolor, s->floor.material.diffusemodulation, sizeof(GLubyte) * 4); @@ -2481,9 +2529,26 @@ static void polymer_drawsector(int16_t sectnum) if (searchit == 2) memcpy(s->floor.material.diffusemodulation, oldcolor, sizeof(GLubyte) * 4); + } else if (!domasks && sec->floorstat & 384) { + // If we just skipped a mask, queue it for later + cursectormasks[(*cursectormaskcount)++] = sectnum; + // Don't queue it twice if the ceiling is also a mask, though. + queuedmask = TRUE; } - if (!(sec->ceilingstat & 1025) || (searchit == 2)) { + draw = TRUE; + // Draw masks regardless; avoid all non-masks TROR links + if (sec->ceilingstat & 384) { + draw = domasks; + } else if (sec->ceilingstat & 1024) { + draw = FALSE; + } + // Parallaxed + if (sec->ceilingstat & 1) { + draw = FALSE; + } + + if (draw || (searchit == 2)) { if (searchit == 2) { memcpy(oldcolor, s->ceil.material.diffusemodulation, sizeof(GLubyte) * 4); @@ -2501,6 +2566,9 @@ static void polymer_drawsector(int16_t sectnum) if (searchit == 2) memcpy(s->ceil.material.diffusemodulation, oldcolor, sizeof(GLubyte) * 4); + } else if (!domasks && !queuedmask && (sec->ceilingstat & 384)) { + // If we just skipped a mask, queue it for later + cursectormasks[(*cursectormaskcount)++] = sectnum; } if (pr_verbosity >= 3) OSD_Printf("PR : Finished drawing sector %i...\n", sectnum);