From 7eec6b36a57d12e1455bebbaa592db0e6ee31d01 Mon Sep 17 00:00:00 2001 From: terminx Date: Wed, 21 Oct 2015 19:54:14 +0000 Subject: [PATCH] Sprite sorting changes: -Sort by owner now occurs only when two sprites have matching x/y coordinates. -Cstat 1024 now activates a special drawing mode that indicates a sprite should be drawn without depth after all other sprites have been drawn. The previous cstat 1024 functionality, an internal hack for shadows cast by models in Polymost, has been moved to bit 1 of a new graphical effects bitfield stored in a tsprite's .extra member. git-svn-id: https://svn.eduke32.com/eduke32@5400 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/build/include/build.h | 2 +- polymer/eduke32/build/src/engine.c | 355 ++++++++++++++------------ polymer/eduke32/build/src/mdsprite.c | 6 +- polymer/eduke32/build/src/polymer.c | 8 +- polymer/eduke32/build/src/voxmodel.c | 4 +- polymer/eduke32/source/game.c | 10 +- 6 files changed, 205 insertions(+), 180 deletions(-) diff --git a/polymer/eduke32/build/include/build.h b/polymer/eduke32/build/include/build.h index 8059b749b..73ec6cf21 100644 --- a/polymer/eduke32/build/include/build.h +++ b/polymer/eduke32/build/include/build.h @@ -551,7 +551,7 @@ typedef struct { #define SPREXT_TSPRACCESS 16 #define SPREXT_TEMPINVISIBLE 32 -#define CSTAT_SPRITE_MDHACK 1024 +#define TSPR_EXTRA_MDHACK 1 EXTERN int32_t guniqhudid; EXTERN int32_t spritesortcnt; diff --git a/polymer/eduke32/build/src/engine.c b/polymer/eduke32/build/src/engine.c index 291dd2c98..2ab4fe36e 100644 --- a/polymer/eduke32/build/src/engine.c +++ b/polymer/eduke32/build/src/engine.c @@ -944,7 +944,7 @@ static void yax_copytsprites() Bmemcpy(&tsprite[spritesortcnt], spr, sizeof(spritetype)); tsprite[spritesortcnt].owner = spritenum; - + tsprite[spritesortcnt].extra = 0; tsprite[spritesortcnt].sectnum = sectnum; // potentially tweak sectnum! spritesortcnt++; } @@ -2475,6 +2475,7 @@ int32_t engine_addtsprite(int16_t z, int16_t sectnum) return 1; Bmemcpy(&tsprite[spritesortcnt], spr, sizeof(spritetype)); + tsprite[spritesortcnt].extra = 0; tsprite[spritesortcnt++].owner = z; #ifdef YAX_ENABLE @@ -9764,74 +9765,74 @@ killsprite: spritesxyz[i].y = yp; } - { - int32_t gap, ys; + int32_t gap, ys; - gap = 1; while (gap < spritesortcnt) gap = (gap<<1)+1; - for (gap>>=1; gap>0; gap>>=1) //Sort sprite list - for (i=0; i=0; l-=gap) - { - if (spritesxyz[l].y <= spritesxyz[l+gap].y) break; - swapptr(&tspriteptr[l],&tspriteptr[l+gap]); - swaplong(&spritesxyz[l].x,&spritesxyz[l+gap].x); - swaplong(&spritesxyz[l].y,&spritesxyz[l+gap].y); - } - - if (spritesortcnt > 0) - spritesxyz[spritesortcnt].y = (spritesxyz[spritesortcnt-1].y^1); - - ys = spritesxyz[0].y; i = 0; - for (int32_t j=1; j<=spritesortcnt; j++) - { - if (spritesxyz[j].y == ys) - continue; - - ys = spritesxyz[j].y; - - if (j > i+1) + gap = 1; while (gap < spritesortcnt) gap = (gap<<1)+1; + for (gap>>=1; gap>0; gap>>=1) //Sort sprite list + for (i=0; i=0; l-=gap) { - for (int32_t k=i; kz; - if ((s->cstat&48) != 32) - { - int32_t yoff = picanm[s->picnum].yofs + s->yoffset; - int32_t yspan = (tilesiz[s->picnum].y*s->yrepeat<<2); - - spritesxyz[k].z -= (yoff*s->yrepeat)<<2; - - if (!(s->cstat&128)) - spritesxyz[k].z -= (yspan>>1); - if (klabs(spritesxyz[k].z-globalposz) < (yspan>>1)) - spritesxyz[k].z = globalposz; - } - } - - for (int32_t k=i+1; kowner < tspriteptr[l]->owner) - { - swapptr(&tspriteptr[k], &tspriteptr[l]); - vec3_t tv3 = spritesxyz[k]; - spritesxyz[k] = spritesxyz[l]; - spritesxyz[l] = tv3; - } + if (spritesxyz[l].y <= spritesxyz[l+gap].y) break; + swapptr(&tspriteptr[l],&tspriteptr[l+gap]); + swaplong(&spritesxyz[l].x,&spritesxyz[l+gap].x); + swaplong(&spritesxyz[l].y,&spritesxyz[l+gap].y); } - i = j; + + if (spritesortcnt > 0) + spritesxyz[spritesortcnt].y = (spritesxyz[spritesortcnt-1].y^1); + + ys = spritesxyz[0].y; i = 0; + for (int32_t j=1; j<=spritesortcnt; j++) + { + if (spritesxyz[j].y == ys) + continue; + + ys = spritesxyz[j].y; + + if (j > i+1) + { + for (int32_t k=i; kz; + if ((s->cstat&48) != 32) + { + int32_t yoff = picanm[s->picnum].yofs + s->yoffset; + int32_t yspan = (tilesiz[s->picnum].y*s->yrepeat<<2); + + spritesxyz[k].z -= (yoff*s->yrepeat)<<2; + + if (!(s->cstat&128)) + spritesxyz[k].z -= (yspan>>1); + if (klabs(spritesxyz[k].z-globalposz) < (yspan>>1)) + spritesxyz[k].z = globalposz; + } + } + + for (int32_t k=i+1; kx == tspriteptr[l]->x && + tspriteptr[k]->y == tspriteptr[l]->y && + tspriteptr[k]->owner < tspriteptr[l]->owner) + { + swapptr(&tspriteptr[k], &tspriteptr[l]); + vec3_t tv3 = spritesxyz[k]; + spritesxyz[k] = spritesxyz[l]; + spritesxyz[l] = tv3; + } } + i = j; } begindrawing(); //{{{ @@ -9856,135 +9857,157 @@ killsprite: } } #endif + + vec2f_t pos; + + pos.x = fglobalposx; + pos.y = fglobalposy; + + // CAUTION: maskwallcnt and spritesortcnt may be zero! + // Writing e.g. "while (maskwallcnt--)" is wrong! + while (maskwallcnt) { - vec2f_t pos; + vec2f_t dot, dot2, middle; + // PLAG: sorting stuff + _equation maskeq, p1eq, p2eq; - pos.x = fglobalposx; - pos.y = fglobalposy; + const int32_t w = (getrendermode()==REND_POLYMER) ? + maskwall[maskwallcnt-1] : thewall[maskwall[maskwallcnt-1]]; - // CAUTION: maskwallcnt and spritesortcnt may be zero! - // Writing e.g. "while (maskwallcnt--)" is wrong! - while (maskwallcnt) + maskwallcnt--; + + dot.x = (float)wall[w].x; + dot.y = (float)wall[w].y; + dot2.x = (float)wall[wall[w].point2].x; + dot2.y = (float)wall[wall[w].point2].y; + + maskeq = equation(dot.x, dot.y, dot2.x, dot2.y); + + p1eq = equation(pos.x, pos.y, dot.x, dot.y); + p2eq = equation(pos.x, pos.y, dot2.x, dot2.y); + + middle.x = (dot.x + dot2.x) * .5f; + middle.y = (dot.y + dot2.y) * .5f; + + i = spritesortcnt; + while (i) { - vec2f_t dot, dot2, middle; - // PLAG: sorting stuff - _equation maskeq, p1eq, p2eq; - - const int32_t w = (getrendermode()==REND_POLYMER) ? - maskwall[maskwallcnt-1] : thewall[maskwall[maskwallcnt-1]]; - - maskwallcnt--; - - dot.x = (float)wall[w].x; - dot.y = (float)wall[w].y; - dot2.x = (float)wall[wall[w].point2].x; - dot2.y = (float)wall[wall[w].point2].y; - - maskeq = equation(dot.x, dot.y, dot2.x, dot2.y); - - p1eq = equation(pos.x, pos.y, dot.x, dot.y); - p2eq = equation(pos.x, pos.y, dot2.x, dot2.y); - - middle.x = (dot.x + dot2.x) * .5f; - middle.y = (dot.y + dot2.y) * .5f; - - i = spritesortcnt; - while (i) + i--; + if (tspriteptr[i] != NULL && (tspriteptr[i]->cstat & 1024) != 1024) { - i--; - if (tspriteptr[i] != NULL) + vec2f_t spr; + const tspritetype *tspr = tspriteptr[i]; + + spr.x = (float)tspr->x; + spr.y = (float)tspr->y; + + if (!sameside(&maskeq, &spr, &pos)) { - vec2f_t spr; - const tspritetype *tspr = tspriteptr[i]; + // Sprite and camera are on different sides of the + // masked wall. - spr.x = (float)tspr->x; - spr.y = (float)tspr->y; + // Check if the sprite is inside the 'cone' given by + // the rays from the camera to the two wall-points. + const int32_t inleft = sameside(&p1eq, &middle, &spr); + const int32_t inright = sameside(&p2eq, &middle, &spr); - if (!sameside(&maskeq, &spr, &pos)) + int32_t ok = (inleft && inright); + + if (!ok) { - // Sprite and camera are on different sides of the - // masked wall. + // If not, check if any of the border points are... + int32_t xx[4] = { tspr->x }; + int32_t yy[4] = { tspr->y }; + int32_t numpts, jj; - // Check if the sprite is inside the 'cone' given by - // the rays from the camera to the two wall-points. - const int32_t inleft = sameside(&p1eq, &middle, &spr); - const int32_t inright = sameside(&p2eq, &middle, &spr); + const _equation pineq = inleft ? p1eq : p2eq; - int32_t ok = (inleft && inright); - - if (!ok) + if ((tspr->cstat & 48) == 32) { - // If not, check if any of the border points are... - int32_t xx[4] = { tspr->x }; - int32_t yy[4] = { tspr->y }; - int32_t numpts, jj; + numpts = 4; + get_floorspr_points(tspr, 0, 0, + &xx[0], &xx[1], &xx[2], &xx[3], + &yy[0], &yy[1], &yy[2], &yy[3]); + } + else + { + const int32_t oang = tspr->ang; + numpts = 2; - const _equation pineq = inleft ? p1eq : p2eq; + // Consider face sprites as wall sprites with camera ang. + // XXX: factor 4/5 needed? + if ((tspr->cstat & 48) != 16) + tspriteptr[i]->ang = globalang; - if ((tspr->cstat & 48) == 32) - { - numpts = 4; - get_floorspr_points(tspr, 0, 0, - &xx[0], &xx[1], &xx[2], &xx[3], - &yy[0], &yy[1], &yy[2], &yy[3]); - } - else - { - const int32_t oang = tspr->ang; - numpts = 2; + get_wallspr_points((const spritetype *)tspr, &xx[0], &xx[1], &yy[0], &yy[1]); - // Consider face sprites as wall sprites with camera ang. - // XXX: factor 4/5 needed? - if ((tspr->cstat & 48) != 16) - tspriteptr[i]->ang = globalang; - - get_wallspr_points((const spritetype *)tspr, &xx[0], &xx[1], &yy[0], &yy[1]); - - if ((tspr->cstat & 48) == 0) - tspriteptr[i]->ang = oang; - } - - for (jj=0; jjcstat & 48) == 0) + tspriteptr[i]->ang = oang; } - if (ok) + for (jj=0; jjowner); - drawsprite(i); - tspriteptr[i] = NULL; + spr.x = (float)xx[jj]; + spr.y = (float)yy[jj]; + + if (!sameside(&maskeq, &spr, &pos)) // behind the maskwall, + if ((sameside(&p1eq, &middle, &spr) && // inside the 'cone', + sameside(&p2eq, &middle, &spr)) + || !sameside(&pineq, &middle, &spr)) // or on the other outside. + { + ok = 1; + break; + } } } + + if (ok) + { + debugmask_add(i | 32768, tspr->owner); + drawsprite(i); + tspriteptr[i] = NULL; + } } } - - debugmask_add(maskwall[maskwallcnt], thewall[maskwall[maskwallcnt]]); - drawmaskwall(maskwallcnt); } - while (spritesortcnt) + debugmask_add(maskwall[maskwallcnt], thewall[maskwall[maskwallcnt]]); + drawmaskwall(maskwallcnt); + } + + i = spritesortcnt; + + while (i) + { + i--; + if (tspriteptr[i] != NULL && (tspriteptr[i]->cstat & 1024) != 1024) { - spritesortcnt--; - if (tspriteptr[spritesortcnt] != NULL) - { - debugmask_add(spritesortcnt | 32768, tspriteptr[spritesortcnt]->owner); - drawsprite(spritesortcnt); - } + debugmask_add(i | 32768, tspriteptr[i]->owner); + drawsprite(i); + tspriteptr[i] = NULL; } } +#ifdef USE_OPENGL + if (getrendermode() >= REND_POLYMOST) + bglDepthMask(GL_FALSE); +#endif + + while (spritesortcnt) + { + spritesortcnt--; + if (tspriteptr[spritesortcnt] != NULL && (tspriteptr[spritesortcnt]->cstat & 1024)) + { + drawsprite(spritesortcnt); + tspriteptr[spritesortcnt] = NULL; + } + } + +#ifdef USE_OPENGL + if (getrendermode() >= REND_POLYMOST) + bglDepthMask(GL_TRUE); +#endif + #ifdef POLYMER if (getrendermode() == REND_POLYMER) polymer_drawmasks(); diff --git a/polymer/eduke32/build/src/mdsprite.c b/polymer/eduke32/build/src/mdsprite.c index 526929f09..dddef4e43 100644 --- a/polymer/eduke32/build/src/mdsprite.c +++ b/polymer/eduke32/build/src/mdsprite.c @@ -2138,7 +2138,7 @@ static int32_t polymost_md3draw(md3model_t *m, const tspritetype *tspr) // flat-tsprite-on-floor shadows. // is this still needed? - if (tspr->cstat&CSTAT_SPRITE_MDHACK) + if (tspr->extra&TSPR_EXTRA_MDHACK) { #ifdef __arm__ // GL ES has a glDepthRangef and the loss of precision is OK there float f = (float) (tspr->owner + 1) * (FLT_EPSILON * 8.0); @@ -2209,7 +2209,7 @@ static int32_t polymost_md3draw(md3model_t *m, const tspritetype *tspr) if (sext->offset.y) // Compare with SCREEN_FACTORS above a0.y = (float) sext->offset.y * f; - if ((sext->offset.z) && !(tspr->cstat&CSTAT_SPRITE_MDHACK)) // Compare with SCREEN_FACTORS above + if ((sext->offset.z) && !(tspr->extra&TSPR_EXTRA_MDHACK)) // Compare with SCREEN_FACTORS above a0.z = (float)sext->offset.z / (655360.f * (m0.z+m1.z) * (gxyaspect*fxdimen*(1.f/1280.f))); k0 = (float)sintable[(sext->pitch+512)&2047] * (1.f/16384.f); @@ -2303,7 +2303,7 @@ static int32_t polymost_md3draw(md3model_t *m, const tspritetype *tspr) //i = mdloadskin((md2model *)m,tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum,surfi); //hack for testing multiple surfaces per MD3 bglBindTexture(GL_TEXTURE_2D, i); - if (!(tspr->cstat&CSTAT_SPRITE_MDHACK)) + if (!(tspr->extra&TSPR_EXTRA_MDHACK)) { #ifndef EDUKE32_GLES i = r_detailmapping ? mdloadskin((md2model_t *) m, tile2model[Ptile2tile(tspr->picnum, lpal)].skinnum, DETAILPAL, surfi) : 0; diff --git a/polymer/eduke32/build/src/polymer.c b/polymer/eduke32/build/src/polymer.c index 27b4a9b9f..7e65f59cd 100644 --- a/polymer/eduke32/build/src/polymer.c +++ b/polymer/eduke32/build/src/polymer.c @@ -4659,7 +4659,7 @@ static void polymer_drawmdsprite(tspritetype *tspr) if (!mdspritematerial.diffusemap) continue; - if (!(tspr->cstat&CSTAT_SPRITE_MDHACK)) + if (!(tspr->extra&TSPR_EXTRA_MDHACK)) { mdspritematerial.detailmap = mdloadskin((md2model_t *)m,tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum,DETAILPAL,surfi); @@ -4671,13 +4671,13 @@ static void polymer_drawmdsprite(tspritetype *tspr) mdspritematerial.detailscale[0] = mdspritematerial.detailscale[1] = sk->param; } - if (!(tspr->cstat&CSTAT_SPRITE_MDHACK)) + if (!(tspr->extra&TSPR_EXTRA_MDHACK)) { mdspritematerial.specmap = mdloadskin((md2model_t *)m,tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum,SPECULARPAL,surfi); } - if (!(tspr->cstat&CSTAT_SPRITE_MDHACK)) + if (!(tspr->extra&TSPR_EXTRA_MDHACK)) { mdspritematerial.normalmap = mdloadskin((md2model_t *)m,tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum,NORMALPAL,surfi); @@ -4691,7 +4691,7 @@ static void polymer_drawmdsprite(tspritetype *tspr) } } - if (!(tspr->cstat&CSTAT_SPRITE_MDHACK)) + if (!(tspr->extra&TSPR_EXTRA_MDHACK)) { mdspritematerial.glowmap = mdloadskin((md2model_t *)m,tile2model[Ptile2tile(tspr->picnum,lpal)].skinnum,GLOWPAL,surfi); diff --git a/polymer/eduke32/build/src/voxmodel.c b/polymer/eduke32/build/src/voxmodel.c index d02f7c9b0..4459a92ee 100644 --- a/polymer/eduke32/build/src/voxmodel.c +++ b/polymer/eduke32/build/src/voxmodel.c @@ -951,7 +951,7 @@ int32_t polymost_voxdraw(voxmodel_t *m, const tspritetype *tspr) mat[12] = -mat[12]; } - if (tspr->cstat&CSTAT_SPRITE_MDHACK) + if (tspr->extra&TSPR_EXTRA_MDHACK) { bglDepthFunc(GL_LESS); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS // bglDepthRange(0.0, 0.9999); @@ -1055,7 +1055,7 @@ int32_t polymost_voxdraw(voxmodel_t *m, const tspritetype *tspr) //------------ bglDisable(GL_CULL_FACE); // bglPopAttrib(); - if (tspr->cstat&CSTAT_SPRITE_MDHACK) + if (tspr->extra&TSPR_EXTRA_MDHACK) { bglDepthFunc(GL_LESS); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS // bglDepthRange(0.0, 0.99999); diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c index 229a40525..8752e8b9c 100644 --- a/polymer/eduke32/source/game.c +++ b/polymer/eduke32/source/game.c @@ -4181,6 +4181,7 @@ static void G_OROR_DupeSprites(const spritetype *sp) tsprite[spritesortcnt].z = tsprite[spritesortcnt].z - sp->z + actor[sp->yvel].ceilingz; tsprite[spritesortcnt].sectnum = refsp->sectnum; tsprite[spritesortcnt].owner = k; + tsprite[spritesortcnt].extra = 0; // OSD_Printf("duped sprite of pic %d at %d %d %d\n",tsprite[spritesortcnt].picnum,tsprite[spritesortcnt].x,tsprite[spritesortcnt].y,tsprite[spritesortcnt].z); spritesortcnt++; @@ -7967,7 +7968,8 @@ skip: newt->yrepeat = 0; // 512:trans reverse //1024:tell MD2SPRITE.C to use Z-buffer hacks to hide overdraw issues - newt->cstat |= (512+CSTAT_SPRITE_MDHACK); + newt->extra |= TSPR_EXTRA_MDHACK; + newt->cstat |= 512; } else { @@ -8010,7 +8012,7 @@ skip: //g_restorePalette = 1; // JBF 20040101: why? } t->shade = -127; - t->cstat |= 8192; + t->cstat |= 8192+1024; break; case FIRE__STATIC: case FIRE2__STATIC: @@ -8021,11 +8023,11 @@ skip: t->z = actor[t->owner].floorz; t->shade = -127; case SMALLSMOKE__STATIC: - t->cstat |= 8192; + t->cstat |= 8192+1024; break; case COOLEXPLOSION1__STATIC: t->shade = -127; - t->cstat |= 8192; + t->cstat |= 8192+1024; t->picnum += (s->shade>>1); break; case PLAYERONWATER__STATIC: