Changes to sprite rendering:

- Added render flags (see r_defs.h)
- Implemented floor splats
- Drop shadow sprite rendering through render flags
This commit is contained in:
Jaime Passos 2020-10-12 00:13:22 -03:00
parent b808b3ef41
commit cc97e22e2f
33 changed files with 1489 additions and 1260 deletions

View File

@ -648,12 +648,15 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->eflags = (UINT16)SHORT(players[i].mo->eflags);
rsp->flags = LONG(players[i].mo->flags);
rsp->flags2 = LONG(players[i].mo->flags2);
rsp->renderflags = LONG(players[i].mo->renderflags);
rsp->radius = LONG(players[i].mo->radius);
rsp->height = LONG(players[i].mo->height);
rsp->scale = LONG(players[i].mo->scale);
rsp->destscale = LONG(players[i].mo->destscale);
rsp->scalespeed = LONG(players[i].mo->scalespeed);
rsp->spritexscale = LONG(players[i].mo->spritexscale);
rsp->spriteyscale = LONG(players[i].mo->spriteyscale);
}
static void resynch_read_player(resynch_pak *rsp)
@ -787,6 +790,7 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].mo->eflags = (UINT16)SHORT(rsp->eflags);
players[i].mo->flags = LONG(rsp->flags);
players[i].mo->flags2 = LONG(rsp->flags2);
players[i].mo->renderflags = LONG(rsp->renderflags);
players[i].mo->friction = LONG(rsp->friction);
players[i].mo->health = LONG(rsp->health);
players[i].mo->momx = LONG(rsp->momx);
@ -813,6 +817,8 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].mo->scale = LONG(rsp->scale);
players[i].mo->destscale = LONG(rsp->destscale);
players[i].mo->scalespeed = LONG(rsp->scalespeed);
players[i].mo->spritexscale = LONG(rsp->spritexscale);
players[i].mo->spriteyscale = LONG(rsp->spriteyscale);
// And finally, SET THE MOBJ SKIN damn it.
if ((players[i].powers[pw_carry] == CR_NIGHTSMODE) && (skins[players[i].skin].sprites[SPR2_NFLY].numframes == 0))

View File

@ -293,12 +293,15 @@ typedef struct
UINT32 flags;
UINT32 flags2;
UINT16 eflags;
UINT32 renderflags;
fixed_t radius;
fixed_t height;
fixed_t scale;
fixed_t destscale;
fixed_t scalespeed;
fixed_t spritexscale;
fixed_t spriteyscale;
} ATTRPACK resynch_pak;
typedef struct

View File

@ -671,10 +671,6 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_gif_dynamicdelay);
CV_RegisterVar(&cv_gif_localcolortable);
#ifdef WALLSPLATS
CV_RegisterVar(&cv_splats);
#endif
// register these so it is saved to config
CV_RegisterVar(&cv_playername);
CV_RegisterVar(&cv_playercolor);

View File

@ -75,9 +75,6 @@ extern consvar_t cv_teamscramble;
extern consvar_t cv_scrambleonchange;
extern consvar_t cv_netstat;
#ifdef WALLSPLATS
extern consvar_t cv_splats;
#endif
extern consvar_t cv_countdowntime;
extern consvar_t cv_runscripts;

View File

@ -9035,6 +9035,7 @@ static const char *const MOBJFLAG2_LIST[] = {
"AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH
"LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
"SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
"SPLAT", // Object is a splat
NULL
};
@ -9579,6 +9580,22 @@ struct {
{"tr_trans90",tr_trans90},
{"NUMTRANSMAPS",NUMTRANSMAPS},
// Render flags
{"RF_HORIZONTALFLIP",RF_HORIZONTALFLIP},
{"RF_VERTICALFLIP",RF_VERTICALFLIP},
{"RF_ONESIDED",RF_ONESIDED},
{"RF_NOSPLATBILLBOARD",RF_NOSPLATBILLBOARD},
{"RF_NOSPLATROLLANGLE",RF_NOSPLATROLLANGLE},
{"RF_FULLBRIGHT",RF_FULLBRIGHT},
{"RF_FULLDARK",RF_FULLDARK},
{"RF_SPRITETYPEMASK",RF_SPRITETYPEMASK},
{"RF_PAPERSPRITE",RF_PAPERSPRITE},
{"RF_FLOORSPRITE",RF_FLOORSPRITE},
{"RF_VOXELSPRITE",RF_VOXELSPRITE},
{"RF_SHADOWDRAW",RF_SHADOWDRAW},
{"RF_SHADOWEFFECTS",RF_SHADOWEFFECTS},
{"RF_DROPSHADOW",RF_DROPSHADOW},
// Level flags
{"LF_SCRIPTISFILE",LF_SCRIPTISFILE},
{"LF_SPEEDMUSIC",LF_SPEEDMUSIC},

View File

@ -641,6 +641,9 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Render flats on walls
#define WALLFLATS
/// Floor splats
#define FLOORSPLATS
/// Maintain compatibility with older 2.2 demos
#define OLD22DEMOCOMPAT

View File

@ -700,79 +700,6 @@ static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight)
#endif //doplanes
/*
wallVerts order is :
3--2
| /|
|/ |
0--1
*/
#ifdef WALLSPLATS
static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf)
{
FOutVector wallVerts[4];
wallsplat_t *splat;
patch_t *gpatch;
fixed_t i;
// seg bbox
fixed_t segbbox[4];
M_ClearBox(segbbox);
M_AddToBox(segbbox,
FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv1)->x),
FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv1)->y));
M_AddToBox(segbbox,
FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->x),
FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->y));
splat = (wallsplat_t *)gl_curline->linedef->splats;
for (; splat; splat = splat->next)
{
//BP: don't draw splat extern to this seg
// this is quick fix best is explain in logboris.txt at 12-4-2000
if (!M_PointInBox(segbbox,splat->v1.x,splat->v1.y) && !M_PointInBox(segbbox,splat->v2.x,splat->v2.y))
continue;
gpatch = W_CachePatchNum(splat->patch, PU_SPRITE);
HWR_GetPatch(gpatch);
wallVerts[0].x = wallVerts[3].x = FIXED_TO_FLOAT(splat->v1.x);
wallVerts[0].z = wallVerts[3].z = FIXED_TO_FLOAT(splat->v1.y);
wallVerts[2].x = wallVerts[1].x = FIXED_TO_FLOAT(splat->v2.x);
wallVerts[2].z = wallVerts[1].z = FIXED_TO_FLOAT(splat->v2.y);
i = splat->top;
if (splat->yoffset)
i += *splat->yoffset;
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(i)+(gpatch->height>>1);
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(i)-(gpatch->height>>1);
wallVerts[3].s = wallVerts[3].t = wallVerts[2].s = wallVerts[0].t = 0.0f;
wallVerts[1].s = wallVerts[1].t = wallVerts[2].t = wallVerts[0].s = 1.0f;
switch (splat->flags & SPLATDRAWMODE_MASK)
{
case SPLATDRAWMODE_OPAQUE :
pSurf.PolyColor.s.alpha = 0xff;
i = PF_Translucent;
break;
case SPLATDRAWMODE_TRANS :
pSurf.PolyColor.s.alpha = 128;
i = PF_Translucent;
break;
case SPLATDRAWMODE_SHADE :
pSurf.PolyColor.s.alpha = 0xff;
i = PF_Substractive;
break;
}
HWD.pfnSetShader(2); // wall shader
HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal);
}
}
#endif
FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf)
{
switch (transtablenum)
@ -797,19 +724,21 @@ static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, I
// Wall generation from subsector segs
// ==========================================================================
/*
wallVerts order is :
3--2
| /|
|/ |
0--1
*/
//
// HWR_ProjectWall
//
static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap)
{
HWR_Lighting(pSurf, lightlevel, wallcolormap);
HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, 2, false); // wall shader
#ifdef WALLSPLATS
if (gl_curline->linedef->splats && cv_splats.value)
HWR_DrawSegsSplats(pSurf);
#endif
}
// ==========================================================================
@ -3977,7 +3906,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
patch_t *gpatch; // sprite patch converted to hardware
FSurfaceInfo Surf;
const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES);
//const boolean papersprite = (spr->mobj && (spr->mobj->frame & FF_PAPERSPRITE));
//const boolean papersprite = R_ThingIsPaperSprite(spr->mobj);
if (spr->mobj)
this_scale = FIXED_TO_FLOAT(spr->mobj->scale);
if (hires)
@ -4761,14 +4690,14 @@ static void HWR_ProjectSprite(mobj_t *thing)
size_t lumpoff;
unsigned rot;
UINT16 flip;
boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP));
boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !R_ThingVerticallyFlipped(thing));
boolean mirrored = thing->mirrored;
boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored);
boolean hflip = (!R_ThingHorizontallyFlipped(thing) != !mirrored);
INT32 dispoffset;
angle_t ang;
INT32 heightsec, phs;
const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
const boolean papersprite = R_ThingIsPaperSprite(thing);
angle_t mobjangle = (thing->player ? thing->player->drawangle : thing->angle);
float z1, z2;
@ -4909,13 +4838,16 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (thing->rollangle)
{
rollangle = R_GetRollAngle(thing->rollangle);
rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, sprinfo, rollangle);
rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle);
if (rotsprite != NULL)
{
spr_width = SHORT(rotsprite->width) << FRACBITS;
spr_height = SHORT(rotsprite->height) << FRACBITS;
spr_offset = SHORT(rotsprite->leftoffset) << FRACBITS;
spr_topoffset = SHORT(rotsprite->topoffset) << FRACBITS;
spr_width = rotsprite->width << FRACBITS;
spr_height = rotsprite->height << FRACBITS;
spr_offset = rotsprite->leftoffset << FRACBITS;
spr_topoffset = rotsprite->topoffset << FRACBITS;
spr_topoffset += FEETADJUST;
// flip -> rotate, not rotate -> flip
flip = 0;
}
@ -6224,13 +6156,7 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend,
}
blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency
HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode, shader, false);
#ifdef WALLSPLATS
if (gl_curline->linedef->splats && cv_splats.value)
HWR_DrawSegsSplats(pSurf);
#endif
}
INT32 HWR_GetTextureUsed(void)

