diff --git a/src/d_netcmd.c b/src/d_netcmd.c index f60b07c90..356b377d7 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -551,6 +551,7 @@ void D_RegisterClientCommands(void) COM_AddDebugCommand("goto", Command_Goto_f); COM_AddDebugCommand("angle", Command_Angle_f); COM_AddDebugCommand("respawnat", Command_RespawnAt_f); + COM_AddDebugCommand("goto_skybox", Command_GotoSkybox_f); { extern struct CVarList *cvlist_player; diff --git a/src/m_cheat.c b/src/m_cheat.c index 7c6855e21..8e7a708e6 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -640,6 +640,23 @@ void Command_RespawnAt_f(void) D_Cheat(consoleplayer, CHEAT_RESPAWNAT, atoi(COM_Argv(1))); } +void Command_GotoSkybox_f(void) +{ + REQUIRE_CHEATS; + REQUIRE_INLEVEL; + + mobj_t *skybox = players[consoleplayer].skybox.viewpoint; + + if (P_MobjWasRemoved(skybox)) + { + CONS_Printf("There is no visible skybox for local Player 1.\n"); + return; + } + + D_Cheat(consoleplayer, CHEAT_TELEPORT, skybox->x, skybox->y, skybox->z); + D_Cheat(consoleplayer, CHEAT_ANGLE, skybox->angle); +} + // // OBJECTPLACE (and related variables) // diff --git a/src/m_cheat.h b/src/m_cheat.h index 835832500..1c1270e9b 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -91,6 +91,7 @@ void Command_Grayscale_f(void); void Command_Goto_f(void); void Command_Angle_f(void); void Command_RespawnAt_f(void); +void Command_GotoSkybox_f(void); #ifdef _DEBUG void Command_CauseCfail_f(void); #endif diff --git a/src/r_plane.cpp b/src/r_plane.cpp index e73954869..106cf9a30 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1029,6 +1029,9 @@ void R_DrawSinglePlane(visplane_t *pl) INT32 bmNum = R_GetTextureBrightmap(levelflat->u.texture.num); if (bmNum != 0) { + // FIXME: This has the potential to read out of + // bounds if the brightmap texture is not as + // large as the flat. ds_brightmap = (UINT8 *)R_GenerateTextureAsFlat(bmNum); } } diff --git a/src/r_segs.cpp b/src/r_segs.cpp index b94f1ff08..1f3023d60 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -40,7 +40,7 @@ static boolean markceiling; static boolean maskedtexture; static INT32 toptexture, bottomtexture, midtexture; -static INT32 topbrightmap, bottombrightmap, midbrightmap; +static bool topbrightmapped, bottombrightmapped, midbrightmapped; static INT32 numthicksides, numbackffloors; angle_t rw_normalangle; @@ -160,7 +160,7 @@ static inline boolean R_OverflowTest(void) return false; } -static void R_RenderMaskedSegLoop(drawseg_t *ds, INT32 x1, INT32 x2, INT32 texnum, INT32 bmnum, void (*colfunc_2s)(column_t *, column_t *, INT32)) +static void R_RenderMaskedSegLoop(drawseg_t *ds, INT32 x1, INT32 x2, INT32 texnum, void (*colfunc_2s)(column_t *, column_t *, INT32)) { size_t pindex; column_t *col, *bmCol = NULL; @@ -173,6 +173,7 @@ static void R_RenderMaskedSegLoop(drawseg_t *ds, INT32 x1, INT32 x2, INT32 texnu sector_t *front, *back; INT32 times, repeats; boolean tripwire; + boolean brightmapped = R_TextureHasBrightmap(texnum); ldef = curline->linedef; tripwire = P_IsLineTripWire(ldef); @@ -350,7 +351,11 @@ static void R_RenderMaskedSegLoop(drawseg_t *ds, INT32 x1, INT32 x2, INT32 texnu // draw the texture col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); - if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); } + + if (brightmapped) + { + bmCol = (column_t *)((UINT8 *)R_GetBrightmapColumn(texnum, maskedtexturecol[dc_x]) - 3); + } for (i = 0; i < dc_numlights; i++) { @@ -449,7 +454,11 @@ static void R_RenderMaskedSegLoop(drawseg_t *ds, INT32 x1, INT32 x2, INT32 texnu // draw the texture col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); - if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); } + + if (brightmapped) + { + bmCol = (column_t *)((UINT8 *)R_GetBrightmapColumn(texnum, maskedtexturecol[dc_x]) - 3); + } #if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES)) @@ -557,7 +566,7 @@ static INT32 R_GetTwoSidedMidTexture(seg_t *line) return R_GetTextureNum(texture); } -static boolean R_CheckBlendMode(const line_t *ldef, INT32 bmnum) +static boolean R_CheckBlendMode(const line_t *ldef, boolean brightmapped) { transnum_t transtable = NUMTRANSMAPS; patchalphastyle_t blendmode = AST_COPY; @@ -578,18 +587,18 @@ static boolean R_CheckBlendMode(const line_t *ldef, INT32 bmnum) if (blendmode == AST_FOG) { - R_SetColumnFunc(COLDRAWFUNC_FOG, bmnum != 0); + R_SetColumnFunc(COLDRAWFUNC_FOG, brightmapped); windowtop = frontsector->ceilingheight; windowbottom = frontsector->floorheight; } else if (transtable != NUMTRANSMAPS && (blendmode || transtable)) { dc_transmap = R_GetBlendTable(blendmode, transtable); - R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); + R_SetColumnFunc(COLDRAWFUNC_FUZZY, brightmapped); } else { - R_SetColumnFunc(BASEDRAWFUNC, bmnum != 0); + R_SetColumnFunc(BASEDRAWFUNC, brightmapped); } if (curline->polyseg && curline->polyseg->translucency > 0) @@ -598,7 +607,7 @@ static boolean R_CheckBlendMode(const line_t *ldef, INT32 bmnum) return false; dc_transmap = R_GetTranslucencyTable(curline->polyseg->translucency); - R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); + R_SetColumnFunc(COLDRAWFUNC_FUZZY, brightmapped); } return true; @@ -606,7 +615,7 @@ static boolean R_CheckBlendMode(const line_t *ldef, INT32 bmnum) void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { - INT32 texnum, bmnum; + INT32 texnum; void (*colfunc_2s)(column_t *, column_t *, INT32); line_t *ldef; const boolean debug = R_IsDebugLine(ds->curline); @@ -620,14 +629,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) frontsector = curline->frontsector; backsector = curline->backsector; texnum = R_GetTwoSidedMidTexture(curline); - bmnum = R_GetTextureBrightmap(texnum); windowbottom = windowtop = sprbotscreen = INT32_MAX; ldef = curline->linedef; R_CheckDebugHighlight(SW_HI_MIDTEXTURES); - if (debug == false && R_CheckBlendMode(ldef, bmnum) == false) + if (debug == false && R_CheckBlendMode(ldef, R_TextureHasBrightmap(texnum)) == false) { return; // does not render } @@ -638,7 +646,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // Texture must be cached before setting colfunc_2s, // otherwise texture[texnum]->holes may be false when it shouldn't be R_CheckTextureCache(texnum); - if (bmnum) { R_CheckTextureCache(bmnum); } // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info in SRB2 @@ -671,7 +678,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } else { - R_RenderMaskedSegLoop(ds, x1, x2, texnum, bmnum, colfunc_2s); + R_RenderMaskedSegLoop(ds, x1, x2, texnum, colfunc_2s); } R_SetColumnFunc(BASEDRAWFUNC, false); @@ -719,7 +726,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) size_t pindex = 0; column_t * col, *bmCol = NULL; INT32 lightnum; - INT32 texnum, bmnum; + INT32 texnum; sector_t tempsec; INT32 templight; INT32 i, p; @@ -751,20 +758,20 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) backsector = pfloor->target; frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); - bmnum = R_GetTextureBrightmap(texnum); R_CheckDebugHighlight(SW_HI_FOFSIDES); - R_SetColumnFunc(BASEDRAWFUNC, bmnum != 0); - if (pfloor->master->flags & ML_TFERLINE) { size_t linenum = curline->linedef-backsector->lines[0]; newline = pfloor->master->frontsector->lines[0] + linenum; texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); - bmnum = R_GetTextureBrightmap(texnum); } + boolean brightmapped = R_TextureHasBrightmap(texnum); + + R_SetColumnFunc(BASEDRAWFUNC, brightmapped); + if (pfloor->fofflags & FOF_TRANSLUCENT) { boolean fuzzy = true; @@ -781,12 +788,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (fuzzy) { - R_SetColumnFunc(COLDRAWFUNC_FUZZY, bmnum != 0); + R_SetColumnFunc(COLDRAWFUNC_FUZZY, brightmapped); } } else if (pfloor->fofflags & FOF_FOG) { - R_SetColumnFunc(COLDRAWFUNC_FOG, bmnum != 0); + R_SetColumnFunc(COLDRAWFUNC_FOG, brightmapped); } range = std::max(ds->x2-ds->x1, 1); @@ -980,7 +987,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Texture must be cached before setting colfunc_2s, // otherwise texture[texnum]->holes may be false when it shouldn't be R_CheckTextureCache(texnum); - if (bmnum) { R_CheckTextureCache(bmnum); } //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info anymore in Doom Legacy @@ -1065,7 +1071,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Get data for the column col = (column_t *)((UINT8 *)R_GetColumn(texnum,maskedtexturecol[dc_x]) - 3); - if (bmnum) { bmCol = (column_t *)((UINT8 *)R_GetColumn(bmnum, maskedtexturecol[dc_x]) - 3); } + + if (brightmapped) + { + bmCol = (column_t *)((UINT8 *)R_GetBrightmapColumn(texnum, maskedtexturecol[dc_x]) - 3); + } // SoM: New code does not rely on R_DrawColumnShadowed_8 which // will (hopefully) put less strain on the stack. @@ -1276,13 +1286,13 @@ UINT32 nombre = 100000; #endif //profile stuff --------------------------------------------------------- -static void R_DrawWallColumn(INT32 yl, INT32 yh, fixed_t mid, fixed_t texturecolumn, INT32 texture, INT32 brightmap) +static void R_DrawWallColumn(INT32 yl, INT32 yh, fixed_t mid, fixed_t texturecolumn, INT32 texture, boolean brightmapped) { dc_yl = yl; dc_yh = yh; dc_texturemid = mid; dc_source = R_GetColumn(texture, texturecolumn); - dc_brightmap = (brightmap ? R_GetColumn(brightmap, texturecolumn) : NULL); + dc_brightmap = (brightmapped ? R_GetBrightmapColumn(texture, texturecolumn) : NULL); dc_texheight = textureheight[texture] >> FRACBITS; R_SetColumnFunc(colfunctype, dc_brightmap != NULL); colfunc(); @@ -1560,7 +1570,7 @@ static void R_RenderSegLoop (void) // single sided line if (yl <= yh && yh >= 0 && yl < viewheight) { - R_DrawWallColumn(yl, yh, rw_midtexturemid, texturecolumn, midtexture, midbrightmap); + R_DrawWallColumn(yl, yh, rw_midtexturemid, texturecolumn, midtexture, midbrightmapped); // dont draw anything more for this column, since // a midtexture blocks the view @@ -1599,7 +1609,7 @@ static void R_RenderSegLoop (void) } else if (mid >= 0) // safe to draw top texture { - R_DrawWallColumn(yl, mid, rw_toptexturemid, texturecolumn, toptexture, topbrightmap); + R_DrawWallColumn(yl, mid, rw_toptexturemid, texturecolumn, toptexture, topbrightmapped); ceilingclip[rw_x] = (INT16)mid; } else if (!rw_ceilingmarked) // entirely off top of screen @@ -1630,7 +1640,7 @@ static void R_RenderSegLoop (void) } else if (mid < viewheight) // safe to draw bottom texture { - R_DrawWallColumn(mid, yh, rw_bottomtexturemid, texturecolumn, bottomtexture, bottombrightmap); + R_DrawWallColumn(mid, yh, rw_bottomtexturemid, texturecolumn, bottomtexture, bottombrightmapped); floorclip[rw_x] = (INT16)mid; } else if (!rw_floormarked) // entirely off bottom of screen @@ -1914,7 +1924,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) worldbottomslope -= viewz; midtexture = toptexture = bottomtexture = maskedtexture = 0; - midbrightmap = topbrightmap = bottombrightmap = 0; + midbrightmapped = topbrightmapped = bottombrightmapped = false; ds_p->maskedtexturecol = NULL; ds_p->numthicksides = numthicksides = 0; ds_p->thicksidecol = NULL; @@ -1962,7 +1972,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) fixed_t texheight; // single sided line midtexture = R_GetTextureNum(sidedef->midtexture); - midbrightmap = R_GetTextureBrightmap(midtexture); + midbrightmapped = R_TextureHasBrightmap(midtexture); texheight = textureheight[midtexture]; // a single sided line is terminal, so it must mark ends markfloor = markceiling = true; @@ -2150,7 +2160,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) fixed_t texheight; // top texture toptexture = R_GetTextureNum(sidedef->toptexture); - topbrightmap = R_GetTextureBrightmap(toptexture); + topbrightmapped = R_TextureHasBrightmap(toptexture); texheight = textureheight[toptexture]; if (!(linedef->flags & ML_SKEWTD)) @@ -2179,7 +2189,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) { // bottom texture bottomtexture = R_GetTextureNum(sidedef->bottomtexture); - bottombrightmap = R_GetTextureBrightmap(bottomtexture); + bottombrightmapped = R_TextureHasBrightmap(bottomtexture); if (!(linedef->flags & ML_SKEWTD)) { diff --git a/src/r_textures.c b/src/r_textures.c index 266e5ff58..e3d4a6511 100644 --- a/src/r_textures.c +++ b/src/r_textures.c @@ -50,6 +50,7 @@ INT32 numtextures = 0; // total number of textures found, texture_t **textures = NULL; UINT32 **texturecolumnofs; // column offset lookup table for each texture UINT8 **texturecache; // graphics data for each generated full-size texture +UINT8 **texturebrightmapcache; // graphics data for brightmap converted for use with a specific texture INT32 *texturewidth; fixed_t *textureheight; // needed for texture pegging @@ -249,6 +250,50 @@ static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache } } +static UINT8 *R_AllocateTextureBlock(size_t blocksize, UINT8 **user) +{ + texturememory += blocksize; + + return Z_Malloc(blocksize, PU_CACHE, user); +} + +static UINT8 *R_AllocateDummyTextureBlock(size_t width, UINT8 **user) +{ + // Allocate dummy data. Keep 4-bytes aligned. + // Column offsets will be initialized to 0, which points to the 0xff byte (empty column flag). + size_t blocksize = 4 + (width * 4); + UINT8 *block = R_AllocateTextureBlock(blocksize, user); + + memset(block, 0, blocksize); + block[0] = 0xff; + + return block; +} + +static boolean R_CheckTextureLumpLength(texture_t *texture, size_t patch) +{ + UINT16 wadnum = texture->patches[patch].wad; + UINT16 lumpnum = texture->patches[patch].lump; + size_t lumplength = W_LumpLengthPwad(wadnum, lumpnum); + + // The header does not exist + if (lumplength < offsetof(softwarepatch_t, columnofs)) + { + CONS_Alert( + CONS_ERROR, + "%.8s: texture lump data is too small. Expected %s bytes, got %s. (%s)\n", + texture->name, + sizeu1(offsetof(softwarepatch_t, columnofs)), + sizeu2(lumplength), + wadfiles[wadnum]->lumpinfo[lumpnum].fullname + ); + + return false; + } + + return true; +} + // // R_GenerateTexture // @@ -297,22 +342,11 @@ UINT8 *R_GenerateTexture(size_t texnum) lumplength = W_LumpLengthPwad(wadnum, lumpnum); // The header does not exist - if (lumplength < offsetof(softwarepatch_t, columnofs)) + if (R_CheckTextureLumpLength(texture, 0) == false) { - CONS_Alert( - CONS_ERROR, - "%.8s: texture lump data is too small. Expected %s bytes, got %s. (%s)\n", - texture->name, - sizeu1(offsetof(softwarepatch_t, columnofs)), - sizeu2(lumplength), - wadfiles[wadnum]->lumpinfo[lumpnum].fullname - ); - - // Allocate dummy data. Keep 4-bytes aligned. - // Column offsets will be initialized to 0, which points to the 0xff byte (empty column flag). - block = Z_Calloc(4 + (texture->width * 4), PU_CACHE, &texturecache[texnum]); - block[0] = 0xff; + block = R_AllocateDummyTextureBlock(texture->width, &texturecache[texnum]); texturecolumnofs[texnum] = (UINT32*)&block[4]; + textures[texnum]->holes = true; return block; } @@ -511,6 +545,202 @@ UINT8 *R_GenerateTextureAsFlat(size_t texnum) return texture->flat; } +// This function writes a column to p, using the posts from +// tcol, but the pixel values from bcol. If bcol is larger +// than tcol, the pixels are cropped. If bcol is smaller than +// tcol, the empty space is filled with TRANSPARENTPIXEL. +static void R_ConvertBrightmapColumn(UINT8 *p, const column_t *tcol, const column_t *bcol) +{ + /* + + ___t1 + | + | ___b1 + | | + | | + |__t2 | + | |__b2 + | + | ___b3 + |__t3 | + | + ___t4 | + | |__b4 + |__t5 + + ___t6 + |__t7 + + */ + + // copy post header + memcpy(&p[-3], tcol, 3); + + INT32 ttop = tcol->topdelta; + INT32 btop = bcol->topdelta; + + INT32 y = ttop; + + while (tcol->topdelta != 0xff && bcol->topdelta != 0xff) + { + INT32 tbot = ttop + tcol->length; + INT32 bbot = btop + bcol->length; + + INT32 n; + + // t1 to b1 + // b2 to b3 + // -------- + // The brightmap column starts below the + // texture column, so pad it with black + // pixels. + + n = max(0, min(btop, tbot) - y); + memset(&p[y - ttop], TRANSPARENTPIXEL, n); + y += n; + + // b1 to t2 + // t2 to b2 + // b3 to t3 + // t4 to b4 + // -------- + // Copy parts of the brightmap column which + // line up with the texture column. + + n = max(0, min(bbot, tbot) - y); + memcpy(&p[y - ttop], (const UINT8*)bcol + 3 + (y - btop), n); + y += n; + + if (y == tbot) + { + p += 4 + tcol->length; + tcol = (const column_t*)((const UINT8*)tcol + 4 + tcol->length); + + memcpy(&p[-3], tcol, 3); // copy post header + + // Tall patches add the topdelta if it is less + // than the running topdelta. + ttop = tcol->topdelta <= ttop ? ttop + tcol->topdelta : tcol->topdelta; + y = ttop; + } + + if (y >= bbot) + { + bcol = (const column_t*)((const UINT8*)bcol + 4 + bcol->length); + btop = bcol->topdelta <= btop ? btop + bcol->topdelta : bcol->topdelta; // tall patches + } + } + + if (tcol->topdelta != 0xff) + { + // b4 to t5 + // t6 to t7 + // -------- + // The texture column continues past the end + // of the brightmap column, so pad it with + // black pixels. + + y -= ttop; + memset(&p[y], TRANSPARENTPIXEL, tcol->length - y); + + while + ( + ( + p += 4 + tcol->length, + tcol = (const column_t*)((const UINT8*)tcol + 4 + tcol->length) + )->topdelta != 0xff + ) + { + memcpy(&p[-3], tcol, 3); // copy post header + memset(p, TRANSPARENTPIXEL, tcol->length); + } + } + + p[-3] = 0xff; +} + +// Remember, this function must generate a texture that +// matches the layout of texnum. It must have the same width +// and same columns. Only the pixels that overlap are copied +// from the brightmap texture. +UINT8 *R_GenerateTextureBrightmap(size_t texnum) +{ + texture_t *texture = textures[texnum]; + texture_t *bright = textures[R_GetTextureBrightmap(texnum)]; + + if (R_TextureHasBrightmap(texnum) && bright->patchcount > 1) + { + CONS_Alert( + CONS_WARNING, + "%.8s: BRIGHTMAP should not be a composite texture. Only using the first patch.\n", + bright->name + ); + } + + if (R_CheckTextureLumpLength(texture, 0) == false) + { + return R_AllocateDummyTextureBlock(texture->width, &texturebrightmapcache[texnum]); + } + + R_CheckTextureCache(texnum); + + softwarepatch_t *patch = NULL; + INT32 bmap_width = 0; + column_t empty = {0xff, 0}; + + if (R_TextureHasBrightmap(texnum) && R_CheckTextureLumpLength(bright, 0)) + { + patch = W_CacheLumpNumPwad(bright->patches[0].wad, bright->patches[0].lump, PU_STATIC); + bmap_width = SHORT(patch->width); + } + + UINT8 *block; + + if (texture->holes) + { + block = R_AllocateTextureBlock( + W_LumpLengthPwad(texture->patches[0].wad, texture->patches[0].lump), + &texturebrightmapcache[texnum] + ); + + INT32 x; + + for (x = 0; x < texture->width; ++x) + { + const column_t *tcol = (column_t*)(R_GetColumn(texnum, x) - 3); + const column_t *bcol = x < bmap_width ? (column_t*)((UINT8*)patch + LONG(patch->columnofs[x])) : ∅ + + R_ConvertBrightmapColumn(block + LONG(texturecolumnofs[texnum][x]), tcol, bcol); + } + } + else + { + // Allocate the same size as composite textures. + size_t blocksize = (texture->width * 4) + (texture->width * texture->height) + 1; + + block = R_AllocateTextureBlock(blocksize, &texturebrightmapcache[texnum]); + memset(block, TRANSPARENTPIXEL, blocksize); // Transparency hack + + texpatch_t origin = {0}; + INT32 x; + + for (x = 0; x < texture->width; ++x) + { + R_DrawColumnInCache( + x < bmap_width ? (column_t*)((UINT8*)patch + LONG(patch->columnofs[x])) : &empty, + block + LONG(texturecolumnofs[texnum][x]), + &origin, + texture->height, + patch->height + ); + } + } + + Z_Free(patch); + + return block; +} + // // R_GetTextureNum // @@ -539,6 +769,11 @@ INT32 R_GetTextureBrightmap(INT32 texnum) return texturebrightmaps[texnum]; } +boolean R_TextureHasBrightmap(INT32 texnum) +{ + return R_GetTextureBrightmap(texnum) != 0; +} + // // R_CheckTextureCache // @@ -551,12 +786,8 @@ void R_CheckTextureCache(INT32 tex) R_GenerateTexture(tex); } -// -// R_GetColumn -// -UINT8 *R_GetColumn(fixed_t tex, INT32 col) +static inline INT32 wrap_column(fixed_t tex, INT32 col) { - UINT8 *data; INT32 width = texturewidth[tex]; if (width & (width - 1)) @@ -564,11 +795,29 @@ UINT8 *R_GetColumn(fixed_t tex, INT32 col) else col &= (width - 1); - data = texturecache[tex]; - if (!data) - data = R_GenerateTexture(tex); + return col; +} - return data + LONG(texturecolumnofs[tex][col]); +// +// R_GetColumn +// +UINT8 *R_GetColumn(fixed_t tex, INT32 col) +{ + if (!texturecache[tex]) + R_GenerateTexture(tex); + + return texturecache[tex] + LONG(texturecolumnofs[tex][wrap_column(tex, col)]); +} + +// +// R_GetBrightmapColumn +// +UINT8 *R_GetBrightmapColumn(fixed_t tex, INT32 col) +{ + if (!texturebrightmapcache[tex]) + R_GenerateTextureBrightmap(tex); + + return texturebrightmapcache[tex] + LONG(texturecolumnofs[tex][wrap_column(tex, col)]); } void *R_GetFlat(lumpnum_t flatlumpnum) @@ -1099,6 +1348,7 @@ static void R_AllocateTextures(INT32 add) recallocuser(&texturecolumnofs, oldsize, newsize); // Allocate texture referencing cache. recallocuser(&texturecache, oldsize, newsize); + recallocuser(&texturebrightmapcache, oldsize, newsize); // Allocate texture width table. recallocuser(&texturewidth, oldsize, newsize); // Allocate texture height table. @@ -1113,8 +1363,8 @@ static void R_AllocateTextures(INT32 add) // R_FlushTextureCache relies on the user for // Z_Free, texturecache has been reallocated so the // user is now garbage memory. - Z_SetUser(texturecache[i], - (void**)&texturecache[i]); + Z_SetUser(texturecache[i], (void**)&texturecache[i]); + Z_SetUser(texturebrightmapcache[i], (void**)&texturebrightmapcache[i]); } while (i < newtextures) diff --git a/src/r_textures.h b/src/r_textures.h index 084447faa..b0ca2a6a3 100644 --- a/src/r_textures.h +++ b/src/r_textures.h @@ -80,6 +80,7 @@ extern fixed_t *textureheight; // needed for texture pegging extern UINT32 **texturecolumnofs; // column offset lookup table for each texture extern UINT8 **texturecache; // graphics data for each generated full-size texture +extern UINT8 **texturebrightmapcache; // graphics data for brightmap converted for use with a specific texture // Load TEXTURES definitions, create lookup tables void R_LoadTextures(void); @@ -89,14 +90,17 @@ void R_FlushTextureCache(void); // Texture generation UINT8 *R_GenerateTexture(size_t texnum); UINT8 *R_GenerateTextureAsFlat(size_t texnum); +UINT8 *R_GenerateTextureBrightmap(size_t texnum); INT32 R_GetTextureNum(INT32 texnum); INT32 R_GetTextureBrightmap(INT32 texnum); +boolean R_TextureHasBrightmap(INT32 texnum); void R_CheckTextureCache(INT32 tex); void R_ClearTextureNumCache(boolean btell); // Retrieve texture data. void *R_GetLevelFlat(levelflat_t *levelflat); UINT8 *R_GetColumn(fixed_t tex, INT32 col); +UINT8 *R_GetBrightmapColumn(fixed_t tex, INT32 col); void *R_GetFlat(lumpnum_t flatnum); boolean R_CheckPowersOfTwo(void); diff --git a/src/r_things.c b/src/r_things.c index 8e3ef4079..84e3ef064 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -900,6 +900,14 @@ static void R_DrawVisSprite(vissprite_t *vis) } // Prevent an out of bounds error + // + // FIXME: The following check doesn't account for + // differences in transparency between the patches. + // + // Sprite BRIGHTMAPs should be converted on load, + // as like textures. I'm too tired to bother with it + // right now, though. + // if (bmpatch && (bmpatch->width != patch->width || bmpatch->height != patch->height)) {