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;
}
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[]
static int lib_getSpriteInfo(lua_State *L)
{
@ -454,23 +468,15 @@ static int lib_spriteinfolen(lua_State *L)
// spriteinfo_t
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);
I_Assert(sprinfo != NULL);
luaL_checkudata(L, 1, META_SPRITEINFO);
// push spriteframepivot_t userdata
if (fastcmp(field, "pivot"))
{
// bypass LUA_PushUserdata
void **userdata = lua_newuserdata(L, sizeof(void *));
*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;
}
return PushCast(L, META_PIVOTLIST);
else if (fastcmp(field, "brightmap"))
return PushCast(L, META_SPRITEBRIGHTLIST);
else
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;
}
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 //
////////////////
@ -2033,6 +2062,17 @@ int LUA_InfoLib(lua_State *L)
lua_setfield(L, -2, "__len");
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);
lua_pushcfunction(L, precipprops_get);
lua_setfield(L, -2, "__index");

View file

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

View file

@ -1474,9 +1474,10 @@ static void R_ParseSpriteInfoFrame(struct ParseSpriteInfoState *parser, boolean
size_t sprinfoTokenLength;
char *frameChar = NULL;
UINT8 frameFrame = 0xFF;
INT16 frameXPivot = 0;
INT16 frameYPivot = 0;
INT16 frameXPivot = INT16_MIN;
INT16 frameYPivot = INT16_MIN;
rotaxis_t frameRotAxis = 0;
char *bright = NULL;
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))
frameRotAxis = ROTAXIS_Z;
}
else if (stricmp(sprinfoToken, "BRIGHTMAP")==0)
{
Z_Free(bright);
bright = M_GetToken(NULL);
}
Z_Free(sprinfoToken);
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].y = frameYPivot;
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)
{

View file

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

View file

@ -862,12 +862,13 @@ UINT8 *R_GetSpriteTranslation(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);
INT32 texturecolumn;
INT32 pwidth;
fixed_t frac;
patch_t *patch = vis->patch;
patch_t *bmpatch = vis->bright;
fixed_t this_scale = vis->thingscale;
INT32 x1, x2;
INT64 overflow_test;
@ -888,6 +889,13 @@ static void R_DrawVisSprite(vissprite_t *vis)
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.
dc_colormap = vis->colormap;
dc_fullbright = colormaps;
@ -1022,7 +1030,10 @@ static void R_DrawVisSprite(vissprite_t *vis)
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)
@ -1034,17 +1045,18 @@ static void R_DrawVisSprite(vissprite_t *vis)
// 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;
#ifdef RANGECHECK
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
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));
localcolfunc (column, NULL, baseclip);
localcolfunc (column, bmcol, baseclip);
}
}
else
@ -1056,15 +1068,18 @@ static void R_DrawVisSprite(vissprite_t *vis)
// Non-paper drawing loop
for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan)
{
#ifdef RANGECHECK
texturecolumn = frac>>FRACBITS;
#ifdef RANGECHECK
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
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)
{
column_t *column;
#ifdef RANGECHECK
INT32 texturecolumn;
#endif
fixed_t frac;
patch_t *patch;
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)
{
#ifdef RANGECHECK
texturecolumn = frac>>FRACBITS;
#ifdef RANGECHECK
if (texturecolumn < 0 || texturecolumn >= patch->width)
I_Error("R_DrawPrecipitationSpriteRange: bad texturecolumn");
#endif
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);
}
@ -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)
// Get the first visible floor below the object for shadows
@ -1400,6 +1424,7 @@ static void R_ProjectDropShadow(
shadow = R_NewVisSprite();
shadow->patch = patch;
shadow->bright = NULL;
shadow->heightsec = vis->heightsec;
shadow->mobjflags = 0;
@ -2325,6 +2350,7 @@ static void R_ProjectSprite(mobj_t *thing)
vis->cut |= SC_SPLAT; // I like ya cut g
vis->patch = patch;
vis->bright = R_CacheSpriteBrightMap(sprinfo, frame);
if (thing->subsector->sector->numlights && !(shadowdraw || splat))
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
// than lumpid for sprites-in-pwad : the graphics are patched
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);

View file

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