Merge branch 'sprite-brightmaps' into 'master'

Rudimentary sprite brightmap support

See merge request KartKrew/Kart!801
This commit is contained in:
Oni 2023-02-02 05:49:31 +00:00
commit 79796b00f5
6 changed files with 115 additions and 33 deletions

View file

@ -266,6 +266,20 @@ static UINT8 GetPivotFrame(lua_State *L, int idx)
return frame; return frame;
} }
static int PushCast(lua_State *L, const char *meta)
{
// bypass LUA_PushUserdata
void **userdata = lua_newuserdata(L, sizeof(void *));
*userdata = lua_touserdata(L, 1);
luaL_getmetatable(L, meta);
lua_setmetatable(L, -2);
// stack is left with the userdata on top, as if getting it had originally succeeded.
return 1;
}
// spriteinfo[] // spriteinfo[]
static int lib_getSpriteInfo(lua_State *L) static int lib_getSpriteInfo(lua_State *L)
{ {
@ -454,23 +468,15 @@ static int lib_spriteinfolen(lua_State *L)
// spriteinfo_t // spriteinfo_t
static int spriteinfo_get(lua_State *L) static int spriteinfo_get(lua_State *L)
{ {
spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEINFO));
const char *field = luaL_checkstring(L, 2); const char *field = luaL_checkstring(L, 2);
I_Assert(sprinfo != NULL); luaL_checkudata(L, 1, META_SPRITEINFO);
// push spriteframepivot_t userdata // push spriteframepivot_t userdata
if (fastcmp(field, "pivot")) if (fastcmp(field, "pivot"))
{ return PushCast(L, META_PIVOTLIST);
// bypass LUA_PushUserdata else if (fastcmp(field, "brightmap"))
void **userdata = lua_newuserdata(L, sizeof(void *)); return PushCast(L, META_SPRITEBRIGHTLIST);
*userdata = sprinfo;
luaL_getmetatable(L, META_PIVOTLIST);
lua_setmetatable(L, -2);
// stack is left with the userdata on top, as if getting it had originally succeeded.
return 1;
}
else else
return luaL_error(L, LUA_QL("spriteinfo_t") " has no field named " LUA_QS, field); return luaL_error(L, LUA_QL("spriteinfo_t") " has no field named " LUA_QS, field);
@ -640,6 +646,29 @@ static int framepivot_num(lua_State *L)
return 1; return 1;
} }
static int brightlist_get(lua_State *L)
{
const spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEBRIGHTLIST));
const UINT8 frame = GetPivotFrame(L, 2);
lua_pushstring(L, sprinfo->bright[frame]);
return 1;
}
static int brightlist_set(lua_State *L)
{
spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEBRIGHTLIST));
const UINT8 frame = GetPivotFrame(L, 2);
const char *val = luaL_checkstring(L, 3);
Z_Free(sprinfo->bright[frame]);
sprinfo->bright[frame] = Z_StrDup(val);
return 0;
}
//////////////// ////////////////
// STATE INFO // // STATE INFO //
//////////////// ////////////////
@ -2033,6 +2062,17 @@ int LUA_InfoLib(lua_State *L)
lua_setfield(L, -2, "__len"); lua_setfield(L, -2, "__len");
lua_pop(L, 1); lua_pop(L, 1);
luaL_newmetatable(L, META_SPRITEBRIGHTLIST);
lua_pushcfunction(L, brightlist_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, brightlist_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, pivotlist_num);
lua_setfield(L, -2, "__len");
lua_pop(L, 1);
luaL_newmetatable(L, META_PRECIPPROPS); luaL_newmetatable(L, META_PRECIPPROPS);
lua_pushcfunction(L, precipprops_get); lua_pushcfunction(L, precipprops_get);
lua_setfield(L, -2, "__index"); lua_setfield(L, -2, "__index");

View file

@ -34,6 +34,7 @@ extern lua_State *gL;
#define META_SPRITEINFO "SPRITEINFO_T*" #define META_SPRITEINFO "SPRITEINFO_T*"
#define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]" #define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]"
#define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*" #define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*"
#define META_SPRITEBRIGHTLIST "SPRITEBRIGHTMAP_T[]"
#define META_PRECIPPROPS "PRECIPPROPS_T*" #define META_PRECIPPROPS "PRECIPPROPS_T*"
#define META_TAGLIST "TAGLIST" #define META_TAGLIST "TAGLIST"

View file