View File

@ -458,7 +458,7 @@ static int libd_getSpritePatch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), &spriteinfo[i], rot);
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &spriteinfo[i], rot);
LUA_PushUserdata(L, rotsprite, META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);
@ -570,7 +570,7 @@ static int libd_getSprite2Patch(lua_State *L)
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), &skins[i].sprinfo[j], rot);
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &skins[i].sprinfo[j], rot);
LUA_PushUserdata(L, rotsprite, META_PATCH);
lua_pushboolean(L, false);
lua_pushboolean(L, true);

View File

@ -56,6 +56,7 @@ enum mobj_e {
mobj_flags,
mobj_flags2,
mobj_eflags,
mobj_renderflags,
mobj_skin,
mobj_color,
mobj_bnext,
@ -83,6 +84,8 @@ enum mobj_e {
mobj_scale,
mobj_destscale,
mobj_scalespeed,
mobj_spritexscale,
mobj_spriteyscale,
mobj_extravalue1,
mobj_extravalue2,
mobj_cusval,
@ -125,6 +128,7 @@ static const char *const mobj_opt[] = {
"flags",
"flags2",
"eflags",
"renderflags",
"skin",
"color",
"bnext",
@ -152,6 +156,8 @@ static const char *const mobj_opt[] = {
"scale",
"destscale",
"scalespeed",
"spritexscale",
"spriteyscale",
"extravalue1",
"extravalue2",
"cusval",
@ -277,6 +283,9 @@ static int mobj_get(lua_State *L)
case mobj_eflags:
lua_pushinteger(L, mo->eflags);
break;
case mobj_renderflags:
lua_pushinteger(L, mo->renderflags);
break;
case mobj_skin: // skin name or nil, not struct
if (!mo->skin)
return 0;
@ -381,6 +390,12 @@ static int mobj_get(lua_State *L)
case mobj_scalespeed:
lua_pushfixed(L, mo->scalespeed);
break;
case mobj_spritexscale:
lua_pushfixed(L, mo->spritexscale);
break;
case mobj_spriteyscale:
lua_pushfixed(L, mo->spriteyscale);
break;
case mobj_extravalue1:
lua_pushinteger(L, mo->extravalue1);
break;
@ -580,6 +595,9 @@ static int mobj_set(lua_State *L)
case mobj_eflags:
mo->eflags = (UINT32)luaL_checkinteger(L, 3);
break;
case mobj_renderflags:
mo->renderflags = (UINT32)luaL_checkinteger(L, 3);
break;
case mobj_skin: // set skin by name
{
INT32 i;
@ -721,6 +739,12 @@ static int mobj_set(lua_State *L)
case mobj_scalespeed:
mo->scalespeed = luaL_checkfixed(L, 3);
break;
case mobj_spritexscale:
mo->spritexscale = luaL_checkfixed(L, 3);
break;
case mobj_spriteyscale:
mo->spriteyscale = luaL_checkfixed(L, 3);
break;
case mobj_extravalue1:
mo->extravalue1 = luaL_checkinteger(L, 3);
break;

View File

@ -38,10 +38,6 @@
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);
#ifdef WALLSPLATS
consvar_t cv_splats = CVAR_INIT ("splats", "On", CV_SAVE, CV_OnOff, NULL);
#endif
actioncache_t actioncachehead;
static mobj_t *overlaycap = NULL;
@ -1961,29 +1957,6 @@ void P_XYMovement(mobj_t *mo)
return;
}
// draw damage on wall
//SPLAT TEST ----------------------------------------------------------
#ifdef WALLSPLATS
if (blockingline && mo->type != MT_REDRING && mo->type != MT_FIREBALL
&& !(mo->flags2 & (MF2_AUTOMATIC|MF2_RAILRING|MF2_BOUNCERING|MF2_EXPLOSION|MF2_SCATTER)))
// set by last P_TryMove() that failed
{
divline_t divl;
divline_t misl;
fixed_t frac;
P_MakeDivline(blockingline, &divl);
misl.x = mo->x;
misl.y = mo->y;
misl.dx = mo->momx;
misl.dy = mo->momy;
frac = P_InterceptVector(&divl, &misl);
R_AddWallSplat(blockingline, P_PointOnLineSide(mo->x,mo->y,blockingline),
"A_DMG3", mo->z, frac, SPLATDRAWMODE_SHADE);
}
#endif
// --------------------------------------------------------- SPLAT TEST
P_ExplodeMissile(mo);
return;
}
@ -9614,12 +9587,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->fuse = 1; // Return to base.
break;
}
case MT_CANNONBALL:
#ifdef FLOORSPLATS
R_AddFloorSplat(mobj->tracer->subsector, mobj->tracer, "TARGET", mobj->tracer->x,
mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE);
#endif
break;
case MT_SPINDUST: // Spindash dust
mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000
mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same
@ -10487,6 +10454,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->tics = st->tics;
mobj->sprite = st->sprite;
mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits..
mobj->renderflags = 0;
P_SetupStateAnimation(mobj, st);
mobj->friction = ORIG_FRICTION;
@ -10497,6 +10465,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->scale = FRACUNIT;
mobj->destscale = mobj->scale;
mobj->scalespeed = FRACUNIT/12;
mobj->spritexscale = mobj->spriteyscale = mobj->scale;
// TODO: Make this a special map header
if ((maptol & TOL_ERZ3) && !(mobj->type == MT_BLACKEGGMAN))

View File

@ -194,6 +194,7 @@ typedef enum
MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
MF2_SPLAT = 1<<30, // Renders as a splat
// free: to and including 1<<31
} mobjflag2_t;
@ -308,6 +309,7 @@ typedef struct mobj_s
UINT32 flags; // flags from mobjinfo tables
UINT32 flags2; // MF2_ flags
UINT16 eflags; // extra flags
UINT32 renderflags; // render flags
void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin)
// Player and mobj sprites in multiplayer modes are modified
@ -360,6 +362,7 @@ typedef struct mobj_s
fixed_t scale;
fixed_t destscale;
fixed_t scalespeed;
fixed_t spritexscale, spriteyscale;
// Extra values are for internal use for whatever you want
INT32 extravalue1;

View File

@ -1393,7 +1393,10 @@ typedef enum
MD2_COLORIZED = 1<<12,
MD2_MIRRORED = 1<<13,
MD2_ROLLANGLE = 1<<14,
MD2_SHADOWSCALE = 1<<15,
MD2_SPRITEXSCALE = 1<<15,
MD2_SPRITEYSCALE = 1<<16,
MD2_SHADOWSCALE = 1<<17,
MD2_RENDERFLAGS = 1<<18,
} mobj_diff2_t;
typedef enum
@ -1604,8 +1607,14 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_MIRRORED;
if (mobj->rollangle)
diff2 |= MD2_ROLLANGLE;
if (mobj->spritexscale != FRACUNIT)
diff2 |= MD2_SPRITEXSCALE;
if (mobj->spriteyscale != FRACUNIT)
diff2 |= MD2_SPRITEYSCALE;
if (mobj->shadowscale)
diff2 |= MD2_SHADOWSCALE;
if (mobj->renderflags)
diff2 |= MD2_RENDERFLAGS;
if (diff2 != 0)
diff |= MD_MORE;
@ -1746,8 +1755,14 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEUINT8(save_p, mobj->mirrored);
if (diff2 & MD2_ROLLANGLE)
WRITEANGLE(save_p, mobj->rollangle);
if (diff2 & MD2_SPRITEXSCALE)
WRITEFIXED(save_p, mobj->spritexscale);
if (diff2 & MD2_SPRITEYSCALE)
WRITEFIXED(save_p, mobj->spriteyscale);
if (diff2 & MD2_SHADOWSCALE)
WRITEFIXED(save_p, mobj->shadowscale);
if (diff2 & MD2_RENDERFLAGS)
WRITEUINT32(save_p, mobj->renderflags);
WRITEUINT32(save_p, mobj->mobjnum);
}
@ -2755,8 +2770,14 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->mirrored = READUINT8(save_p);
if (diff2 & MD2_ROLLANGLE)
mobj->rollangle = READANGLE(save_p);
if (diff2 & MD2_SPRITEXSCALE)
mobj->spritexscale = READFIXED(save_p);
if (diff2 & MD2_SPRITEYSCALE)
mobj->spriteyscale = READFIXED(save_p);
if (diff2 & MD2_SHADOWSCALE)
mobj->shadowscale = READFIXED(save_p);
if (diff2 & MD2_RENDERFLAGS)
mobj->renderflags = READUINT32(save_p);
if (diff & MD_REDFLAG)
{

View File

@ -1080,9 +1080,6 @@ static void P_InitializeLinedef(line_t *ld)
ld->frontsector = ld->backsector = NULL;
ld->validcount = 0;
#ifdef WALLSPLATS
ld->splats = NULL;
#endif
ld->firsttag = ld->nexttag = -1;
ld->polyobj = NULL;
@ -2081,9 +2078,6 @@ static boolean P_LoadMapData(const virtres_t *virt)
static void P_InitializeSubsector(subsector_t *ss)
{
ss->sector = NULL;
#ifdef FLOORSPLATS
ss->splats = NULL;
#endif
ss->validcount = 0;
}
@ -2128,7 +2122,7 @@ static void P_LoadNodes(UINT8 *data)
* \param seg Seg to compute length for.
* \return Length in fracunits.
*/
fixed_t P_SegLength(seg_t *seg)
static fixed_t P_SegLength(seg_t *seg)
{
INT64 dx = (seg->v2->x - seg->v1->x)>>1;
INT64 dy = (seg->v2->y - seg->v1->y)>>1;
@ -4094,11 +4088,6 @@ boolean P_LoadLevel(boolean fromnetsave)
Patch_FreeTag(PU_PATCH_ROTATED);
Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1);
#if defined (WALLSPLATS) || defined (FLOORSPLATS)
// clear the splats from previous level
R_ClearLevelSplats();
#endif
P_InitThinkers();
P_InitCachedActions();

View File

@ -8678,12 +8678,6 @@ void P_MovePlayer(player_t *player)
player->fovadd = 0;
#endif
#ifdef FLOORSPLATS
if (cv_shadow.value && rendermode == render_soft)
R_AddFloorSplat(player->mo->subsector, player->mo, "SHADOW", player->mo->x,
player->mo->y, player->mo->floorz, SPLATDRAWMODE_OPAQUE);
#endif
// Look for blocks to bust up
// Because of FF_SHATTER, we should look for blocks constantly,
// not just when spinning or playing as Knuckles

View File

@ -1048,11 +1048,6 @@ static void R_Subsector(size_t num)
}
}
#ifdef FLOORSPLATS
if (sub->splats)
R_AddVisibleFloorSplats(sub);
#endif
// killough 9/18/98: Fix underwater slowdown, by passing real sector
// instead of fake one. Improve sprite lighting by basing sprite
// lightlevels on floor & ceiling lightlevels in the surrounding area.

