diff --git a/src/d_clisrv.c b/src/d_clisrv.c index c9490410b..3db5a6207 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -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)) diff --git a/src/d_clisrv.h b/src/d_clisrv.h index adc8a7cc9..0ed0b10f5 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -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 diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 6f4bcdb1d..7e0c84584 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -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); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 897c28968..3cd4b33c5 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -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; diff --git a/src/dehacked.c b/src/dehacked.c index 80a0ad0ff..92a8ffe4e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -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}, diff --git a/src/doomdef.h b/src/doomdef.h index d0b7ea0c2..98a22e5ab 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -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 diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index fe0aa2f35..cfcad29d0 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -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) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 335e6cfbc..7b290bf3f 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -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<flip & (1<flip & (1<flip & (1<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; diff --git a/src/p_mobj.c b/src/p_mobj.c index de4385fa7..827650ce6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -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)) diff --git a/src/p_mobj.h b/src/p_mobj.h index 27a6ef4f0..eb8a9ccc2 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -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; diff --git a/src/p_saveg.c b/src/p_saveg.c index 4f6f31803..d613efd70 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -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) { diff --git a/src/p_setup.c b/src/p_setup.c index 4dbb70e0c..349b0582d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -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(); diff --git a/src/p_user.c b/src/p_user.c index 7bc45bfc4..0341128d5 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -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 diff --git a/src/r_bsp.c b/src/r_bsp.c index a430ef040..d2c8e9f86 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -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. diff --git a/src/r_defs.h b/src/r_defs.h index 4dfba0691..d32313a46 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -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; diff --git a/src/r_draw.c b/src/r_draw.c index 2b798c3bf..e10d6e399 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -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; diff --git a/src/r_draw.h b/src/r_draw.h index 1ca22f18a..d77bbedd3 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -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 diff --git a/src/r_draw8.c b/src/r_draw8.c index 940ea724b..bc39e91a5 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -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! + // + // 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. */ diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c index 020155694..087a8d30c 100644 --- a/src/r_draw8_npo2.c +++ b/src/r_draw8_npo2.c @@ -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. */ diff --git a/src/r_main.c b/src/r_main.c index 3568e2116..03f9c6818 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -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 diff --git a/src/r_patch.c b/src/r_patch.c index 9ca04dd55..9b1e7d1b8 100644 --- a/src/r_patch.c +++ b/src/r_patch.c @@ -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. diff --git a/src/r_patch.h b/src/r_patch.h index 6991d3637..32bcb3909 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -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__ diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 98e3a7687..123c4eef2 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -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]; diff --git a/src/r_plane.c b/src/r_plane.c index 6c238896c..797919a9f 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -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) diff --git a/src/r_segs.c b/src/r_segs.c index 177827892..77425d345 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -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<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)<>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 diff --git a/src/r_splats.c b/src/r_splats.c index dfec185a1..0b2826107 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -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)<>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)<splats; - while (p_splat->next) + count = (y1-y2)+1; + + dx0 = FixedDiv((x1-x2)<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<verts[2].x = splat->verts[1].x = x + ((splat->size-1)<verts[3].y = splat->verts[2].y = y + ((splat->size-1)<verts[0].y = splat->verts[1].y = y - (splat->size<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)<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; } } diff --git a/src/r_splats.h b/src/r_splats.h index 4ad893abb..9c01084cf 100644 --- a/src/r_splats.h +++ b/src/r_splats.h @@ -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<cut & SC_PRECIP) + && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) + && (vis->mobj->flags2 & MF2_FRET) + && !(vis->mobj->flags & MF_GRENADEBOUNCE) + && (leveltime & 1)); +} + +UINT8 *R_GetSpriteTranslation(vissprite_t *vis) +{ + if (R_SpriteIsFlashing(vis)) // Bosses "flash" + { + if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) + return R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); + else if (vis->mobj->type == MT_METALSONIC_BATTLE) + return R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); + else + return R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); + } + else if (vis->mobj->color && vis->transmap) // Color mapping + { + if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) + return R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + else if (!(vis->cut & SC_PRECIP) + && vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD + && (vis->mobj->player->charflags & SF_DASHMODE) + && ((leveltime/2) & 1)) + { + if (vis->mobj->player->charflags & SF_MACHINE) + return R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); + else + return R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + } + else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> + { + size_t skinnum = (skin_t*)vis->mobj->skin-skins; + return R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); + } + else // Use the defaults + return R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); + } + else if (vis->mobj->color) + { + // New colormap stuff for skins Tails 06-07-2002 + if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) + return R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + else if (!(vis->cut & SC_PRECIP) + && vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD + && (vis->mobj->player->charflags & SF_DASHMODE) + && ((leveltime/2) & 1)) + { + if (vis->mobj->player->charflags & SF_MACHINE) + return R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); + else + return R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + } + else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! + { + size_t skinnum = (skin_t*)vis->mobj->skin-skins; + return R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); + } + else // Use the defaults + return R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); + } + else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome. + return R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE); + + return NULL; +} + // // R_DrawVisSprite // mfloorclip and mceilingclip should also be set. @@ -770,77 +845,24 @@ static void R_DrawVisSprite(vissprite_t *vis) colfunc = colfuncs[BASEDRAWFUNC]; // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; - if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" - { - // translate certain pixels to white - colfunc = colfuncs[COLDRAWFUNC_TRANS]; - if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) - dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); - else if (vis->mobj->type == MT_METALSONIC_BATTLE) - dc_translation = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); - else - dc_translation = R_GetTranslationColormap(TC_BOSS, 0, GTC_CACHE); - } + dc_translation = R_GetSpriteTranslation(vis); + + if (R_SpriteIsFlashing(vis)) // Bosses "flash" + colfunc = colfuncs[COLDRAWFUNC_TRANS]; // translate certain pixels to white else if (vis->mobj->color && vis->transmap) // Color mapping { colfunc = colfuncs[COLDRAWFUNC_TRANSTRANS]; dc_transmap = vis->transmap; - if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) - dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - else if (!(vis->cut & SC_PRECIP) - && vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD - && (vis->mobj->player->charflags & SF_DASHMODE) - && ((leveltime/2) & 1)) - { - if (vis->mobj->player->charflags & SF_MACHINE) - dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); - else - dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - } - else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> - { - size_t skinnum = (skin_t*)vis->mobj->skin-skins; - dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); - } - else // Use the defaults - dc_translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); } else if (vis->transmap) { colfunc = colfuncs[COLDRAWFUNC_FUZZY]; dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table } - else if (vis->mobj->color) - { - // translate green skin to another color + else if (vis->mobj->color) // translate green skin to another color colfunc = colfuncs[COLDRAWFUNC_TRANS]; - - // New colormap stuff for skins Tails 06-07-2002 - if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) - dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - else if (!(vis->cut & SC_PRECIP) - && vis->mobj->player && vis->mobj->player->dashmode >= DASHMODE_THRESHOLD - && (vis->mobj->player->charflags & SF_DASHMODE) - && ((leveltime/2) & 1)) - { - if (vis->mobj->player->charflags & SF_MACHINE) - dc_translation = R_GetTranslationColormap(TC_DASHMODE, 0, GTC_CACHE); - else - dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - } - else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! - { - size_t skinnum = (skin_t*)vis->mobj->skin-skins; - dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); - } - else // Use the defaults - dc_translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); - } else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome. - { colfunc = colfuncs[COLDRAWFUNC_TRANS]; - dc_translation = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE); - } if (vis->extra_colormap) { @@ -923,6 +945,28 @@ static void R_DrawVisSprite(vissprite_t *vis) localcolfunc (column); } } + else if (vis->cut & SC_SHEAR) + { +#ifdef RANGECHECK + pwidth = SHORT(patch->width); +#endif + + // Vertically sheared sprite + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, dc_texturemid -= vis->shear.tan) + { +#ifdef RANGECHECK + texturecolumn = frac>>FRACBITS; + if (texturecolumn < 0 || texturecolumn >= pwidth) + I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); +#else + column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS])); +#endif + + sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); + localcolfunc (column); + } + } else { #ifdef RANGECHECK @@ -1217,6 +1261,29 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) #undef CHECKZ } +static void R_SkewShadowSprite( + mobj_t *thing, pslope_t *groundslope, + fixed_t groundz, INT32 spriteheight, fixed_t scalemul, + fixed_t *shadowyscale, fixed_t *shadowskew) +{ + // haha let's try some dumb stuff + fixed_t xslope, zslope; + angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - groundslope->xydirection) >> ANGLETOFINESHIFT; + + xslope = FixedMul(FINESINE(sloperelang), groundslope->zdelta); + zslope = FixedMul(FINECOSINE(sloperelang), groundslope->zdelta); + + //CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope); + + if (viewz < groundz) + *shadowyscale += FixedMul(FixedMul(thing->radius*2 / spriteheight, scalemul), zslope); + else + *shadowyscale -= FixedMul(FixedMul(thing->radius*2 / spriteheight, scalemul), zslope); + + *shadowyscale = abs((*shadowyscale)); + *shadowskew = xslope; +} + static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz) { vissprite_t *shadow; @@ -1245,40 +1312,22 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, yscale = FixedDiv(projectiony, tz); shadowxscale = FixedMul(thing->radius*2, scalemul); shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz)); - shadowyscale = min(shadowyscale, shadowxscale) / SHORT(patch->height); - shadowxscale /= SHORT(patch->width); + shadowyscale = min(shadowyscale, shadowxscale) / patch->height; + shadowxscale /= patch->width; shadowskew = 0; if (groundslope) - { - // haha let's try some dumb stuff - fixed_t xslope, zslope; - angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - groundslope->xydirection) >> ANGLETOFINESHIFT; + R_SkewShadowSprite(thing, groundslope, groundz, patch->height, scalemul, &shadowyscale, &shadowskew); - xslope = FixedMul(FINESINE(sloperelang), groundslope->zdelta); - zslope = FixedMul(FINECOSINE(sloperelang), groundslope->zdelta); - - //CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope); - - if (viewz < groundz) - shadowyscale += FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope); - else - shadowyscale -= FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope); - - shadowyscale = abs(shadowyscale); - - shadowskew = xslope; - } - - tx -= SHORT(patch->width) * shadowxscale/2; + tx -= patch->width * shadowxscale/2; x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; if (x1 >= viewwidth) return; - tx += SHORT(patch->width) * shadowxscale; + tx += patch->width * shadowxscale; x2 = ((centerxfrac + FixedMul(tx,xscale))>>FRACBITS); x2--; if (x2 < 0 || x2 <= x1) return; - if (shadowyscale < FRACUNIT/SHORT(patch->height)) return; // fix some crashes? + if (shadowyscale < FRACUNIT/patch->height) return; // fix some crashes? shadow = R_NewVisSprite(); shadow->patch = patch; @@ -1293,8 +1342,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, shadow->dispoffset = vis->dispoffset - 5; shadow->gx = thing->x; shadow->gy = thing->y; - shadow->gzt = (isflipped ? shadow->pzt : shadow->pz) + SHORT(patch->height) * shadowyscale / 2; - shadow->gz = shadow->gzt - SHORT(patch->height) * shadowyscale; + shadow->gzt = (isflipped ? shadow->pzt : shadow->pz) + patch->height * shadowyscale / 2; + shadow->gz = shadow->gzt - patch->height * shadowyscale; shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) shadow->texturemid = FixedMul(shadow->texturemid, ((skin_t *)thing->skin)->highresscale); @@ -1315,7 +1364,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, shadow->startfrac = 0; //shadow->xiscale = 0x7ffffff0 / (shadow->xscale/2); - shadow->xiscale = (SHORT(patch->width)<xiscale = (patch->width<x1 > x1) shadow->startfrac += shadow->xiscale*(shadow->x1-x1); @@ -1374,13 +1423,15 @@ static void R_ProjectSprite(mobj_t *thing) size_t frame, 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 lindex; + INT32 trans; vissprite_t *vis; + patch_t *patch; spritecut_e cut = SC_NONE; @@ -1389,10 +1440,15 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t scalestep; fixed_t offset, offset2; + fixed_t sheartan = 0; + fixed_t shadowscale = FRACUNIT; fixed_t basetx; // drop shadows - boolean papersprite = !!(thing->frame & FF_PAPERSPRITE); - fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; + boolean shadowdraw, shadoweffects, shadowskew; + boolean splat = R_ThingIsFloorSprite(thing); + boolean papersprite = (R_ThingIsPaperSprite(thing) && !splat); + fixed_t paperoffset = 0, paperdistance = 0; + angle_t centerangle = 0; INT32 dispoffset = thing->info->dispoffset; @@ -1401,10 +1457,12 @@ static void R_ProjectSprite(mobj_t *thing) INT32 heightsec, phs; INT32 light = 0; fixed_t this_scale = thing->scale; + fixed_t spritexscale, spriteyscale; // rotsprite fixed_t spr_width, spr_height; fixed_t spr_offset, spr_topoffset; + #ifdef ROTSPRITE patch_t *rotsprite = NULL; INT32 rollangle = 0; @@ -1533,17 +1591,28 @@ static void R_ProjectSprite(mobj_t *thing) spr_offset = spritecachedinfo[lump].offset; spr_topoffset = spritecachedinfo[lump].topoffset; + //Fab: lumppat is the lump number of the patch to use, this is different + // than lumpid for sprites-in-pwad : the graphics are patched + patch = W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); + #ifdef ROTSPRITE - if (thing->rollangle) + if (thing->rollangle + && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { 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; + patch = rotsprite; + cut |= SC_ISROTATED; + + 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; } @@ -1553,12 +1622,18 @@ static void R_ProjectSprite(mobj_t *thing) flip = !flip != !hflip; // calculate edges of the shape + spritexscale = thing->spritexscale; + spriteyscale = thing->spriteyscale; + if (spritexscale < 1 || spriteyscale < 1) + return; + if (flip) offset = spr_offset - spr_width; else offset = -spr_offset; - offset = FixedMul(offset, this_scale); - offset2 = FixedMul(spr_width, this_scale); + + offset = FixedMul(offset, FixedMul(spritexscale, this_scale)); + offset2 = FixedMul(spr_width, FixedMul(spritexscale, this_scale)); if (papersprite) { @@ -1686,7 +1761,7 @@ static void R_ProjectSprite(mobj_t *thing) dispoffset *= -1; // if it's physically behind, make sure it's ordered behind (if dispoffset > 0) sortscale = linkscale; // now make sure it's linked - cut = SC_LINKDRAW; + cut |= SC_LINKDRAW; } // PORTAL SPRITE CLIPPING @@ -1699,19 +1774,87 @@ static void R_ProjectSprite(mobj_t *thing) return; } - //SoM: 3/17/2000: Disregard sprites that are out of view.. - if (vflip) - { - // When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned. - // sprite height - sprite topoffset is the proper inverse of the vertical offset, of course. - // remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes! - gz = oldthing->z + oldthing->height - FixedMul(spr_topoffset, this_scale); - gzt = gz + FixedMul(spr_height, this_scale); - } + // Determine the translucency value. + if (oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) + trans = tr_trans80; // because now the translucency is set through FF_TRANSMASK + else if (oldthing->frame & FF_TRANSMASK) + trans = (oldthing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; else + trans = 0; + + // Check if this sprite needs to be rendered like a shadow + shadowdraw = (!!(thing->renderflags & RF_SHADOWDRAW) && !(papersprite || splat)); + shadoweffects = (thing->renderflags & RF_SHADOWEFFECTS); + shadowskew = (shadowdraw && thing->standingslope); + + if (shadowdraw || shadoweffects) { - gzt = oldthing->z + FixedMul(spr_topoffset, this_scale); - gz = gzt - FixedMul(spr_height, this_scale); + fixed_t groundz = R_GetShadowZ(thing, NULL); + boolean isflipped = (thing->eflags & MFE_VERTICALFLIP); + + if (shadoweffects) + { + mobj_t *caster = thing->target; + + if (caster && !P_MobjWasRemoved(caster)) + { + fixed_t floordiff; + + if (abs(groundz-viewz)/tz > 4) + return; // Prevent stretchy shadows and possible crashes + + floordiff = abs((isflipped ? caster->height : 0) + caster->z - groundz); + trans += ((floordiff / (100*FRACUNIT)) + 3); + shadowscale = FixedMul(FRACUNIT - floordiff/640, caster->scale); + } + else + trans += 3; + + if (trans >= 9) + return; + + trans--; + } + + if (shadowdraw) + { + spritexscale = FixedMul(thing->radius * 2, shadowscale); + spriteyscale = FixedMul(thing->radius * 2, shadowscale); + spriteyscale = FixedMul(spriteyscale, FixedDiv(abs(groundz - viewz), tz)); + spriteyscale = min(spriteyscale, spritexscale) / patch->height; + } + else + spritexscale = spriteyscale = shadowscale; + + spritexscale /= patch->width; + + if (shadowskew) + { + R_SkewShadowSprite(thing, thing->standingslope, groundz, patch->height, shadowscale, &spriteyscale, &sheartan); + + gzt = (isflipped ? (thing->z + thing->height) : thing->z) + patch->height * spriteyscale / 2; + gz = gzt - patch->height * spriteyscale; + + cut |= SC_SHEAR; + } + } + + if (!shadowskew) + { + //SoM: 3/17/2000: Disregard sprites that are out of view.. + if (vflip) + { + // When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned. + // sprite height - sprite topoffset is the proper inverse of the vertical offset, of course. + // remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes! + gz = oldthing->z + oldthing->height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); + gzt = gz + FixedMul(spr_height, FixedMul(spriteyscale, this_scale)); + } + else + { + gzt = oldthing->z + FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale)); + gz = gzt - FixedMul(spr_height, FixedMul(spriteyscale, this_scale)); + } } if (thing->subsector->sector->cullheight) @@ -1764,9 +1907,10 @@ static void R_ProjectSprite(mobj_t *thing) // store information in a vissprite vis = R_NewVisSprite(); + vis->renderflags = thing->renderflags; + vis->rotateflags = sprframe->rotate; vis->heightsec = heightsec; //SoM: 3/17/2000 vis->mobjflags = thing->flags; - vis->scale = yscale; //<sortscale = sortscale; vis->dispoffset = dispoffset; // Monster Iestyn: 23/11/15 vis->gx = thing->x; @@ -1776,12 +1920,12 @@ static void R_ProjectSprite(mobj_t *thing) vis->thingheight = thing->height; vis->pz = thing->z; vis->pzt = vis->pz + vis->thingheight; - vis->texturemid = vis->gzt - viewz; + vis->texturemid = FixedDiv(gzt - viewz, spriteyscale); vis->scalestep = scalestep; vis->paperoffset = paperoffset; vis->paperdistance = paperdistance; vis->centerangle = centerangle; - vis->shear.tan = 0; + vis->shear.tan = sheartan; vis->shear.offset = 0; vis->mobj = thing; // Easy access! Tails 06-07-2002 @@ -1789,17 +1933,28 @@ static void R_ProjectSprite(mobj_t *thing) vis->x1 = x1 < portalclipstart ? portalclipstart : x1; vis->x2 = x2 >= portalclipend ? portalclipend-1 : x2; - vis->xscale = xscale; //SoM: 4/17/2000 vis->sector = thing->subsector->sector; vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, sortscale))>>FRACBITS); vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, sortscale))>>FRACBITS); vis->cut = cut; + if (thing->subsector->sector->numlights) vis->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap; else vis->extra_colormap = thing->subsector->sector->extra_colormap; - iscale = FixedDiv(FRACUNIT, xscale); + vis->xscale = FixedMul(spritexscale, xscale); //SoM: 4/17/2000 + vis->scale = FixedMul(spriteyscale, yscale); //<width<shear.offset = vis->x1-x1; + vis->shadowscale = shadowscale; + } + else + iscale = FixedDiv(FRACUNIT, vis->xscale); if (flip) { @@ -1818,14 +1973,7 @@ static void R_ProjectSprite(mobj_t *thing) vis->scale += scalestep*(vis->x1 - x1); } - //Fab: lumppat is the lump number of the patch to use, this is different - // than lumpid for sprites-in-pwad : the graphics are patched -#ifdef ROTSPRITE - if (rotsprite != NULL) - vis->patch = rotsprite; - else -#endif - vis->patch = W_CachePatchNum(sprframe->lumppat[rot], PU_SPRITE); + vis->patch = patch; // // determine the colormap (lightlevel & special effects) @@ -1835,13 +1983,13 @@ static void R_ProjectSprite(mobj_t *thing) // specific translucency if (!cv_translucency.value) ; // no translucency - else if (oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) - vis->transmap = transtables + ((tr_trans80-1)<frame & FF_TRANSMASK) - vis->transmap = transtables + (oldthing->frame & FF_TRANSMASK) - 0x10000; + else if (trans) + vis->transmap = transtables + ((trans-1)<frame & FF_FULLBRIGHT || oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) + if (R_ThingIsFullBright(oldthing) || oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) vis->cut |= SC_FULLBRIGHT; + else if (R_ThingIsFullDark(oldthing)) + vis->cut |= SC_FULLDARK; if (vis->cut & SC_FULLBRIGHT && (!vis->extra_colormap || !(vis->extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES))) @@ -1849,6 +1997,8 @@ static void R_ProjectSprite(mobj_t *thing) // full bright: goggles vis->colormap = colormaps; } + else if (vis->cut & SC_FULLDARK) + vis->colormap = scalelight[0][0]; else { // diminished light @@ -1862,8 +2012,10 @@ static void R_ProjectSprite(mobj_t *thing) if (vflip) vis->cut |= SC_VFLIP; + if (splat) + vis->cut |= SC_SPLAT; // I like ya cut g - if (thing->subsector->sector->numlights) + if (thing->subsector->sector->numlights && !(shadowdraw || splat)) R_SplitSprite(vis); if (oldthing->shadowscale && cv_shadow.value) @@ -2470,10 +2622,13 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps } else if (r2->sprite) { - if (r2->sprite->x1 > rover->x2 || r2->sprite->x2 < rover->x1) - continue; - if (r2->sprite->szt > rover->sz || r2->sprite->sz < rover->szt) - continue; + if (!(r2->sprite->cut & SC_SPLAT || rover->cut & SC_SPLAT)) + { + if (r2->sprite->x1 > rover->x2 || r2->sprite->x2 < rover->x1) + continue; + if (r2->sprite->szt > rover->sz || r2->sprite->sz < rover->szt) + continue; + } if (r2->sprite->sortscale > rover->sortscale || (r2->sprite->sortscale == rover->sortscale && r2->sprite->dispoffset > rover->dispoffset)) @@ -2552,6 +2707,146 @@ void R_InitDrawNodes(void) nodebankhead.next = nodebankhead.prev = &nodebankhead; } +static void R_DrawVisSplat(vissprite_t *spr) +{ +#ifdef FLOORSPLATS + floorsplat_t splat; + fixed_t tr_x, tr_y, rot_x, rot_y, rot_z; + vertex_t *v3d; + vertex_t v2d[4]; + fixed_t x, y; + fixed_t w, h; + angle_t splatangle, angle; + fixed_t ca, sa; + fixed_t xscale, yscale; + fixed_t xoffset, yoffset; + fixed_t leftoffset, topoffset; + boolean hflip = (spr->xiscale < 0); + boolean vflip = (spr->cut & SC_VFLIP); + UINT8 flipflags = 0; + vector2_t rotated[4]; + INT32 i; + + if (hflip) + flipflags |= PICFLAGS_XFLIP; + if (vflip) + flipflags |= PICFLAGS_YFLIP; + + Patch_GenerateFlat(spr->patch, flipflags); + splat.pic = spr->patch->flats[flipflags]; + if (splat.pic == NULL) + return; + + splat.mobj = spr->mobj; + splat.width = spr->patch->width; + splat.height = spr->patch->height; + splat.scale = spr->mobj->scale; + + if (spr->renderflags & RF_SHADOWEFFECTS) + splat.scale = FixedMul(splat.scale, spr->shadowscale); + + if (spr->rotateflags & SRF_3D || spr->renderflags & RF_NOSPLATBILLBOARD) + splatangle = spr->mobj->angle; + else + splatangle = viewangle; + + if (!(spr->cut & SC_ISROTATED)) + splatangle += spr->mobj->rollangle; + + splat.angle = -splatangle; + splat.angle += ANGLE_90; + + topoffset = (spr->patch->topoffset * FRACUNIT); + leftoffset = (spr->patch->leftoffset * FRACUNIT); + if (hflip) + leftoffset = ((splat.width * FRACUNIT) - leftoffset); + + xscale = spr->mobj->spritexscale; + yscale = spr->mobj->spriteyscale; + + splat.xscale = FixedMul(splat.scale, xscale); + splat.yscale = FixedMul(splat.scale, yscale); + + xoffset = FixedMul(leftoffset, splat.xscale); + yoffset = FixedMul(topoffset, splat.yscale); + + x = spr->mobj->x; + y = spr->mobj->y; + w = (splat.width * splat.xscale); + h = (splat.height * splat.yscale); + + splat.x = x; + splat.y = y; + splat.z = spr->mobj->z; + + // Set positions + + // 3--2 + // | | + // 0--1 + + splat.verts[0].x = w - xoffset; + splat.verts[0].y = yoffset; + + splat.verts[1].x = -xoffset; + splat.verts[1].y = yoffset; + + splat.verts[2].x = -xoffset; + splat.verts[2].y = -h + yoffset; + + splat.verts[3].x = w - xoffset; + splat.verts[3].y = -h + yoffset; + + angle = -splat.angle; + ca = FINECOSINE(angle>>ANGLETOFINESHIFT); + sa = FINESINE(angle>>ANGLETOFINESHIFT); + + // Rotate + for (i = 0; i < 4; i++) + { + rotated[i].x = FixedMul(splat.verts[i].x, ca) - FixedMul(splat.verts[i].y, sa); + rotated[i].y = FixedMul(splat.verts[i].x, sa) + FixedMul(splat.verts[i].y, ca); + } + + // Translate + for (i = 0; i < 4; i++) + { + splat.verts[i].x = rotated[i].x + x; + splat.verts[i].y = rotated[i].y + y; + } + + rot_z = splat.z - viewz; + + for (i = 0; i < 4; i++) + { + v3d = &splat.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 || rot_y < FixedDiv(4*FRACUNIT, splat.scale)) + return; + + // 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(&splat, v2d, spr); +#else + (void)spr; +#endif +} + // // R_DrawSprite // @@ -2562,7 +2857,11 @@ static void R_DrawSprite(vissprite_t *spr) { mfloorclip = spr->clipbot; mceilingclip = spr->cliptop; - R_DrawVisSprite(spr); + + if (spr->cut & SC_SPLAT) + R_DrawVisSplat(spr); + else + R_DrawVisSprite(spr); } // Special drawer for precipitation sprites Tails 08-18-2002 @@ -2573,205 +2872,208 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr) R_DrawPrecipitationVisSprite(spr); } -// R_ClipSprites +// R_ClipVisSprite // Clips vissprites without drawing, so that portals can work. -Red -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) { - vissprite_t *spr; - for (; clippedvissprites < visspritecount; clippedvissprites++) + drawseg_t *ds; + INT32 x; + INT32 r1; + INT32 r2; + fixed_t scale; + fixed_t lowscale; + INT32 silhouette; + + for (x = x1; x <= x2; x++) + spr->clipbot[x] = spr->cliptop[x] = -2; + + // Scan drawsegs from end to start for obscuring segs. + // The first drawseg that has a greater scale + // is the clip seg. + //SoM: 4/8/2000: + // Pointer check was originally nonportable + // and buggy, by going past LEFT end of array: + + // for (ds = ds_p-1; ds >= drawsegs; ds--) old buggy code + for (ds = ds_p; ds-- > dsstart;) { - drawseg_t *ds; - INT32 x; - INT32 r1; - INT32 r2; - fixed_t scale; - fixed_t lowscale; - INT32 silhouette; - - spr = R_GetVisSprite(clippedvissprites); - - for (x = spr->x1; x <= spr->x2; x++) - spr->clipbot[x] = spr->cliptop[x] = -2; - - // Scan drawsegs from end to start for obscuring segs. - // The first drawseg that has a greater scale - // is the clip seg. - //SoM: 4/8/2000: - // Pointer check was originally nonportable - // and buggy, by going past LEFT end of array: - - // for (ds = ds_p-1; ds >= drawsegs; ds--) old buggy code - for (ds = ds_p; ds-- > dsstart;) + // determine if the drawseg obscures the sprite + if (ds->x1 > x2 || + ds->x2 < x1 || + (!ds->silhouette + && !ds->maskedtexturecol)) { - // determine if the drawseg obscures the sprite - if (ds->x1 > spr->x2 || - ds->x2 < spr->x1 || - (!ds->silhouette - && !ds->maskedtexturecol)) + // does not cover sprite + continue; + } + + if (ds->portalpass != 66) + { + if (ds->portalpass > 0 && ds->portalpass <= portalrender) + continue; // is a portal + + if (ds->scale1 > ds->scale2) { - // does not cover sprite + lowscale = ds->scale2; + scale = ds->scale1; + } + else + { + lowscale = ds->scale1; + scale = ds->scale2; + } + + if (scale < spr->sortscale || + (lowscale < spr->sortscale && + !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) + { + // masked mid texture? + /*if (ds->maskedtexturecol) + R_RenderMaskedSegRange (ds, r1, r2);*/ + // seg is behind sprite continue; } - - if (ds->portalpass != 66) - { - if (ds->portalpass > 0 && ds->portalpass <= portalrender) - continue; // is a portal - - if (ds->scale1 > ds->scale2) - { - lowscale = ds->scale2; - scale = ds->scale1; - } - else - { - lowscale = ds->scale1; - scale = ds->scale2; - } - - if (scale < spr->sortscale || - (lowscale < spr->sortscale && - !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) - { - // masked mid texture? - /*if (ds->maskedtexturecol) - R_RenderMaskedSegRange (ds, r1, r2);*/ - // seg is behind sprite - continue; - } - } - - r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; - r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; - - // clip this piece of the sprite - silhouette = ds->silhouette; - - if (spr->gz >= ds->bsilheight) - silhouette &= ~SIL_BOTTOM; - - if (spr->gzt <= ds->tsilheight) - silhouette &= ~SIL_TOP; - - if (silhouette == SIL_BOTTOM) - { - // bottom sil - for (x = r1; x <= r2; x++) - if (spr->clipbot[x] == -2) - spr->clipbot[x] = ds->sprbottomclip[x]; - } - else if (silhouette == SIL_TOP) - { - // top sil - for (x = r1; x <= r2; x++) - if (spr->cliptop[x] == -2) - spr->cliptop[x] = ds->sprtopclip[x]; - } - else if (silhouette == (SIL_TOP|SIL_BOTTOM)) - { - // both - for (x = r1; x <= r2; x++) - { - if (spr->clipbot[x] == -2) - spr->clipbot[x] = ds->sprbottomclip[x]; - if (spr->cliptop[x] == -2) - spr->cliptop[x] = ds->sprtopclip[x]; - } - } } - //SoM: 3/17/2000: Clip sprites in water. - if (spr->heightsec != -1) // only things in specially marked sectors + + r1 = ds->x1 < x1 ? x1 : ds->x1; + r2 = ds->x2 > x2 ? x2 : ds->x2; + + // clip this piece of the sprite + silhouette = ds->silhouette; + + if (spr->gz >= ds->bsilheight) + silhouette &= ~SIL_BOTTOM; + + if (spr->gzt <= ds->tsilheight) + silhouette &= ~SIL_TOP; + + if (silhouette == SIL_BOTTOM) { - fixed_t mh, h; - INT32 phs = viewplayer->mo->subsector->sector->heightsec; - if ((mh = sectors[spr->heightsec].floorheight) > spr->gz && - (h = centeryfrac - FixedMul(mh -= viewz, spr->sortscale)) >= 0 && - (h >>= FRACBITS) < viewheight) - { - if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight)) - { // clip bottom - for (x = spr->x1; x <= spr->x2; x++) - if (spr->clipbot[x] == -2 || h < spr->clipbot[x]) - spr->clipbot[x] = (INT16)h; - } - else // clip top - { - for (x = spr->x1; x <= spr->x2; x++) - if (spr->cliptop[x] == -2 || h > spr->cliptop[x]) - spr->cliptop[x] = (INT16)h; - } - } - - if ((mh = sectors[spr->heightsec].ceilingheight) < spr->gzt && - (h = centeryfrac - FixedMul(mh-viewz, spr->sortscale)) >= 0 && - (h >>= FRACBITS) < viewheight) - { - if (phs != -1 && viewz >= sectors[phs].ceilingheight) - { // clip bottom - for (x = spr->x1; x <= spr->x2; x++) - if (spr->clipbot[x] == -2 || h < spr->clipbot[x]) - spr->clipbot[x] = (INT16)h; - } - else // clip top - { - for (x = spr->x1; x <= spr->x2; x++) - if (spr->cliptop[x] == -2 || h > spr->cliptop[x]) - spr->cliptop[x] = (INT16)h; - } - } + // bottom sil + for (x = r1; x <= r2; x++) + if (spr->clipbot[x] == -2) + spr->clipbot[x] = ds->sprbottomclip[x]; } - if (spr->cut & SC_TOP && spr->cut & SC_BOTTOM) + else if (silhouette == SIL_TOP) { - for (x = spr->x1; x <= spr->x2; x++) + // top sil + for (x = r1; x <= r2; x++) + if (spr->cliptop[x] == -2) + spr->cliptop[x] = ds->sprtopclip[x]; + } + else if (silhouette == (SIL_TOP|SIL_BOTTOM)) + { + // both + for (x = r1; x <= r2; x++) { - if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x]) - spr->cliptop[x] = spr->szt; - - if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x]) - spr->clipbot[x] = spr->sz; + if (spr->clipbot[x] == -2) + spr->clipbot[x] = ds->sprbottomclip[x]; + if (spr->cliptop[x] == -2) + spr->cliptop[x] = ds->sprtopclip[x]; } } - else if (spr->cut & SC_TOP) + } + //SoM: 3/17/2000: Clip sprites in water. + if (spr->heightsec != -1) // only things in specially marked sectors + { + fixed_t mh, h; + INT32 phs = viewplayer->mo->subsector->sector->heightsec; + if ((mh = sectors[spr->heightsec].floorheight) > spr->gz && + (h = centeryfrac - FixedMul(mh -= viewz, spr->sortscale)) >= 0 && + (h >>= FRACBITS) < viewheight) { - for (x = spr->x1; x <= spr->x2; x++) - { - if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x]) - spr->cliptop[x] = spr->szt; + if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight)) + { // clip bottom + for (x = x1; x <= x2; x++) + if (spr->clipbot[x] == -2 || h < spr->clipbot[x]) + spr->clipbot[x] = (INT16)h; } - } - else if (spr->cut & SC_BOTTOM) - { - for (x = spr->x1; x <= spr->x2; x++) + else // clip top { - if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x]) - spr->clipbot[x] = spr->sz; + for (x = x1; x <= x2; x++) + if (spr->cliptop[x] == -2 || h > spr->cliptop[x]) + spr->cliptop[x] = (INT16)h; } } - // all clipping has been performed, so store the values - what, did you think we were drawing them NOW? - - // check for unclipped columns - for (x = spr->x1; x <= spr->x2; x++) + if ((mh = sectors[spr->heightsec].ceilingheight) < spr->gzt && + (h = centeryfrac - FixedMul(mh-viewz, spr->sortscale)) >= 0 && + (h >>= FRACBITS) < viewheight) { - if (spr->clipbot[x] == -2) - spr->clipbot[x] = (INT16)viewheight; - - if (spr->cliptop[x] == -2) - //Fab : 26-04-98: was -1, now clips against console bottom - spr->cliptop[x] = (INT16)con_clipviewtop; - } - - if (portal) - { - for (x = spr->x1; x <= spr->x2; x++) + if (phs != -1 && viewz >= sectors[phs].ceilingheight) + { // clip bottom + for (x = x1; x <= x2; x++) + if (spr->clipbot[x] == -2 || h < spr->clipbot[x]) + spr->clipbot[x] = (INT16)h; + } + else // clip top { - if (spr->clipbot[x] > portal->floorclip[x - portal->start]) - spr->clipbot[x] = portal->floorclip[x - portal->start]; - if (spr->cliptop[x] < portal->ceilingclip[x - portal->start]) - spr->cliptop[x] = portal->ceilingclip[x - portal->start]; + for (x = x1; x <= x2; x++) + if (spr->cliptop[x] == -2 || h > spr->cliptop[x]) + spr->cliptop[x] = (INT16)h; } } } + if (spr->cut & SC_TOP && spr->cut & SC_BOTTOM) + { + for (x = x1; x <= x2; x++) + { + if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x]) + spr->cliptop[x] = spr->szt; + + if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x]) + spr->clipbot[x] = spr->sz; + } + } + else if (spr->cut & SC_TOP) + { + for (x = x1; x <= x2; x++) + { + if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x]) + spr->cliptop[x] = spr->szt; + } + } + else if (spr->cut & SC_BOTTOM) + { + for (x = x1; x <= x2; x++) + { + if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x]) + spr->clipbot[x] = spr->sz; + } + } + + // all clipping has been performed, so store the values - what, did you think we were drawing them NOW? + + // check for unclipped columns + for (x = x1; x <= x2; x++) + { + if (spr->clipbot[x] == -2) + spr->clipbot[x] = (INT16)viewheight; + + if (spr->cliptop[x] == -2) + //Fab : 26-04-98: was -1, now clips against console bottom + spr->cliptop[x] = (INT16)con_clipviewtop; + } + + if (portal) + { + for (x = x1; x <= x2; x++) + { + if (spr->clipbot[x] > portal->floorclip[x - portal->start]) + spr->clipbot[x] = portal->floorclip[x - portal->start]; + if (spr->cliptop[x] < portal->ceilingclip[x - portal->start]) + spr->cliptop[x] = portal->ceilingclip[x - portal->start]; + } + } +} + +void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) +{ + for (; clippedvissprites < visspritecount; clippedvissprites++) + { + vissprite_t *spr = R_GetVisSprite(clippedvissprites); + R_ClipVisSprite(spr, spr->x1, spr->x2, dsstart, portal); + } } /* Check if thing may be drawn from our current view. */ @@ -2823,6 +3125,36 @@ boolean R_PrecipThingVisible (precipmobj_t *precipthing, return ( approx_dist <= limit_dist ); } +boolean R_ThingHorizontallyFlipped(mobj_t *thing) +{ + return (thing->frame & FF_HORIZONTALFLIP || thing->renderflags & RF_HORIZONTALFLIP); +} + +boolean R_ThingVerticallyFlipped(mobj_t *thing) +{ + return (thing->frame & FF_VERTICALFLIP || thing->renderflags & RF_VERTICALFLIP); +} + +boolean R_ThingIsPaperSprite(mobj_t *thing) +{ + return (thing->frame & FF_PAPERSPRITE || thing->renderflags & RF_PAPERSPRITE); +} + +boolean R_ThingIsFloorSprite(mobj_t *thing) +{ + return (thing->flags2 & MF2_SPLAT || thing->renderflags & RF_FLOORSPRITE); +} + +boolean R_ThingIsFullBright (mobj_t *thing) +{ + return (thing->frame & FF_FULLBRIGHT || thing->renderflags & RF_FULLBRIGHT); +} + +boolean R_ThingIsFullDark (mobj_t *thing) +{ + return (thing->renderflags & RF_FULLDARK); +} + // // R_DrawMasked // diff --git a/src/r_things.h b/src/r_things.h index f241a78ba..2addcb7ca 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -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 // ---------- diff --git a/src/screen.c b/src/screen.c index adda4ba2f..f5d182f34 100644 --- a/src/screen.c +++ b/src/screen.c @@ -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; diff --git a/src/screen.h b/src/screen.h index acc08f001..021c644ba 100644 --- a/src/screen.h +++ b/src/screen.h @@ -142,6 +142,8 @@ enum SPANDRAWFUNC_TRANS, SPANDRAWFUNC_SPLAT, SPANDRAWFUNC_TRANSSPLAT, + SPANDRAWFUNC_SPRITE, + SPANDRAWFUNC_TRANSSPRITE, SPANDRAWFUNC_FOG, #ifndef NOWATER SPANDRAWFUNC_WATER, diff --git a/src/tmap.nas b/src/tmap.nas index 106f38e96..69282d0b4 100644 --- a/src/tmap.nas +++ b/src/tmap.nas @@ -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