@ -1474,9 +1474,10 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean
size_t sprinfoTokenLength; size_t sprinfoTokenLength;
char *frameChar = NULL; char *frameChar = NULL;
UINT8 frameFrame = 0xFF; UINT8 frameFrame = 0xFF;
INT16 frameXPivot = 0; INT16 frameXPivot = INT16_MIN;
INT16 frameYPivot = 0; INT16 frameYPivot = INT16_MIN;
rotaxis_t frameRotAxis = 0; rotaxis_t frameRotAxis = 0;
char *bright = NULL;
if (all) if (all)
{ {
@ -1541,6 +1542,11 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean
else if ((stricmp(sprinfoToken, "Z")==0) || (stricmp(sprinfoToken, "ZAXIS")==0) || (stricmp(sprinfoToken, "YAW")==0)) else if ((stricmp(sprinfoToken, "Z")==0) || (stricmp(sprinfoToken, "ZAXIS")==0) || (stricmp(sprinfoToken, "YAW")==0))
frameRotAxis = ROTAXIS_Z; frameRotAxis = ROTAXIS_Z;
} }
else if (stricmp(sprinfoToken, "BRIGHTMAP")==0)
{
Z_Free(bright);
bright = M_GetToken(NULL);
}
Z_Free(sprinfoToken); Z_Free(sprinfoToken);
sprinfoToken = M_GetToken(NULL); sprinfoToken = M_GetToken(NULL);
@ -1557,8 +1563,13 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean
parser->info->pivot[frameFrame].x = frameXPivot; parser->info->pivot[frameFrame].x = frameXPivot;
parser->info->pivot[frameFrame].y = frameYPivot; parser->info->pivot[frameFrame].y = frameYPivot;
parser->info->pivot[frameFrame].rotaxis = frameRotAxis; parser->info->pivot[frameFrame].rotaxis = frameRotAxis;
Z_Free(parser->info->bright[frameFrame]);
parser->info->bright[frameFrame] = bright;
set_bit_array(parser->info->available, frameFrame); if (frameXPivot != INT16_MIN || frameYPivot != INT16_MIN)
{
set_bit_array(parser->info->available, frameFrame);
}
if (parser->spr2) if (parser->spr2)
{ {

View file

@ -107,6 +107,7 @@ struct spriteinfo_t
spriteframepivot_t pivot[64 + 1]; spriteframepivot_t pivot[64 + 1];
#define SPRINFO_DEFAULT_PIVOT (64) #define SPRINFO_DEFAULT_PIVOT (64)
UINT8 available[BIT_ARRAY_SIZE(64 + 1)]; // 1 extra for default_pivot UINT8 available[BIT_ARRAY_SIZE(64 + 1)]; // 1 extra for default_pivot
char *bright[64 + 1]; // brightmap lump name
}; };
// Portable Network Graphics // Portable Network Graphics

View file