View File

@ -409,9 +409,6 @@ typedef struct line_s
sector_t *backsector;
size_t validcount; // if == validcount, already checked
#if 1//#ifdef WALLSPLATS
void *splats; // wallsplat_t list
#endif
INT32 firsttag, nexttag; // improves searches for tags.
polyobj_t *polyobj; // Belongs to a polyobject?
@ -457,9 +454,6 @@ typedef struct subsector_s
INT16 numlines;
UINT16 firstline;
struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects
#if 1//#ifdef FLOORSPLATS
void *splats; // floorsplat_t list
#endif
size_t validcount;
} subsector_t;
@ -674,6 +668,7 @@ typedef struct
UINT8 *columns; // Software column data
void *hardware; // OpenGL patch, allocated whenever necessary
void *flats[4]; // The patch as flats
#ifdef ROTSPRITE
rotsprite_t *rotated; // Rotated patches
@ -718,6 +713,28 @@ typedef struct
#pragma pack()
#endif
typedef enum
{
RF_HORIZONTALFLIP = 0x0001, // Flip sprite horizontally
RF_VERTICALFLIP = 0x0002, // Flip sprite vertically
RF_ONESIDED = 0x0004, // Wall/floor sprite is visible from front only
RF_NOSPLATBILLBOARD = 0x0008, // Don't billboard floor sprites (faces forward from the view angle)
RF_NOSPLATROLLANGLE = 0x0010, // Don't rotate floor sprites by the object's rollangle (uses rotated patches instead)
RF_BLENDMASK = 0x0F00, // --Blending modes
RF_FULLBRIGHT = 0x0100, // Sprite is drawn at full brightness
RF_FULLDARK = 0x0200, // Sprite is drawn completely dark
RF_SPRITETYPEMASK = 0x7000, // ---Different sprite types, not all implemented
RF_PAPERSPRITE = 0x1000, // Paper sprite
RF_FLOORSPRITE = 0x2000, // Floor sprite
RF_VOXELSPRITE = 0x3000, // Voxel object
RF_SHADOWDRAW = 0x10000, // Stretches and skews the sprite like a shadow.
RF_SHADOWEFFECTS = 0x20000, // Scales and becomes transparent like a shadow.
RF_DROPSHADOW = (RF_SHADOWDRAW | RF_SHADOWEFFECTS | RF_FULLDARK),
} renderflags_t;
typedef enum
{
SRF_SINGLE = 0, // 0-angle for all rotations
@ -759,7 +776,7 @@ typedef struct
UINT16 flip;
#ifdef ROTSPRITE
rotsprite_t *rotated[16]; // Rotated patches
rotsprite_t *rotated[2][16]; // Rotated patches
#endif
} spriteframe_t;

View File

@ -98,6 +98,7 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight;
INT32 ds_y, ds_x1, ds_x2;
lighttable_t *ds_colormap;
lighttable_t *ds_translation; // Lactozilla: Sprite splat drawer
fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
UINT16 ds_flatwidth, ds_flatheight;
boolean ds_powersoftwo;

View File

@ -56,6 +56,7 @@ extern INT32 dc_texheight;
extern INT32 ds_y, ds_x1, ds_x2;
extern lighttable_t *ds_colormap;
extern lighttable_t *ds_translation;
extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
extern UINT16 ds_flatwidth, ds_flatheight;
extern boolean ds_powersoftwo;
@ -151,8 +152,10 @@ void R_DrawColumnShadowed_8(void);
void R_DrawSpan_8(void);
void R_DrawSplat_8(void);
void R_DrawFloorSprite_8(void);
void R_DrawTranslucentSpan_8(void);
void R_DrawTranslucentSplat_8(void);
void R_DrawTranslucentFloorSprite_8(void);
void R_DrawTiltedSpan_8(void);
void R_DrawTiltedTranslucentSpan_8(void);
#ifndef NOWATER
@ -171,8 +174,10 @@ void R_DrawFogSpan_8(void);
// Lactozilla: Non-powers-of-two
void R_DrawSpan_NPO2_8(void);
void R_DrawTranslucentSpan_NPO2_8(void);
void R_DrawFloorSprite_NPO2_8(void);
void R_DrawSplat_NPO2_8(void);
void R_DrawTranslucentSplat_NPO2_8(void);
void R_DrawTranslucentFloorSprite_NPO2_8(void);
void R_DrawTiltedSpan_NPO2_8(void);
void R_DrawTiltedTranslucentSpan_NPO2_8(void);
#ifndef NOWATER

View File

@ -1419,6 +1419,230 @@ void R_DrawTranslucentSplat_8 (void)
}
}
/** \brief The R_DrawFloorSprite_8 function
Just like R_DrawSplat_8, but for floor sprites.
*/
void R_DrawFloorSprite_8 (void)
{
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
UINT16 *source;
UINT8 *colormap;
UINT8 *translation;
UINT8 *dest;
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
size_t count = (ds_x2 - ds_x1 + 1);
UINT32 val;
xposition = ds_xfrac; yposition = ds_yfrac;
xstep = ds_xstep; ystep = ds_ystep;
// SoM: we only need 6 bits for the integer part (0 thru 63) so the rest
// can be used for the fraction part. This allows calculation of the memory address in the
// texture with two shifts, an OR and one AND. (see below)
// for texture sizes > 64 the amount of precision we can allow will decrease, but only by one
// bit per power of two (obviously)
// Ok, because I was able to eliminate the variable spot below, this function is now FASTER
// than the original span renderer. Whodathunkit?
xposition <<= nflatshiftup; yposition <<= nflatshiftup;
xstep <<= nflatshiftup; ystep <<= nflatshiftup;
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
dest = ylookup[ds_y] + columnofs[ds_x1];
while (count >= 8)
{
// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
// have the uber complicated math to calculate it now, so that was a memory write we didn't
// need!
//
// <Callum> 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size)
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[0] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[1] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[2] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[3] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[4] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[5] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[6] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
val &= 4194303;
val = source[val];
if (val & 0xFF00)
dest[7] = colormap[translation[val & 0xFF]];
xposition += xstep;
yposition += ystep;
dest += 8;
count -= 8;
}
while (count-- && dest <= deststop)
{
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
*dest = colormap[translation[val & 0xFF]];
dest++;
xposition += xstep;
yposition += ystep;
}
}
/** \brief The R_DrawTranslucentFloorSplat_8 function
Just like R_DrawFloorSprite_8, but is translucent!
*/
void R_DrawTranslucentFloorSprite_8 (void)
{
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
UINT16 *source;
UINT8 *colormap;
UINT8 *translation;
UINT8 *dest;
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
size_t count = (ds_x2 - ds_x1 + 1);
UINT32 val;
xposition = ds_xfrac; yposition = ds_yfrac;
xstep = ds_xstep; ystep = ds_ystep;
// SoM: we only need 6 bits for the integer part (0 thru 63) so the rest
// can be used for the fraction part. This allows calculation of the memory address in the
// texture with two shifts, an OR and one AND. (see below)
// for texture sizes > 64 the amount of precision we can allow will decrease, but only by one
// bit per power of two (obviously)
// Ok, because I was able to eliminate the variable spot below, this function is now FASTER
// than the original span renderer. Whodathunkit?
xposition <<= nflatshiftup; yposition <<= nflatshiftup;
xstep <<= nflatshiftup; ystep <<= nflatshiftup;
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
dest = ylookup[ds_y] + columnofs[ds_x1];
while (count >= 8)
{
// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
// have the uber complicated math to calculate it now, so that was a memory write we didn't
// need!
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[0] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[0]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[1] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[1]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[2] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[2]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[3] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[3]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[4] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[4]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[5] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[5]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[6] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[6]);
xposition += xstep;
yposition += ystep;
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
dest[7] = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + dest[7]);
xposition += xstep;
yposition += ystep;
dest += 8;
count -= 8;
}
while (count-- && dest <= deststop)
{
val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)];
if (val & 0xFF00)
*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
dest++;
xposition += xstep;
yposition += ystep;
}
}
/** \brief The R_DrawTranslucentSpan_8 function
Draws the actual span with translucency.
*/

