From d0043bed78082c7faf749236c9939d90a081b25e Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 2 Aug 2014 22:35:57 -0500 Subject: [PATCH] Q&D port of decal code to draw generic wall sprites - This still doesn't use all the sprite properties correctly. It also looks like they're going to need different code to build the clipping arrays. But at least wall sprites are drawn at the proper angle now! --- src/r_bsp.h | 8 ++ src/r_segs.cpp | 36 +------ src/r_segs.h | 9 ++ src/r_things.cpp | 252 +++++++++++++++++++++++++++++++++++++++++++++-- src/r_things.h | 21 +++- 5 files changed, 279 insertions(+), 47 deletions(-) diff --git a/src/r_bsp.h b/src/r_bsp.h index 53a0b2b0b..d15beca0c 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -26,6 +26,11 @@ #include "tarray.h" #include +// The 3072 below is just an arbitrary value picked to avoid +// drawing lines the player is too close to that would overflow +// the texture calculations. +#define TOO_CLOSE_Z 3072 + struct FWallCoords { fixed_t TX1, TX2; // x coords at left, right of wall in view space @@ -51,6 +56,9 @@ struct FWallTmapVals void InitDepth(); }; +extern FWallCoords WallC; +extern FWallTmapVals WallT; + enum { FAKED_Center, diff --git a/src/r_segs.cpp b/src/r_segs.cpp index f985a732d..25395a596 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -64,11 +64,6 @@ CVAR(Bool, r_np2, true, 0) #define HEIGHTBITS 12 #define HEIGHTSHIFT (FRACBITS-HEIGHTBITS) -// The 3072 below is just an arbitrary value picked to avoid -// drawing lines the player is too close to that would overflow -// the texture calculations. -#define TOO_CLOSE_Z 3072 - extern fixed_t globaluclip, globaldclip; @@ -86,10 +81,6 @@ fixed_t rw_offset_top; fixed_t rw_offset_mid; fixed_t rw_offset_bottom; -void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat, int x1, int x2); -void PrepLWall (fixed_t *lwall, fixed_t walxrepeat, int x1, int x2); -extern FWallCoords WallC; -extern FWallTmapVals WallT; int wallshade; @@ -139,7 +130,6 @@ static fixed_t rw_bottomtexturescaley; FTexture *rw_pic; static fixed_t *maskedtexturecol; -static FTexture *WallSpriteTile; static void R_RenderDecal (side_t *wall, DBaseDecal *first, drawseg_t *clipper, int pass); static void WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)); @@ -3216,8 +3206,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { // calculate lighting dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); } - - WallSpriteColumn (R_DrawMaskedColumn); + R_WallSpriteColumn (R_DrawMaskedColumn); dc_x++; } @@ -3230,7 +3219,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, rt_initcols(); for (int zz = 4; zz; --zz) { - WallSpriteColumn (R_DrawMaskedColumnHoriz); + R_WallSpriteColumn (R_DrawMaskedColumnHoriz); dc_x++; } rt_draw4cols (dc_x - 4); @@ -3242,8 +3231,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, { // calculate lighting dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, wallshade) << COLORMAPSHIFT); } - - WallSpriteColumn (R_DrawMaskedColumn); + R_WallSpriteColumn (R_DrawMaskedColumn); dc_x++; } } @@ -3264,21 +3252,3 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, done: WallC = savecoord; } - -static void WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)) -{ - unsigned int texturecolumn = lwall[dc_x] >> FRACBITS; - dc_iscale = MulScale16 (swall[dc_x], rw_offset); - spryscale = SafeDivScale32 (1, dc_iscale); - if (sprflipvert) - sprtopscreen = centeryfrac + FixedMul (dc_texturemid, spryscale); - else - sprtopscreen = centeryfrac - FixedMul (dc_texturemid, spryscale); - - const BYTE *column; - const FTexture::Span *spans; - column = WallSpriteTile->GetColumn (texturecolumn, &spans); - dc_texturefrac = 0; - drawfunc (column, spans); - rw_light += rw_lightstep; -} diff --git a/src/r_segs.h b/src/r_segs.h index 838b019a9..b8bf96511 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -33,6 +33,8 @@ extern size_t maxopenings; int OWallMost (short *mostbuf, fixed_t z, const FWallCoords *wallc); int WallMost (short *mostbuf, const secplane_t &plane, const FWallCoords *wallc); +void PrepWall (fixed_t *swall, fixed_t *lwall, fixed_t walxrepeat, int x1, int x2); +void PrepLWall (fixed_t *lwall, fixed_t walxrepeat, int x1, int x2); ptrdiff_t R_NewOpening (ptrdiff_t len); @@ -40,4 +42,11 @@ void R_CheckDrawSegs (); void R_RenderSegLoop (); +extern fixed_t swall[MAXWIDTH]; +extern fixed_t lwall[MAXWIDTH]; +extern fixed_t rw_light; // [RH] Scale lights with viewsize adjustments +extern fixed_t rw_lightstep; +extern fixed_t rw_lightleft; +extern fixed_t rw_offset; + #endif diff --git a/src/r_things.cpp b/src/r_things.cpp index 7243ac6f9..1d2c07a2a 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -114,6 +114,8 @@ FDynamicColormap *VisPSpritesBaseColormap[NUMPSPRITES]; static int spriteshade; +FTexture *WallSpriteTile; + // constant arrays // used for psprite clipping and initializing clipping short zeroarray[MAXWIDTH]; @@ -145,6 +147,8 @@ static vissprite_t **spritesorter; static int spritesortersize = 0; static int vsprcount; +static void R_ProjectWallSprite(AActor *thing, fixed_t fx, fixed_t fy, fixed_t fz, FTextureID picnum, fixed_t xscale, fixed_t yscale, INTBOOL flip); + void R_DeinitSprites() { @@ -401,6 +405,151 @@ void R_DrawVisSprite (vissprite_t *vis) NetUpdate (); } +void R_DrawWallSprite(vissprite_t *spr) +{ + int x1, x2; + fixed_t yscale; + int shade = LIGHT2SHADE(140); + + x1 = MAX(spr->x1, spr->wallc.SX1); + x2 = MIN(spr->x2, spr->wallc.SX2 + 1); + if (x1 >= x2) + return; + WallT.InitFromWallCoords(&spr->wallc); + PrepWall(swall, lwall, spr->pic->GetWidth() << FRACBITS, x1, x2); + dc_texturemid = spr->gzt - viewz; + yscale = FRACUNIT; + if (spr->renderflags & RF_XFLIP) + { + int right = (spr->pic->GetWidth() << FRACBITS) - 1; + + for (int i = x1; i < x2; i++) + { + lwall[i] = right - lwall[i]; + } + } + // Prepare lighting + bool calclighting = false; + FDynamicColormap *usecolormap = basecolormap; + bool rereadcolormap = true; + + // Decals that are added to the scene must fade to black. + if (spr->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) + { + usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate); + rereadcolormap = false; + } + + rw_light = rw_lightleft + (x1 - spr->wallc.SX1) * rw_lightstep; + if (fixedlightlev >= 0) + dc_colormap = usecolormap->Maps + fixedlightlev; + else if (fixedcolormap != NULL) + dc_colormap = fixedcolormap; + else if (!foggy && (spr->renderflags & RF_FULLBRIGHT)) + dc_colormap = usecolormap->Maps; + else + calclighting = true; + + // Draw it + WallSpriteTile = spr->pic; + if (spr->renderflags & RF_YFLIP) + { + sprflipvert = true; + yscale = -yscale; + dc_texturemid = dc_texturemid - (spr->pic->GetHeight() << FRACBITS); + } + else + { + sprflipvert = false; + } + + // rw_offset is used as the texture's vertical scale + rw_offset = SafeDivScale30(1, yscale); + + dc_x = x1; + ESPSResult mode; + + mode = R_SetPatchStyle (spr->Style.RenderStyle, spr->Style.alpha, spr->Translation, spr->FillColor); + + // R_SetPatchStyle can modify basecolormap. + if (rereadcolormap) + { + usecolormap = basecolormap; + } + + if (mode == DontDraw) + { + return; + } + else + { + int stop4; + + if (mode == DoDraw0) + { // 1 column at a time + stop4 = dc_x; + } + else // DoDraw1 + { // up to 4 columns at a time + stop4 = x2 & ~3; + } + + while ((dc_x < stop4) && (dc_x & 3)) + { + if (calclighting) + { // calculate lighting + dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT); + } + R_WallSpriteColumn(R_DrawMaskedColumn); + dc_x++; + } + + while (dc_x < stop4) + { + if (calclighting) + { // calculate lighting + dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT); + } + rt_initcols(); + for (int zz = 4; zz; --zz) + { + R_WallSpriteColumn(R_DrawMaskedColumnHoriz); + dc_x++; + } + rt_draw4cols(dc_x - 4); + } + + while (dc_x < x2) + { + if (calclighting) + { // calculate lighting + dc_colormap = usecolormap->Maps + (GETPALOOKUP (rw_light, shade) << COLORMAPSHIFT); + } + R_WallSpriteColumn(R_DrawMaskedColumn); + dc_x++; + } + } + R_FinishSetPatchStyle(); +} + +void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)) +{ + unsigned int texturecolumn = lwall[dc_x] >> FRACBITS; + dc_iscale = MulScale16 (swall[dc_x], rw_offset); + spryscale = SafeDivScale32 (1, dc_iscale); + if (sprflipvert) + sprtopscreen = centeryfrac + FixedMul (dc_texturemid, spryscale); + else + sprtopscreen = centeryfrac - FixedMul (dc_texturemid, spryscale); + + const BYTE *column; + const FTexture::Span *spans; + column = WallSpriteTile->GetColumn (texturecolumn, &spans); + dc_texturefrac = 0; + drawfunc (column, spans); + rw_light += rw_lightstep; +} + void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop, short *clipbot) { ESPSResult mode; @@ -521,12 +670,6 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor fy = thing->PrevY + FixedMul (r_TicFrac, thing->y - thing->PrevY); fz = thing->PrevZ + FixedMul (r_TicFrac, thing->z - thing->PrevZ) + thing->GetBobOffset(r_TicFrac); - // transform the origin point - tr_x = fx - viewx; - tr_y = fy - viewy; - - tz = DMulScale20 (tr_x, viewtancos, tr_y, viewtansin); - tex = NULL; voxel = NULL; @@ -618,6 +761,18 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor return; } + if ((thing->renderflags & RF_SPRITETYPEMASK) == RF_WALLSPRITE) + { + R_ProjectWallSprite(thing, fx, fy, fz, picnum, spritescaleX, spritescaleY, flip); + return; + } + + // transform the origin point + tr_x = fx - viewx; + tr_y = fy - viewy; + + tz = DMulScale20 (tr_x, viewtancos, tr_y, viewtansin); + // thing is behind view plane? if (voxel == NULL && tz < MINZ) return; @@ -782,7 +937,6 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor vis->heightsec = heightsec; vis->sector = thing->Sector; - vis->cx = tx2; vis->depth = tz; vis->gx = fx; vis->gy = fy; @@ -807,12 +961,14 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor { vis->voxel = voxel->Voxel; vis->bIsVoxel = true; + vis->bWallSprite = false; DrewAVoxel = true; } else { vis->pic = tex; vis->bIsVoxel = false; + vis->bWallSprite = false; } // The software renderer cannot invert the source without inverting the overlay @@ -874,6 +1030,78 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor } } +static void R_ProjectWallSprite(AActor *thing, fixed_t fx, fixed_t fy, fixed_t fz, FTextureID picnum, fixed_t xscale, fixed_t yscale, INTBOOL flip) +{ + FWallCoords wallc; + int x1, x2; + fixed_t lx1, lx2, ly1, ly2; + fixed_t gzb, gzt, tz; + FTexture *pic = TexMan(picnum, true); + angle_t ang = (thing->angle + ANGLE_90) >> ANGLETOFINESHIFT; + vissprite_t *vis; + + // Determine left and right edges of sprite. The sprite's angle is its normal, + // so the edges are 90 degrees each side of it. + x2 = pic->GetScaledWidth(); + x1 = pic->GetScaledLeftOffset(); + + x1 *= xscale; + x2 *= xscale; + + lx1 = fx - FixedMul(x1, finecosine[ang]) - viewx; + ly1 = fy - FixedMul(x1, finesine[ang]) - viewy; + lx2 = lx1 + FixedMul(x2, finecosine[ang]); + ly2 = ly1 + FixedMul(x2, finesine[ang]); + + // Is it off-screen? + if (wallc.Init(lx1, ly1, lx2, ly2, TOO_CLOSE_Z)) + return; + + if (wallc.SX1 > WindowRight || wallc.SX2 <= WindowLeft) + return; + + // Sprite sorting should probably treat these as walls, not sprites, + // but right now, I just want to get them drawing. + tz = DMulScale20(fx - viewx, viewtancos, fy - viewy, viewtansin); + + int scaled_to = pic->GetScaledTopOffset(); + int scaled_bo = scaled_to - pic->GetScaledHeight(); + gzt = fz + yscale * scaled_to; + gzb = fz + yscale * scaled_bo; + + vis = R_NewVisSprite(); + vis->x1 = wallc.SX1 < WindowLeft ? WindowLeft : wallc.SX1; + vis->x2 = wallc.SX2 >= WindowRight ? WindowRight-1 : wallc.SX2-1; + vis->idepth = (unsigned)DivScale32(1, tz) >> 1; + vis->depth = tz; + vis->sector = thing->Sector; + vis->heightsec = NULL; + vis->gx = fx; + vis->gy = fy; + vis->gz = fz; + vis->gzb = gzb; + vis->gzt = gzt; + vis->deltax = fx - viewx; + vis->deltay = fy - viewy; + vis->renderflags = thing->renderflags; + if(thing->flags5 & MF5_BRIGHT) vis->renderflags |= RF_FULLBRIGHT; // kg3D + vis->Style.RenderStyle = thing->RenderStyle; + vis->FillColor = thing->fillcolor; + vis->Translation = thing->Translation; + vis->FakeFlatStat = 0; + vis->Style.alpha = thing->alpha; + vis->fakefloor = NULL; + vis->fakeceiling = NULL; + vis->ColormapNum = 0; + vis->bInMirror = MirrorFlags & RF_XFLIP; + vis->pic = pic; + vis->bIsVoxel = false; + vis->bWallSprite = true; + vis->ColormapNum = GETPALOOKUP( + (fixed_t)DivScale12 (r_SpriteVisibility, MAX(tz, MINZ)), spriteshade); + vis->Style.colormap = basecolormap->Maps + (vis->ColormapNum << COLORMAPSHIFT); + vis->wallc = wallc; +} // // R_AddSprites @@ -1904,7 +2132,14 @@ void R_DrawSprite (vissprite_t *spr) { mfloorclip = clipbot; mceilingclip = cliptop; - R_DrawVisSprite (spr); + if (!spr->bWallSprite) + { + R_DrawVisSprite(spr); + } + else + { + R_DrawWallSprite(spr); + } } else { @@ -2161,7 +2396,6 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade, vis->yscale = xscale; vis->depth = tz; vis->idepth = (DWORD)DivScale32 (1, tz) >> 1; - vis->cx = tx; vis->gx = particle->x; vis->gy = particle->y; vis->gz = particle->z; // kg3D diff --git a/src/r_things.h b/src/r_things.h index 2219eee20..3ce1a4d4d 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -23,6 +23,7 @@ #ifndef __R_THINGS__ #define __R_THINGS__ +#include "r_bsp.h" // A vissprite_t is a thing // that will be drawn during a refresh. @@ -31,7 +32,6 @@ struct vissprite_t { short x1, x2; - fixed_t cx; // for line side calculation fixed_t gx, gy, gz; // origin in world coordinates angle_t angle; fixed_t gzb, gzt; // global bottom / top for silhouette clipping @@ -43,18 +43,26 @@ struct vissprite_t fixed_t floorclip; union { - // Used by regular sprites + FTexture *pic; + struct FVoxel *voxel; + }; + union + { + // Used by face sprites struct { - FTexture *pic; fixed_t texturemid; fixed_t startfrac; // horizontal position of x1 fixed_t xiscale; // negative if flipped }; + // Used by wall sprites + struct + { + FWallCoords wallc; + }; // Used by voxels struct { - struct FVoxel *voxel; fixed_t vx, vy, vz; // view origin angle_t vang; // view angle }; @@ -64,6 +72,7 @@ struct vissprite_t F3DFloor *fakefloor; F3DFloor *fakeceiling; BYTE bIsVoxel:1; // [RH] Use voxel instead of pic + BYTE bWallSprite:1; // [RH] This is a wall sprite BYTE bSplitSprite:1; // [RH] Sprite was split by a drawseg BYTE bInMirror:1; // [RH] Sprite is "inside" a mirror BYTE FakeFlatStat; // [RH] which side of fake/floor ceiling sprite is on @@ -99,9 +108,11 @@ extern fixed_t pspritexscale; extern fixed_t pspriteyscale; extern fixed_t pspritexiscale; +extern FTexture *WallSpriteTile; + void R_DrawMaskedColumn (const BYTE *column, const FTexture::Span *spans); - +void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Span *spans)); void R_CacheSprite (spritedef_t *sprite); void R_SortVisSprites (int (STACK_ARGS *compare)(const void *, const void *), size_t first);