@ -862,12 +862,13 @@ UINT8 *R_GetSpriteTranslation(vissprite_t *vis)
// //
static void R_DrawVisSprite(vissprite_t *vis) static void R_DrawVisSprite(vissprite_t *vis)
{ {
column_t *column; column_t *column, *bmcol = NULL;
void (*localcolfunc)(column_t *, column_t *, INT32); void (*localcolfunc)(column_t *, column_t *, INT32);
INT32 texturecolumn; INT32 texturecolumn;
INT32 pwidth; INT32 pwidth;
fixed_t frac; fixed_t frac;
patch_t *patch = vis->patch; patch_t *patch = vis->patch;
patch_t *bmpatch = vis->bright;
fixed_t this_scale = vis->thingscale; fixed_t this_scale = vis->thingscale;
INT32 x1, x2; INT32 x1, x2;
INT64 overflow_test; INT64 overflow_test;
@ -888,6 +889,13 @@ static void R_DrawVisSprite(vissprite_t *vis)
if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto
} }
// Prevent an out of bounds error
if (bmpatch && (bmpatch->width != patch->width ||
bmpatch->height != patch->height))
{
return;
}
R_SetColumnFunc(BASEDRAWFUNC, false); // hack: this isn't resetting properly somewhere. R_SetColumnFunc(BASEDRAWFUNC, false); // hack: this isn't resetting properly somewhere.
dc_colormap = vis->colormap; dc_colormap = vis->colormap;
dc_fullbright = colormaps; dc_fullbright = colormaps;
@ -1022,7 +1030,10 @@ static void R_DrawVisSprite(vissprite_t *vis)
column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn]));
localcolfunc (column, NULL, baseclip); if (bmpatch)
bmcol = (column_t *)((UINT8 *)bmpatch->columns + (bmpatch->columnofs[texturecolumn]));
localcolfunc (column, bmcol, baseclip);
} }
} }
else if (vis->cut & SC_SHEAR) else if (vis->cut & SC_SHEAR)
@ -1034,17 +1045,18 @@ static void R_DrawVisSprite(vissprite_t *vis)
// Vertically sheared sprite // Vertically sheared sprite
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, dc_texturemid -= vis->shear.tan) for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, dc_texturemid -= vis->shear.tan)
{ {
#ifdef RANGECHECK
texturecolumn = frac>>FRACBITS; texturecolumn = frac>>FRACBITS;
#ifdef RANGECHECK
if (texturecolumn < 0 || texturecolumn >= pwidth) if (texturecolumn < 0 || texturecolumn >= pwidth)
I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); 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 #endif
column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn]));
if (bmpatch)
bmcol = (column_t *)((UINT8 *)bmpatch->columns + (bmpatch->columnofs[texturecolumn]));
sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale));
localcolfunc (column, NULL, baseclip); localcolfunc (column, bmcol, baseclip);
} }
} }
else else
@ -1056,15 +1068,18 @@ static void R_DrawVisSprite(vissprite_t *vis)
// Non-paper drawing loop // Non-paper drawing loop
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan) for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan)
{ {
#ifdef RANGECHECK
texturecolumn = frac>>FRACBITS; texturecolumn = frac>>FRACBITS;
#ifdef RANGECHECK
if (texturecolumn < 0 || texturecolumn >= pwidth) if (texturecolumn < 0 || texturecolumn >= pwidth)
I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); 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 #endif
localcolfunc (column, NULL, baseclip); column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn]));
if (bmpatch)
bmcol = (column_t *)((UINT8 *)bmpatch->columns + (bmpatch->columnofs[texturecolumn]));
localcolfunc (column, bmcol, baseclip);
} }
} }
@ -1079,9 +1094,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
static void R_DrawPrecipitationVisSprite(vissprite_t *vis) static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
{ {
column_t *column; column_t *column;
#ifdef RANGECHECK
INT32 texturecolumn; INT32 texturecolumn;
#endif
fixed_t frac; fixed_t frac;
patch_t *patch; patch_t *patch;
fixed_t this_scale = vis->thingscale; fixed_t this_scale = vis->thingscale;
@ -1128,16 +1141,15 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale)
{ {
#ifdef RANGECHECK
texturecolumn = frac>>FRACBITS; texturecolumn = frac>>FRACBITS;
#ifdef RANGECHECK
if (texturecolumn < 0 || texturecolumn >= patch->width) if (texturecolumn < 0 || texturecolumn >= patch->width)
I_Error("R_DrawPrecipitationSpriteRange: bad texturecolumn"); I_Error("R_DrawPrecipitationSpriteRange: bad texturecolumn");
#endif
column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn])); column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[texturecolumn]));
#else
column = (column_t *)((UINT8 *)patch->columns + (patch->columnofs[frac>>FRACBITS]));
#endif
R_DrawMaskedColumn(column, NULL, -1); R_DrawMaskedColumn(column, NULL, -1);
} }
@ -1224,6 +1236,18 @@ static void R_SplitSprite(vissprite_t *sprite)
} }
} }
static patch_t *R_CacheSpriteBrightMap(const spriteinfo_t *sprinfo, UINT8 frame)
{
const char *name = sprinfo->bright[frame];
if (name == NULL)
{
name = sprinfo->bright[SPRINFO_DEFAULT_PIVOT];
}
return W_CachePatchNum(W_CheckNumForLongName(name), PU_SPRITE);
}
// //
// R_GetShadowZ(thing, shadowslope) // R_GetShadowZ(thing, shadowslope)
// Get the first visible floor below the object for shadows // Get the first visible floor below the object for shadows
@ -1400,6 +1424,7 @@ static void R_ProjectDropShadow(
shadow = R_NewVisSprite(); shadow = R_NewVisSprite();
shadow->patch = patch; shadow->patch = patch;
shadow->bright = NULL;
shadow->heightsec = vis->heightsec; shadow->heightsec = vis->heightsec;
shadow->mobjflags = 0; shadow->mobjflags = 0;
@ -2325,6 +2350,7 @@ static void R_ProjectSprite(mobj_t *thing)
vis->cut |= SC_SPLAT; // I like ya cut g vis->cut |= SC_SPLAT; // I like ya cut g
vis->patch = patch; vis->patch = patch;
vis->bright = R_CacheSpriteBrightMap(sprinfo, frame);
if (thing->subsector->sector->numlights && !(shadowdraw || splat)) if (thing->subsector->sector->numlights && !(shadowdraw || splat))
R_SplitSprite(vis); R_SplitSprite(vis);
@ -2508,6 +2534,8 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
//Fab: lumppat is the lump number of the patch to use, this is different //Fab: lumppat is the lump number of the patch to use, this is different
// than lumpid for sprites-in-pwad : the graphics are patched // than lumpid for sprites-in-pwad : the graphics are patched
vis->patch = W_CachePatchNum(sprframe->lumppat[0], PU_SPRITE); vis->patch = W_CachePatchNum(sprframe->lumppat[0], PU_SPRITE);
vis->bright = R_CacheSpriteBrightMap(&spriteinfo[thing->sprite],
thing->frame & FF_FRAMEMASK);
vis->transmap = R_GetBlendTable(blendmode, trans); vis->transmap = R_GetBlendTable(blendmode, trans);

View file

@ -190,6 +190,7 @@ struct vissprite_t
fixed_t texturemid; fixed_t texturemid;
patch_t *patch; patch_t *patch;
patch_t *bright;
lighttable_t *colormap; // for color translation and shadow draw lighttable_t *colormap; // for color translation and shadow draw
// maxbright frames as well // maxbright frames as well