View File

@ -754,6 +754,104 @@ void R_DrawTranslucentSplat_NPO2_8 (void)
}
}
/** \brief The R_DrawFloorSprite_NPO2_8 function
Just like R_DrawSplat_NPO2_8, but for floor sprites.
*/
void R_DrawFloorSprite_NPO2_8 (void)
{
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
UINT16 *source;
UINT8 *translation;
UINT8 *colormap;
UINT8 *dest;
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
size_t count = (ds_x2 - ds_x1 + 1);
UINT32 val;
xposition = ds_xfrac; yposition = ds_yfrac;
xstep = ds_xstep; ystep = ds_ystep;
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
dest = ylookup[ds_y] + columnofs[ds_x1];
while (count-- && dest <= deststop)
{
fixed_t x = (xposition >> FRACBITS);
fixed_t y = (yposition >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
if (val & 0xFF00)
*dest = colormap[translation[val & 0xFF]];
dest++;
xposition += xstep;
yposition += ystep;
}
}
/** \brief The R_DrawTranslucentFloorSprite_NPO2_8 function
Just like R_DrawFloorSprite_NPO2_8, but is translucent!
*/
void R_DrawTranslucentFloorSprite_NPO2_8 (void)
{
fixed_t xposition;
fixed_t yposition;
fixed_t xstep, ystep;
UINT16 *source;
UINT8 *translation;
UINT8 *colormap;
UINT8 *dest;
const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height;
size_t count = (ds_x2 - ds_x1 + 1);
UINT32 val;
xposition = ds_xfrac; yposition = ds_yfrac;
xstep = ds_xstep; ystep = ds_ystep;
source = (UINT16 *)ds_source;
colormap = ds_colormap;
translation = ds_translation;
dest = ylookup[ds_y] + columnofs[ds_x1];
while (count-- && dest <= deststop)
{
fixed_t x = (xposition >> FRACBITS);
fixed_t y = (yposition >> FRACBITS);
// Carefully align all of my Friends.
if (x < 0)
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
if (y < 0)
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
x %= ds_flatwidth;
y %= ds_flatheight;
val = source[((y * ds_flatwidth) + x)];
if (val & 0xFF00)
*dest = *(ds_transmap + (colormap[translation[val & 0xFF]] << 8) + *dest);
dest++;
xposition += xstep;
yposition += ystep;
}
}
/** \brief The R_DrawTranslucentSpan_NPO2_8 function
Draws the actual span with translucency.
*/

View File

@ -1472,9 +1472,6 @@ void R_RenderPlayerView(player_t *player)
}
R_ClearDrawSegs();
R_ClearSprites();
#ifdef FLOORSPLATS
R_ClearVisibleFloorSplats();
#endif
Portal_InitList();
// check for new console commands.
@ -1555,9 +1552,6 @@ void R_RenderPlayerView(player_t *player)
rs_sw_planetime = I_GetTimeMicros();
R_DrawPlanes();
#ifdef FLOORSPLATS
R_DrawVisibleFloorSplats();
#endif
rs_sw_planetime = I_GetTimeMicros() - rs_sw_planetime;
// draw mid texture and sprite

View File

@ -11,6 +11,7 @@
#include "doomdef.h"
#include "r_patch.h"
#include "r_picformats.h"
#include "r_defs.h"
#include "z_zone.h"
@ -66,18 +67,25 @@ patch_t *Patch_Create(softwarepatch_t *source, size_t srcsize, void *dest)
static void Patch_FreeData(patch_t *patch)
{
INT32 i;
#ifdef HWRENDER
if (patch->hardware)
HWR_FreeTexture(patch);
#endif
for (i = 0; i < 2; i++)
{
if (patch->flats[i])
Patch_Free(patch->flats[i]);
}
#ifdef ROTSPRITE
if (patch->rotated)
{
rotsprite_t *rotsprite = patch->rotated;
INT32 i = 0;
for (; i < rotsprite->angles; i++)
for (i = 0; i < rotsprite->angles; i++)
{
if (rotsprite->patches[i])
Patch_Free(rotsprite->patches[i]);
@ -116,6 +124,13 @@ void Patch_FreeTags(INT32 lowtag, INT32 hightag)
Z_IterateTags(lowtag, hightag, Patch_FreeTagsCallback);
}
void Patch_GenerateFlat(patch_t *patch, pictureflags_t flags)
{
UINT8 flip = (flags & (PICFLAGS_XFLIP | PICFLAGS_YFLIP));
if (patch->flats[flip] == NULL)
patch->flats[flip] = Picture_Convert(PICFMT_PATCH, patch, PICFMT_FLAT16, 0, NULL, 0, 0, 0, 0, flags);
}
#ifdef HWRENDER
//
// Allocates a hardware patch.

View File

@ -13,6 +13,7 @@
#define __R_PATCH__
#include "r_defs.h"
#include "r_picformats.h"
#include "doomdef.h"
// Patch functions
@ -22,6 +23,8 @@ void Patch_Free(patch_t *patch);
#define Patch_FreeTag(tagnum) Patch_FreeTags(tagnum, tagnum)
void Patch_FreeTags(INT32 lowtag, INT32 hightag);
void Patch_GenerateFlat(patch_t *patch, pictureflags_t flags);
#ifdef HWRENDER
void *Patch_AllocateHardwarePatch(patch_t *patch);
void *Patch_CreateGL(patch_t *patch);
@ -30,7 +33,12 @@ void *Patch_CreateGL(patch_t *patch);
#ifdef ROTSPRITE
void Patch_Rotate(patch_t *patch, INT32 angle, INT32 xpivot, INT32 ypivot, boolean flip);
patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip);
patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spriteangle, boolean flip, void *info, INT32 rotationangle);INT32 R_GetRollAngle(angle_t rollangle);
patch_t *Patch_GetRotatedSprite(
spriteframe_t *sprite,
size_t frame, size_t spriteangle,
boolean flip, boolean adjustfeet,
void *info, INT32 rotationangle);
INT32 R_GetRollAngle(angle_t rollangle);
#endif
#endif // __R_PATCH__

View File

@ -41,19 +41,26 @@ patch_t *Patch_GetRotated(patch_t *patch, INT32 angle, boolean flip)
return rotsprite->patches[angle];
}
patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spriteangle, boolean flip, void *info, INT32 rotationangle)
patch_t *Patch_GetRotatedSprite(
spriteframe_t *sprite,
size_t frame, size_t spriteangle,
boolean flip, boolean adjustfeet,
void *info, INT32 rotationangle)
{
rotsprite_t *rotsprite = sprite->rotated[spriteangle];
rotsprite_t *rotsprite;
spriteinfo_t *sprinfo = (spriteinfo_t *)info;
INT32 idx = rotationangle;
UINT8 type = (adjustfeet ? 1 : 0);
if (rotationangle < 1 || rotationangle >= ROTANGLES)
return NULL;
rotsprite = sprite->rotated[type][spriteangle];
if (rotsprite == NULL)
{
rotsprite = RotatedPatch_Create(ROTANGLES);
sprite->rotated[spriteangle] = rotsprite;
sprite->rotated[type][spriteangle] = rotsprite;
}
if (flip)
@ -84,7 +91,8 @@ patch_t *Patch_GetRotatedSprite(spriteframe_t *sprite, size_t frame, size_t spri
RotatedPatch_DoRotation(rotsprite, patch, rotationangle, xpivot, ypivot, flip);
//BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer
((patch_t *)rotsprite->patches[idx])->topoffset += FEETADJUST>>FRACBITS;
if (adjustfeet)
((patch_t *)rotsprite->patches[idx])->topoffset += FEETADJUST>>FRACBITS;
}
return rotsprite->patches[idx];

View File

@ -745,6 +745,7 @@ void R_DrawSinglePlane(visplane_t *pl)
ffloor_t *rover;
int type;
int spanfunctype = BASEDRAWFUNC;
angle_t viewang = viewangle;
if (!(pl->minx <= pl->maxx))
return;
@ -871,20 +872,6 @@ void R_DrawSinglePlane(visplane_t *pl)
light = (pl->lightlevel >> LIGHTSEGSHIFT);
}
if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later
&& viewangle != pl->viewangle+pl->plangle)
{
memset(cachedheight, 0, sizeof (cachedheight));
angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT;
basexscale = FixedDiv(FINECOSINE(angle),centerxfrac);
baseyscale = -FixedDiv(FINESINE(angle),centerxfrac);
viewangle = pl->viewangle+pl->plangle;
}
xoffs = pl->xoffs;
yoffs = pl->yoffs;
planeheight = abs(pl->height - pl->viewz);
currentplane = pl;
levelflat = &levelflats[pl->picnum];
@ -909,6 +896,20 @@ void R_DrawSinglePlane(visplane_t *pl)
R_CheckFlatLength(ds_flatwidth * ds_flatheight);
}
if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later
&& viewangle != pl->viewangle+pl->plangle)
{
memset(cachedheight, 0, sizeof (cachedheight));
angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT;
basexscale = FixedDiv(FINECOSINE(angle),centerxfrac);
baseyscale = -FixedDiv(FINESINE(angle),centerxfrac);
viewangle = pl->viewangle+pl->plangle;
}
xoffs = pl->xoffs;
yoffs = pl->yoffs;
planeheight = abs(pl->height - pl->viewz);
if (light >= LIGHTLEVELS)
light = LIGHTLEVELS-1;
@ -1121,6 +1122,8 @@ using the palette colors.
}
}
#endif
viewangle = viewang;
}
void R_PlaneBounds(visplane_t *plane)

View File

@ -63,170 +63,6 @@ static lighttable_t **walllights;
static INT16 *maskedtexturecol;
static fixed_t *maskedtextureheight = NULL;
// ==========================================================================
// R_Splats Wall Splats Drawer
// ==========================================================================
#ifdef WALLSPLATS
static INT16 last_ceilingclip[MAXVIDWIDTH];
static INT16 last_floorclip[MAXVIDWIDTH];
static void R_DrawSplatColumn(column_t *column)
{
INT32 topscreen, bottomscreen;
fixed_t basetexturemid;
INT32 topdelta, prevdelta = -1;
basetexturemid = dc_texturemid;
for (; column->topdelta != 0xff ;)
{
// calculate unclipped screen coordinates for post
topdelta = column->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
topscreen = sprtopscreen + spryscale*topdelta;
bottomscreen = topscreen + spryscale*column->length;
dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
dc_yh = (bottomscreen-1)>>FRACBITS;
if (dc_yh >= last_floorclip[dc_x])
dc_yh = last_floorclip[dc_x] - 1;
if (dc_yl <= last_ceilingclip[dc_x])
dc_yl = last_ceilingclip[dc_x] + 1;
if (dc_yl <= dc_yh && dl_yh < vid.height && yh > 0)
{
dc_source = (UINT8 *)column + 3;
dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
// Drawn by R_DrawColumn.
colfunc();
}
column = (column_t *)((UINT8 *)column + column->length + 4);
}
dc_texturemid = basetexturemid;
}
static void R_DrawWallSplats(void)
{
wallsplat_t *splat;
seg_t *seg;
angle_t angle, angle1, angle2;
INT32 x1, x2;
size_t pindex;
column_t *col;
patch_t *patch;
fixed_t texturecolumn;
splat = (wallsplat_t *)linedef->splats;
I_Assert(splat != NULL);
seg = ds_p->curline;
// draw all splats from the line that touches the range of the seg
for (; splat; splat = splat->next)
{
angle1 = R_PointToAngle(splat->v1.x, splat->v1.y);
angle2 = R_PointToAngle(splat->v2.x, splat->v2.y);
angle1 = (angle1 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT;
angle2 = (angle2 - viewangle + ANGLE_90)>>ANGLETOFINESHIFT;
// out of the viewangletox lut
/// \todo clip it to the screen
if (angle1 > FINEANGLES/2 || angle2 > FINEANGLES/2)
continue;
x1 = viewangletox[angle1];
x2 = viewangletox[angle2];
if (x1 >= x2)
continue; // does not cross a pixel
// splat is not in this seg range
if (x2 < ds_p->x1 || x1 > ds_p->x2)
continue;
if (x1 < ds_p->x1)
x1 = ds_p->x1;
if (x2 > ds_p->x2)
x2 = ds_p->x2;
if (x2 <= x1)
continue;
// calculate incremental stepping values for texture edges
rw_scalestep = ds_p->scalestep;
spryscale = ds_p->scale1 + (x1 - ds_p->x1)*rw_scalestep;
mfloorclip = floorclip;
mceilingclip = ceilingclip;
patch = W_CachePatchNum(splat->patch, PU_PATCH);
dc_texturemid = splat->top + (SHORT(patch->height)<<(FRACBITS-1)) - viewz;
if (splat->yoffset)
dc_texturemid += *splat->yoffset;
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
// set drawing mode
switch (splat->flags & SPLATDRAWMODE_MASK)
{
case SPLATDRAWMODE_OPAQUE:
colfunc = colfuncs[BASEDRAWFUNC];
break;
case SPLATDRAWMODE_TRANS:
if (!cv_translucency.value)
colfunc = colfuncs[BASEDRAWFUNC];
else
{
dc_transmap = transtables + ((tr_trans50 - 1)<<FF_TRANSSHIFT);
colfunc = colfuncs[COLDRAWFUNC_FUZZY];
}
break;
case SPLATDRAWMODE_SHADE:
colfunc = colfuncs[COLDRAWFUNC_SHADE];
break;
}
dc_texheight = 0;
// draw the columns
for (dc_x = x1; dc_x <= x2; dc_x++, spryscale += rw_scalestep)
{
pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT;
if (pindex >= MAXLIGHTSCALE)
pindex = MAXLIGHTSCALE - 1;
dc_colormap = walllights[pindex];
if (frontsector->extra_colormap)
dc_colormap = frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
dc_iscale = 0xffffffffu / (unsigned)spryscale;
// find column of patch, from perspective
angle = (rw_centerangle + xtoviewangle[dc_x])>>ANGLETOFINESHIFT;
texturecolumn = rw_offset2 - splat->offset
- FixedMul(FINETANGENT(angle), rw_distance);
// FIXME!
texturecolumn >>= FRACBITS;
if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
continue;
// draw the texture
col = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn]));
R_DrawSplatColumn(col);
}
} // next splat
colfunc = colfuncs[BASEDRAWFUNC];
}
#endif //WALLSPLATS
// ==========================================================================
// R_RenderMaskedSegRange
// ==========================================================================
@ -2786,20 +2622,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
}
}
#ifdef WALLSPLATS
if (linedef->splats && cv_splats.value)
{
// Isn't a bit wasteful to copy the ENTIRE array for every drawseg?
M_Memcpy(last_ceilingclip + ds_p->x1, ceilingclip + ds_p->x1,
sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1));
M_Memcpy(last_floorclip + ds_p->x1, floorclip + ds_p->x1,
sizeof (INT16) * (ds_p->x2 - ds_p->x1 + 1));
R_RenderSegLoop();
R_DrawWallSplats();
}
else
#endif
R_RenderSegLoop();
R_RenderSegLoop();
colfunc = colfuncs[BASEDRAWFUNC];
if (portalline) // if curline is a portal, set portalrender for drawseg

View File

@ -8,459 +8,253 @@
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file r_splats.c
/// \brief floor and wall splats
/// \brief Floor splats
#include "r_draw.h"
#include "r_main.h"
#include "r_plane.h"
#include "r_splats.h"
#include "r_bsp.h"
#include "w_wad.h"
#include "z_zone.h"
#include "d_netcmd.h"
#ifdef WALLSPLATS
static wallsplat_t wallsplats[MAXLEVELSPLATS]; // WALL splats
static INT32 freewallsplat;
#endif
#ifdef USEASM
/// \brief for floorsplats \note accessed by asm code
struct rastery_s *prastertab;
#endif
struct rastery_s *prastertab; // for ASM code
#ifdef FLOORSPLATS
static floorsplat_t floorsplats[1]; // FLOOR splats
static INT32 freefloorsplat;
struct rastery_s
{
fixed_t minx, maxx; // for each raster line starting at line 0
fixed_t tx1, ty1;
fixed_t tx2, ty2; // start/end points in texture at this line
};
static struct rastery_s rastertab[MAXVIDHEIGHT];
static void prepare_rastertab(void);
#endif
// --------------------------------------------------------------------------
// setup splat cache
// --------------------------------------------------------------------------
void R_ClearLevelSplats(void)
{
#ifdef WALLSPLATS
freewallsplat = 0;
memset(wallsplats, 0, sizeof (wallsplats));
#endif
#ifdef FLOORSPLATS
freefloorsplat = 0;
memset(floorsplats, 0, sizeof (floorsplats));
// setup to draw floorsplats
prastertab = rastertab;
prepare_rastertab();
#endif
}
// ==========================================================================
// WALL SPLATS
// ==========================================================================
#ifdef WALLSPLATS
// --------------------------------------------------------------------------
// Return a pointer to a splat free for use, or NULL if no more splats are
// available
// --------------------------------------------------------------------------
static wallsplat_t *R_AllocWallSplat(void)
{
wallsplat_t *splat;
wallsplat_t *p_splat;
line_t *li;
// clear the splat from the line if it was in use
splat = &wallsplats[freewallsplat];
li = splat->line;
if (li)
{
// remove splat from line splats list
if (li->splats == splat)
li->splats = splat->next; // remove from head
else
{
I_Assert(li->splats != NULL);
for (p_splat = li->splats; p_splat->next; p_splat = p_splat->next)
if (p_splat->next == splat)
{
p_splat->next = splat->next;
break;
}
}
}
memset(splat, 0, sizeof (wallsplat_t));
// for next allocation
freewallsplat++;
if (freewallsplat >= 20)
freewallsplat = 0;
return splat;
}
// Add a new splat to the linedef:
// top: top z coord
// wallfrac: frac along the linedef vector (0 to FRACUNIT)
// splatpatchname: name of patch to draw
void R_AddWallSplat(line_t *wallline, INT16 sectorside, const char *patchname, fixed_t top,
fixed_t wallfrac, INT32 flags)
{
fixed_t fracsplat, linelength;
wallsplat_t *splat = NULL;
wallsplat_t *p_splat;
patch_t *patch;
sector_t *backsector = NULL;
if (W_CheckNumForName(patchname) != LUMPERROR)
splat = R_AllocWallSplat();
if (!splat)
return;
// set the splat
splat->patch = W_GetNumForName(patchname);
sectorside ^= 1;
if (wallline->sidenum[sectorside] != 0xffff)
{
backsector = sides[wallline->sidenum[sectorside]].sector;
if (top < backsector->floorheight)
{
splat->yoffset = &backsector->floorheight;
top -= backsector->floorheight;
}
else if (top > backsector->ceilingheight)
{
splat->yoffset = &backsector->ceilingheight;
top -= backsector->ceilingheight;
}
}
splat->top = top;
splat->flags = flags;
// bad.. but will be needed for drawing anyway..
patch = W_CachePatchNum(splat->patch, PU_PATCH);
// offset needed by draw code for texture mapping
linelength = P_SegLength((seg_t *)wallline);
splat->offset = FixedMul(wallfrac, linelength) - (SHORT(patch->width)<<(FRACBITS-1));
fracsplat = FixedDiv(((SHORT(patch->width)<<FRACBITS)>>1), linelength);
wallfrac -= fracsplat;
if (wallfrac > linelength)
return;
splat->v1.x = wallline->v1->x + FixedMul(wallline->dx, wallfrac);
splat->v1.y = wallline->v1->y + FixedMul(wallline->dy, wallfrac);
wallfrac += fracsplat + fracsplat;
if (wallfrac < 0)
return;
splat->v2.x = wallline->v1->x + FixedMul(wallline->dx, wallfrac);
splat->v2.y = wallline->v1->y + FixedMul(wallline->dy, wallfrac);
if (wallline->frontsector && wallline->frontsector == backsector)
return;
// insert splat in the linedef splat list
// BP: why not insert in head is much more simple?
// BP: because for remove it is more simple!
splat->line = wallline;
splat->next = NULL;
if (wallline->splats)
{
p_splat = wallline->splats;
while (p_splat->next)
p_splat = p_splat->next;
p_splat->next = splat;
}
else
wallline->splats = splat;
}
#endif // WALLSPLATS
UINT8 ds_splatclip[MAXVIDWIDTH];
// ==========================================================================
// FLOOR SPLATS
// ==========================================================================
#ifdef FLOORSPLATS
// --------------------------------------------------------------------------
// Return a pointer to a splat free for use, or NULL if no more splats are
// available
// --------------------------------------------------------------------------
static floorsplat_t *R_AllocFloorSplat(void)
#ifdef USEASM
void ASMCALL rasterize_segment_tex_asm(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir);
#endif
// Lactozilla
static void rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2, INT32 tc, INT32 dir)
{
floorsplat_t *splat;
floorsplat_t *p_splat;
subsector_t *sub;
// find splat to use
freefloorsplat++;
if (freefloorsplat >= 1)
freefloorsplat = 0;
// clear the splat from the line if it was in use
splat = &floorsplats[freefloorsplat];
sub = splat->subsector;
if (sub)
#ifdef USEASM
if (R_ASM)
{
// remove splat from subsector splats list
if (sub->splats == splat)
sub->splats = splat->next; // remove from head
rasterize_segment_tex_asm(x1, y1, x2, y2, tv1, tv2, tc, dir);
return;
}
else
#endif
{
fixed_t xs, xe, count;
fixed_t dx0, dx1;
if (y1 == y2)
return;
if (y2 > y1)
{
count = (y2-y1)+1;
dx0 = FixedDiv((x2-x1)<<FRACBITS, count<<FRACBITS);
dx1 = FixedDiv((tv2-tv1)<<FRACBITS, count<<FRACBITS);
xs = x1 << FRACBITS;
xe = tv1 << FRACBITS;
tc <<= FRACBITS;
if (dir == 0)
{
for (;;)
{
rastertab[y1].maxx = xs;
rastertab[y1].tx2 = xe;
rastertab[y1].ty2 = tc;
xs += dx0;
xe += dx1;
y1++;
if (count-- < 1) break;
}
}
else
{
for (;;)
{
rastertab[y1].maxx = xs;
rastertab[y1].tx2 = tc;
rastertab[y1].ty2 = xe;
xs += dx0;
xe += dx1;
y1++;
if (count-- < 1) break;
}
}
}
else
{
p_splat = sub->splats;
while (p_splat->next)
count = (y1-y2)+1;
dx0 = FixedDiv((x1-x2)<<FRACBITS, count<<FRACBITS);
dx1 = FixedDiv((tv1-tv2)<<FRACBITS, count<<FRACBITS);
xs = x2 << FRACBITS;
xe = tv2 << FRACBITS;
tc <<= FRACBITS;
if (dir == 0)
{
if (p_splat->next == splat)
p_splat->next = splat->next;
for (;;)
{
rastertab[y2].minx = xs;
rastertab[y2].tx1 = xe;
rastertab[y2].ty1 = tc;
xs += dx0;
xe += dx1;
y2++;
if (count-- < 1) break;
}
}
else
{
for (;;)
{
rastertab[y2].minx = xs;
rastertab[y2].tx1 = tc;
rastertab[y2].ty1 = xe;
xs += dx0;
xe += dx1;
y2++;
if (count-- < 1) break;
}
}
}
}
memset(splat, 0, sizeof (floorsplat_t));
return splat;
}
// --------------------------------------------------------------------------
// Add a floor splat to the subsector
// --------------------------------------------------------------------------
void R_AddFloorSplat(subsector_t *subsec, mobj_t *mobj, const char *picname, fixed_t x, fixed_t y, fixed_t z,
INT32 flags)
{
floorsplat_t *splat = NULL;
floorsplat_t *p_splat;
INT32 size;
if (W_CheckNumForName(picname) != LUMPERROR)
splat = R_AllocFloorSplat();
if (!splat)
return;
// set the splat
splat->pic = W_GetNumForName(picname);
splat->flags = flags;
splat->mobj = mobj;
splat->z = z;
size = W_LumpLength(splat->pic);
switch (size)
{
case 4194304: // 2048x2048 lump
splat->size = 1024;
break;
case 1048576: // 1024x1024 lump
splat->size = 512;
break;
case 262144:// 512x512 lump
splat->size = 256;
break;
case 65536: // 256x256 lump
splat->size = 128;
break;
case 16384: // 128x128 lump
splat->size = 64;
break;
case 1024: // 32x32 lump
splat->size = 16;
break;
default: // 64x64 lump
splat->size = 32;
break;
}
// 3--2
// | |
// 0--1
//
splat->verts[0].x = splat->verts[3].x = x - (splat->size<<FRACBITS);
splat->verts[2].x = splat->verts[1].x = x + ((splat->size-1)<<FRACBITS);
splat->verts[3].y = splat->verts[2].y = y + ((splat->size-1)<<FRACBITS);
splat->verts[0].y = splat->verts[1].y = y - (splat->size<<FRACBITS);
// insert splat in the subsector splat list
splat->subsector = subsec;
splat->next = NULL;
if (subsec->splats)
{
p_splat = subsec->splats;
while (p_splat->next)
p_splat = p_splat->next;
p_splat->next = splat;
}
else
subsec->splats = splat;
}
// --------------------------------------------------------------------------
// Before each frame being rendered, clear the visible floorsplats list
// --------------------------------------------------------------------------
static floorsplat_t *visfloorsplats;
void R_ClearVisibleFloorSplats(void)
{
visfloorsplats = NULL;
}
// --------------------------------------------------------------------------
// Add a floorsplat to the visible floorsplats list, for the current frame
// --------------------------------------------------------------------------
void R_AddVisibleFloorSplats(subsector_t *subsec)
{
floorsplat_t *pSplat;
I_Assert(subsec->splats != NULL);
pSplat = subsec->splats;
// the splat is not visible from below
// FIXME: depending on some flag in pSplat->flags, some splats may be visible from 2 sides
// (above/below)
if (pSplat->z < viewz)
{
pSplat->nextvis = visfloorsplats;
visfloorsplats = pSplat;
}
while (pSplat->next)
{
pSplat = pSplat->next;
if (pSplat->z < viewz)
{
pSplat->nextvis = visfloorsplats;
visfloorsplats = pSplat;
}
}
}
#ifdef USEASM
// tv1, tv2 = x/y qui varie dans la texture, tc = x/y qui est constant.
void ASMCALL rasterize_segment_tex(INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 tv1, INT32 tv2,
INT32 tc, INT32 dir);
#endif
// current test with floor tile
//#define FLOORSPLATSOLIDCOLOR
// --------------------------------------------------------------------------
// Rasterize the four edges of a floor splat polygon,
// fill the polygon with linear interpolation, call span drawer for each
// scan line
// --------------------------------------------------------------------------
static void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, UINT8 *pTex)
void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis)
{
// rasterizing
INT32 miny = vid.height + 1, maxy = 0, y, x1, ry1, x2, y2;
fixed_t offsetx, offsety;
INT32 miny = viewheight + 1, maxy = 0, y, x1, ry1, x2, y2, i;
fixed_t offsetx = 0, offsety = 0;
fixed_t step;
#ifdef FLOORSPLATSOLIDCOLOR
UINT8 *pDest;
INT32 tdx, tdy, ty, tx, x;
#else
lighttable_t **planezlight;
fixed_t planeheight;
fixed_t xstep, ystep;
angle_t angle, planecos, planesin;
fixed_t distance, span;
size_t indexr;
INT32 light;
#endif
(void)pTex;
offsetx = pSplat->verts[0].x & ((pSplat->size << FRACBITS)-1);
offsety = pSplat->verts[0].y & ((pSplat->size << FRACBITS)-1);
int spanfunctype = SPANDRAWFUNC_SPRITE;
prepare_rastertab();
#define RASTERPARAMS(vnum1, vnum2, tv1, tv2, tc, dir) \
x1 = verts[vnum1].x; \
ry1 = verts[vnum1].y; \
x2 = verts[vnum2].x; \
y2 = verts[vnum2].y; \
if (y2 > ry1) \
step = FixedDiv(x2-x1, y2-ry1+1); \
else if (y2 == ry1) \
step = 0; \
else \
step = FixedDiv(x2-x1, ry1-y2+1); \
if (ry1 < 0) { \
if (step) { \
x1 <<= FRACBITS; \
x1 += (-ry1)*step; \
x1 >>= FRACBITS; \
} \
ry1 = 0; \
} \
if (ry1 >= vid.height) { \
if (step) { \
x1 <<= FRACBITS; \
x1 -= (vid.height-1-ry1)*step; \
x1 >>= FRACBITS; \
} \
ry1 = vid.height - 1; \
} \
if (y2 < 0) { \
if (step) { \
x2 <<= FRACBITS; \
x2 -= (-y2)*step; \
x2 >>= FRACBITS; \
} \
y2 = 0; \
} \
if (y2 >= vid.height) { \
if (step) { \
x2 <<= FRACBITS; \
x2 += (vid.height-1-y2)*step; \
x2 >>= FRACBITS; \
} \
y2 = vid.height - 1; \
} \
rasterize_segment_tex(x1, ry1, x2, y2, tv1, tv2, tc, dir); \
if (ry1 < miny) \
miny = ry1; \
if (ry1 > maxy) \
maxy = ry1;
// do segment a -> top of texture
x1 = verts[3].x;
ry1 = verts[3].y;
x2 = verts[2].x;
y2 = verts[2].y;
if (ry1 < 0)
ry1 = 0;
if (ry1 >= vid.height)
ry1 = vid.height - 1;
if (y2 < 0)
y2 = 0;
if (y2 >= vid.height)
y2 = vid.height - 1;
rasterize_segment_tex(x1, ry1, x2, y2, 0, pSplat->size - 1, 0, 0);
if (ry1 < miny)
miny = ry1;
if (ry1 > maxy)
maxy = ry1;
RASTERPARAMS(3,2,0,pSplat->width-1,0,0);
// do segment b -> right side of texture
x1 = x2;
ry1 = y2;
x2 = verts[1].x;
y2 = verts[1].y;
if (ry1 < 0)
ry1 = 0;
if (ry1 >= vid.height)
ry1 = vid.height - 1;
if (y2 < 0)
y2 = 0;
if (y2 >= vid.height)
y2 = vid.height - 1;
rasterize_segment_tex(x1, ry1, x2, y2, 0, pSplat->size - 1, pSplat->size - 1, 1);
if (ry1 < miny)
miny = ry1;
if (ry1 > maxy)
maxy = ry1;
RASTERPARAMS(2,1,0,pSplat->width-1,pSplat->height-1,0);
// do segment c -> bottom of texture
x1 = x2;
ry1 = y2;
x2 = verts[0].x;
y2 = verts[0].y;
if (ry1 < 0)
ry1 = 0;
if (ry1 >= vid.height)
ry1 = vid.height - 1;
if (y2 < 0)
y2 = 0;
if (y2 >= vid.height)
y2 = vid.height - 1;
rasterize_segment_tex(x1, ry1, x2, y2, pSplat->size - 1, 0, pSplat->size - 1, 0);
if (ry1 < miny)
miny = ry1;
if (ry1 > maxy)
maxy = ry1;
RASTERPARAMS(1,0,pSplat->width-1,0,pSplat->height-1,0);
// do segment d -> left side of texture
x1 = x2;
ry1 = y2;
x2 = verts[3].x;
y2 = verts[3].y;
if (ry1 < 0)
ry1 = 0;
if (ry1 >= vid.height)
ry1 = vid.height - 1;
if (y2 < 0)
y2 = 0;
if (y2 >= vid.height)
y2 = vid.height - 1;
rasterize_segment_tex(x1, ry1, x2, y2, pSplat->size - 1, 0, 0, 1);
if (ry1 < miny)
miny = ry1;
if (ry1 > maxy)
maxy = ry1;
RASTERPARAMS(0,3,pSplat->width-1,0,0,1);
ds_source = pSplat->pic;
ds_flatwidth = pSplat->width;
ds_flatheight = pSplat->height;
if (R_CheckPowersOfTwo())
R_CheckFlatLength(ds_flatwidth * ds_flatheight);
ds_transmap = NULL;
if (vis->transmap)
{
ds_transmap = vis->transmap;
spanfunctype = SPANDRAWFUNC_TRANSSPRITE;
}
if (ds_powersoftwo)
spanfunc = spanfuncs[spanfunctype];
else
spanfunc = spanfuncs_npo2[spanfunctype];
if (pSplat->angle)
{
memset(cachedheight, 0, sizeof(cachedheight));
angle = (viewangle + pSplat->angle - ANGLE_90) >> ANGLETOFINESHIFT;
basexscale = FixedDiv(FINECOSINE(angle), centerxfrac);
baseyscale = -FixedDiv(FINESINE(angle), centerxfrac);
}
else
{
angle = (viewangle - ANGLE_90) >> ANGLETOFINESHIFT;
basexscale = FixedDiv(FINECOSINE(angle), centerxfrac);
baseyscale = -FixedDiv(FINESINE(angle), centerxfrac);
}
#ifndef FLOORSPLATSOLIDCOLOR
// prepare values for all the splat
ds_source = W_CacheLumpNum(pSplat->pic, PU_CACHE);
planeheight = abs(pSplat->z - viewz);
light = (pSplat->subsector->sector->lightlevel >> LIGHTSEGSHIFT);
if (light >= LIGHTLEVELS)
light = LIGHTLEVELS - 1;
if (light < 0)
light = 0;
planezlight = zlight[light];
if (maxy >= vid.height)
maxy = vid.height-1;
for (y = miny; y <= maxy; y++)
{
@ -472,7 +266,7 @@ static void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, UINT8 *pTe
if (x2 >= vid.width)
x2 = vid.width - 1;
angle = (currentplane->viewangle + currentplane->plangle)>>ANGLETOFINESHIFT;
angle = (viewangle + pSplat->angle)>>ANGLETOFINESHIFT;
planecos = FINECOSINE(angle);
planesin = FINESINE(angle);
@ -480,146 +274,115 @@ static void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, UINT8 *pTe
{
cachedheight[y] = planeheight;
distance = cacheddistance[y] = FixedMul(planeheight, yslope[y]);
ds_xstep = cachedxstep[y] = FixedMul(distance,basexscale);
ds_ystep = cachedystep[y] = FixedMul(distance,baseyscale);
xstep = cachedxstep[y] = FixedMul(distance, basexscale);
ystep = cachedystep[y] = FixedMul(distance, baseyscale);
// don't divide by zero
if ((span = abs(centery-y)))
{
ds_xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span;
ds_ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span;
xstep = cachedxstep[y] = FixedMul(planesin, planeheight) / span;
ystep = cachedystep[y] = FixedMul(planecos, planeheight) / span;
}
}
else
{
distance = cacheddistance[y];
ds_xstep = cachedxstep[y];
ds_ystep = cachedystep[y];
xstep = cachedxstep[y];
ystep = cachedystep[y];
}
ds_xfrac = xoffs + FixedMul(planecos, distance) + (x1 - centerx) * ds_xstep;
ds_yfrac = yoffs - FixedMul(planesin, distance) + (x1 - centerx) * ds_ystep;
ds_xfrac -= offsetx;
ds_yfrac += offsety;
ds_xstep = FixedDiv(xstep, pSplat->xscale);
ds_ystep = FixedDiv(ystep, pSplat->yscale);
indexr = distance >> LIGHTZSHIFT;
if (indexr >= MAXLIGHTZ)
indexr = MAXLIGHTZ - 1;
ds_colormap = planezlight[indexr];
ds_colormap = vis->colormap;
ds_translation = R_GetSpriteTranslation(vis);
if (ds_translation == NULL)
ds_translation = colormaps;
ds_y = y;
if (x2 >= x1) // sanity check
if (vis->extra_colormap)
{
ds_x1 = x1;
ds_x2 = x2;
ds_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
(spanfuncs[SPANDRAWFUNC_SPLAT])();
if (!ds_colormap)
ds_colormap = vis->extra_colormap->colormap;
else
ds_colormap = &vis->extra_colormap->colormap[ds_colormap - colormaps];
}
// reset for next calls to edge rasterizer
rastertab[y].minx = INT32_MAX;
rastertab[y].maxx = INT32_MIN;
}
#else
for (y = miny; y <= maxy; y++)
{
x1 = rastertab[y].minx>>FRACBITS;
x2 = rastertab[y].maxx>>FRACBITS;
if (x1 < 0)
x1 = 0;
if (x2 >= vid.width)
x2 = vid.width - 1;
// pDest = ylookup[y] + columnofs[x1];
pDest = &topleft[y*vid.width + x1];
x = x2 - x1 + 1;
// starting point of the texture
tx = rastertab[y].tx1;
ty = rastertab[y].ty1;
// HORRIBLE BUG!!!
if (x > 0)
if (pSplat->angle)
{
tdx = (rastertab[y].tx2 - tx) / x;
tdy = (rastertab[y].ty2 - ty) / x;
// Add the view offset, rotated by the plane angle.
fixed_t a = -pSplat->verts[0].x + viewx;
fixed_t b = -pSplat->verts[0].y + viewy;
angle = (pSplat->angle >> ANGLETOFINESHIFT);
offsetx = FixedMul(a, FINECOSINE(angle)) - FixedMul(b,FINESINE(angle));
offsety = -FixedMul(a, FINESINE(angle)) - FixedMul(b,FINECOSINE(angle));
}
else
{
offsetx = viewx - pSplat->verts[0].x;
offsety = pSplat->verts[0].y - viewy;
}
while (x-- > 0)
if (vis != NULL)
{
INT32 xclip;
mfloorclip = vis->clipbot;
mceilingclip = vis->cliptop;
R_ClipVisSprite(vis, x1-1, x2+1, drawsegs, NULL);
memset(ds_splatclip, 0, sizeof(ds_splatclip));
if (x2 >= x1 && x1 < viewwidth && x1 >= 0)
{
*(pDest++) = (UINT8)(y&1);
tx += tdx;
ty += tdy;
for (xclip = x1; xclip <= x2; xclip++)
{
if (y >= mfloorclip[xclip])
ds_splatclip[xclip] = 1;
}
}
while (ds_splatclip[x1])
x1++;
i = x2;
while (i > x1)
{
if (ds_splatclip[i])
x2 = i-1;
i--;
}
}
// reinitialise the minimum and maximum for the next approach
ds_xfrac = FixedDiv(offsetx + FixedMul(planecos, distance) + (x1 - centerx) * xstep, pSplat->xscale);
ds_yfrac = FixedDiv(offsety - FixedMul(planesin, distance) + (x1 - centerx) * ystep, pSplat->yscale);
if (x2 >= x1)
{
ds_y = y;
ds_x1 = x1;
ds_x2 = x2;
spanfunc();
}
rastertab[y].minx = INT32_MAX;
rastertab[y].maxx = INT32_MIN;
}
#endif
}
// --------------------------------------------------------------------------
// R_DrawVisibleFloorSplats
// draw the flat floor/ceiling splats
// --------------------------------------------------------------------------
void R_DrawVisibleFloorSplats(void)
{
floorsplat_t *pSplat;
INT32 iCount = 0, i;
fixed_t tr_x, tr_y, rot_x, rot_y, rot_z, xscale, yscale;
vertex_t *v3d;
vertex_t v2d[4];
pSplat = visfloorsplats;
while (pSplat)
if (pSplat->angle)
{
iCount++;
// Draw a floor splat
// 3--2
// | |
// 0--1
rot_z = pSplat->z - viewz;
for (i = 0; i < 4; i++)
{
v3d = &pSplat->verts[i];
// transform the origin point
tr_x = v3d->x - viewx;
tr_y = v3d->y - viewy;
// rotation around vertical y axis
rot_x = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos);
rot_y = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin);
if (rot_y < 4*FRACUNIT)
goto skipit;
// note: y from view above of map, is distance far away
xscale = FixedDiv(projection, rot_y);
yscale = -FixedDiv(projectiony, rot_y);
// projection
v2d[i].x = (centerxfrac + FixedMul (rot_x, xscale))>>FRACBITS;
v2d[i].y = (centeryfrac + FixedMul (rot_z, yscale))>>FRACBITS;
}
R_RenderFloorSplat(pSplat, v2d, NULL);
skipit:
pSplat = pSplat->nextvis;
memset(cachedheight, 0, sizeof(cachedheight));
angle = (viewangle - ANGLE_90) >> ANGLETOFINESHIFT;
basexscale = FixedDiv(FINECOSINE(angle), centerxfrac);
baseyscale = -FixedDiv(FINESINE(angle), centerxfrac);
}
}
static void prepare_rastertab(void)
{
INT32 iLine;
for (iLine = 0; iLine < vid.height; iLine++)
INT32 i;
prastertab = rastertab;
for (i = 0; i < vid.height; i++)
{
rastertab[iLine].minx = INT32_MAX;
rastertab[iLine].maxx = INT32_MIN;
rastertab[i].minx = INT32_MAX;
rastertab[i].maxx = INT32_MIN;
}
}

View File

@ -14,68 +14,35 @@
#define __R_SPLATS_H__
#include "r_defs.h"
//#define WALLSPLATS // comment this out to compile without splat effects
/*#ifdef USEASM
#define FLOORSPLATS
#endif*/
#define MAXLEVELSPLATS 1024
// splat flags
#define SPLATDRAWMODE_MASK 0x03 // mask to get drawmode from flags
#define SPLATDRAWMODE_OPAQUE 0x00
#define SPLATDRAWMODE_SHADE 0x01
#define SPLATDRAWMODE_TRANS 0x02
#include "r_things.h"
// ==========================================================================
// DEFINITIONS
// ==========================================================================
// WALL SPLATS are patches drawn on top of wall segs
typedef struct wallsplat_s
struct rastery_s
{
lumpnum_t patch; // lump id.
vertex_t v1, v2; // vertices along the linedef
fixed_t top;
fixed_t offset; // offset in columns<<FRACBITS from start of linedef to start of splat
INT32 flags;
fixed_t *yoffset;
line_t *line; // the parent line of the splat seg
struct wallsplat_s *next;
} wallsplat_t;
fixed_t minx, maxx; // for each raster line starting at line 0
fixed_t tx1, ty1; // start points in texture at this line
fixed_t tx2, ty2; // end points in texture at this line
};
extern struct rastery_s *prastertab; // for ASM code
// FLOOR SPLATS are pic_t (raw horizontally stored) drawn on top of the floor or ceiling
#ifdef FLOORSPLATS
typedef struct floorsplat_s
{
lumpnum_t pic; // a pic_t lump id
INT32 flags;
INT32 size; // 64, 128, 256, etc.
vertex_t verts[4]; // (x,y) as viewn from above on map
fixed_t z; // z (height) is constant for all the floorsplats
subsector_t *subsector; // the parent subsector
UINT8 *pic;
INT32 width, height;
fixed_t scale, xscale, yscale;
angle_t angle;
vertex_t verts[4]; // (x,y) as viewed from above on map
fixed_t x, y, z; // position
mobj_t *mobj; // Mobj it is tied to
struct floorsplat_s *next;
struct floorsplat_s *nextvis;
} floorsplat_t;
// p_setup.c
fixed_t P_SegLength(seg_t *seg);
// call at P_SetupLevel()
void R_ClearLevelSplats(void);
#ifdef WALLSPLATS
void R_AddWallSplat(line_t *wallline, INT16 sectorside, const char *patchname, fixed_t top,
fixed_t wallfrac, INT32 flags);
void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, vissprite_t *vis);
extern UINT8 ds_splatclip[MAXVIDWIDTH];
#endif
#ifdef FLOORSPLATS
void R_AddFloorSplat(subsector_t *subsec, mobj_t *mobj, const char *picname, fixed_t x, fixed_t y, fixed_t z,
INT32 flags);
#endif
void R_ClearVisibleFloorSplats(void);
void R_AddVisibleFloorSplats(subsector_t *subsec);
void R_DrawVisibleFloorSplats(void);
#endif /*__R_SPLATS_H__*/

File diff suppressed because it is too large Load Diff

View File

@ -65,7 +65,6 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
void R_AddSprites(sector_t *sec, INT32 lightlevel);
void R_InitSprites(void);
void R_ClearSprites(void);
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
boolean R_ThingVisible (mobj_t *thing);
@ -76,6 +75,15 @@ boolean R_ThingVisibleWithinDist (mobj_t *thing,
boolean R_PrecipThingVisible (precipmobj_t *precipthing,
fixed_t precip_draw_dist);
boolean R_ThingHorizontallyFlipped (mobj_t *thing);
boolean R_ThingVerticallyFlipped (mobj_t *thing);
boolean R_ThingIsPaperSprite (mobj_t *thing);
boolean R_ThingIsFloorSprite (mobj_t *thing);
boolean R_ThingIsFullBright (mobj_t *thing);
boolean R_ThingIsFullDark (mobj_t *thing);
// --------------
// MASKED DRAWING
// --------------
@ -108,19 +116,23 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks);
typedef enum
{
// actual cuts
SC_NONE = 0,
SC_TOP = 1,
SC_BOTTOM = 1<<1,
SC_NONE = 0,
SC_TOP = 1,
SC_BOTTOM = 1<<1,
// other flags
SC_PRECIP = 1<<2,
SC_LINKDRAW = 1<<3,
SC_PRECIP = 1<<2,
SC_LINKDRAW = 1<<3,
SC_FULLBRIGHT = 1<<4,
SC_VFLIP = 1<<5,
SC_ISSCALED = 1<<6,
SC_SHADOW = 1<<7,
SC_FULLDARK = 1<<5,
SC_VFLIP = 1<<6,
SC_ISSCALED = 1<<7,
SC_ISROTATED = 1<<8,
SC_SHADOW = 1<<9,
SC_SHEAR = 1<<10,
SC_SPLAT = 1<<11,
// masks
SC_CUTMASK = SC_TOP|SC_BOTTOM,
SC_FLAGMASK = ~SC_CUTMASK
SC_CUTMASK = SC_TOP|SC_BOTTOM,
SC_FLAGMASK = ~SC_CUTMASK
} spritecut_e;
// A vissprite_t is a thing that will be drawn during a refresh,
@ -177,6 +189,10 @@ typedef struct vissprite_s
INT16 sz, szt;
spritecut_e cut;
UINT32 renderflags;
UINT8 rotateflags;
fixed_t shadowscale;
INT16 clipbot[MAXVIDWIDTH], cliptop[MAXVIDWIDTH];
@ -185,6 +201,12 @@ typedef struct vissprite_s
extern UINT32 visspritecount;
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal);
boolean R_SpriteIsFlashing(vissprite_t *vis);
UINT8 *R_GetSpriteTranslation(vissprite_t *vis);
// ----------
// DRAW NODES
// ----------

View File

@ -124,6 +124,8 @@ void SCR_SetDrawFuncs(void)
spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8;
spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8;
spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8;
spanfuncs[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_8;
spanfuncs[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_8;
spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8;
#ifndef NOWATER
spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8;
@ -140,6 +142,8 @@ void SCR_SetDrawFuncs(void)
spanfuncs_npo2[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_SPRITE] = R_DrawFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_TRANSSPRITE] = R_DrawTranslucentFloorSprite_NPO2_8;
spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed
#ifndef NOWATER
spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8;

View File

@ -142,6 +142,8 @@ enum
SPANDRAWFUNC_TRANS,
SPANDRAWFUNC_SPLAT,
SPANDRAWFUNC_TRANSSPLAT,
SPANDRAWFUNC_SPRITE,
SPANDRAWFUNC_TRANSSPRITE,
SPANDRAWFUNC_FOG,
#ifndef NOWATER
SPANDRAWFUNC_WATER,

View File

@ -763,8 +763,8 @@ TX2 EQU 16
TY2 EQU 20
RASTERY_SIZEOF EQU 24
cglobal rasterize_segment_tex
rasterize_segment_tex:
cglobal rasterize_segment_tex_asm
rasterize_segment_tex_asm:
push ebp
mov ebp,esp