Precalculate as much shared minimap/automap data on level load as possible

- `P_InitMinimapInfo`
    - Writes to `p_local.h` extern struct
    - Handles everything previously distributed across multiple K_drawKartMinimapIcon calls (and most of AM_findMinMaxBoundaries)
- Reduces complexity of drawKartMinimapIcon significantly
- Last prerequisite before implementing user-placable minimap boundaries...
This commit is contained in:
toaster 2023-01-24 14:46:25 +00:00
parent 16d6837112
commit 223531ffce
6 changed files with 116 additions and 129 deletions

View file

@ -255,51 +255,21 @@ static inline void AM_restoreScaleAndLoc(void)
*/ */
static void AM_findMinMaxBoundaries(void) static void AM_findMinMaxBoundaries(void)
{ {
fixed_t a; fixed_t a, b;
fixed_t b;
node_t *bsp = &nodes[numnodes-1]; min_x = minimapinfo.min_x << MAPBITS;
max_x = minimapinfo.max_x << MAPBITS;
min_y = minimapinfo.min_y << MAPBITS;
max_y = minimapinfo.max_y << MAPBITS;
min_x = bsp->bbox[0][BOXLEFT]; max_w = minimapinfo.map_w << MAPBITS;
max_x = bsp->bbox[0][BOXRIGHT]; max_h = minimapinfo.map_h << MAPBITS;
min_y = bsp->bbox[0][BOXBOTTOM];
max_y = bsp->bbox[0][BOXTOP];
if (bsp->bbox[1][BOXLEFT] < min_x)
min_x = bsp->bbox[1][BOXLEFT];
if (bsp->bbox[1][BOXRIGHT] > max_x)
max_x = bsp->bbox[1][BOXRIGHT];
if (bsp->bbox[1][BOXBOTTOM] < min_y)
min_y = bsp->bbox[1][BOXBOTTOM];
if (bsp->bbox[1][BOXTOP] > max_y)
max_y = bsp->bbox[1][BOXTOP];
max_w = (max_x >>= FRACTOMAPBITS) - (min_x >>= FRACTOMAPBITS);
max_h = (max_y >>= FRACTOMAPBITS) - (min_y >>= FRACTOMAPBITS);
a = FixedDiv(f_w<<FRACBITS, max_w); a = FixedDiv(f_w<<FRACBITS, max_w);
b = FixedDiv(f_h<<FRACBITS, max_h); b = FixedDiv(f_h<<FRACBITS, max_h);
//min_scale_mtof = a < b ? a : b; min_scale_mtof = a < b ? a : b;
if (a < b) max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
{
if (am_minigen)
{
f_h = FixedMul(a, max_h)>>FRACBITS;
}
min_scale_mtof = a;
max_scale_mtof = f_h;
}
else
{
if (am_minigen)
{
f_w = FixedMul(b, max_w)>>FRACBITS;
}
min_scale_mtof = b;
max_scale_mtof = f_w;
}
max_scale_mtof = FixedDiv(max_scale_mtof<<FRACBITS, 2*PLAYERRADIUS);
} }
static void AM_changeWindowLoc(void) static void AM_changeWindowLoc(void)
@ -1353,28 +1323,26 @@ void AM_Drawer(void)
if (!followplayer) AM_drawCrosshair(XHAIRCOLORS); if (!followplayer) AM_drawCrosshair(XHAIRCOLORS);
} }
minigen_t *AM_MinimapGenerate(INT32 wh) minigen_t *AM_MinimapGenerate(INT32 mul)
{ {
static minigen_t ret = {0}; static minigen_t ret = {0};
if (automapactive) if (automapactive)
return NULL; return NULL;
ret.w = ret.h = 0;
ret.buf = NULL;
am_minigen = true; am_minigen = true;
AM_drawFline = AM_drawFline_soft; // yes, even in GL AM_drawFline = AM_drawFline_soft; // yes, even in GL
//AM_FrameBufferInit(); //AM_FrameBufferInit();
f_x = f_y = 0; f_x = f_y = 0;
f_w = f_h = wh; ret.w = f_w = minimapinfo.minimap_w * mul;
am_buf = NULL; ret.h = f_h = minimapinfo.minimap_h * mul;
am_buf = ret.buf = NULL;
//AM_LevelInit(); //AM_LevelInit();
AM_findMinMaxBoundaries(); AM_findMinMaxBoundaries();
scale_mtof = FixedMul(min_scale_mtof, FRACUNIT-FRACUNIT/20); scale_mtof = min_scale_mtof - (min_scale_mtof/20);
scale_ftom = FixedDiv(FRACUNIT, scale_mtof); scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
//AM_initVariables(); //AM_initVariables();
@ -1399,8 +1367,6 @@ minigen_t *AM_MinimapGenerate(INT32 wh)
old_m_w = m_w; old_m_w = m_w;
old_m_h = m_h; old_m_h = m_h;
ret.w = f_w;
ret.h = f_h;
am_buf = ret.buf = malloc((f_w*f_h)); am_buf = ret.buf = malloc((f_w*f_h));
if (ret.buf == NULL) if (ret.buf == NULL)

View file

@ -55,7 +55,7 @@ struct minigen_t
}; };
// Minimap generation // Minimap generation
minigen_t *AM_MinimapGenerate(INT32 wh); minigen_t *AM_MinimapGenerate(INT32 mul);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"

View file

@ -3733,7 +3733,7 @@ static void K_drawKartNameTags(void)
} }
} }
static void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hudy, INT32 flags, patch_t *icon, UINT8 *colormap, patch_t *AutomapPic) static void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, INT32 hudy, INT32 flags, patch_t *icon, UINT8 *colormap)
{ {
// amnum xpos & ypos are the icon's speed around the HUD. // amnum xpos & ypos are the icon's speed around the HUD.
// The number being divided by is for how fast it moves. // The number being divided by is for how fast it moves.
@ -3745,69 +3745,21 @@ static void K_drawKartMinimapIcon(fixed_t objx, fixed_t objy, INT32 hudx, INT32
fixed_t amnumxpos, amnumypos; fixed_t amnumxpos, amnumypos;
INT32 amxpos, amypos; INT32 amxpos, amypos;
node_t *bsp = &nodes[numnodes-1]; amnumxpos = (FixedMul(objx, minimapinfo.zoom) - minimapinfo.offs_x);
fixed_t maxx, minx, maxy, miny; amnumypos = -(FixedMul(objy, minimapinfo.zoom) - minimapinfo.offs_y);
fixed_t mapwidth, mapheight;
fixed_t xoffset, yoffset;
fixed_t xscale, yscale, zoom;
minx = bsp->bbox[0][BOXLEFT];
maxx = bsp->bbox[0][BOXRIGHT];
miny = bsp->bbox[0][BOXBOTTOM];
maxy = bsp->bbox[0][BOXTOP];
if (bsp->bbox[1][BOXLEFT] < minx)
minx = bsp->bbox[1][BOXLEFT];
if (bsp->bbox[1][BOXRIGHT] > maxx)
maxx = bsp->bbox[1][BOXRIGHT];
if (bsp->bbox[1][BOXBOTTOM] < miny)
miny = bsp->bbox[1][BOXBOTTOM];
if (bsp->bbox[1][BOXTOP] > maxy)
maxy = bsp->bbox[1][BOXTOP];
// You might be wondering why these are being bitshift here
// it's because mapwidth and height would otherwise overflow for maps larger than half the size possible...
// map boundaries and sizes will ALWAYS be whole numbers thankfully
// later calculations take into consideration that these are actually not in terms of FRACUNIT though
minx >>= FRACBITS;
maxx >>= FRACBITS;
miny >>= FRACBITS;
maxy >>= FRACBITS;
mapwidth = maxx - minx;
mapheight = maxy - miny;
// These should always be small enough to be bitshift back right now
xoffset = (minx + mapwidth/2)<<FRACBITS;
yoffset = (miny + mapheight/2)<<FRACBITS;
xscale = FixedDiv(AutomapPic->width, mapwidth);
yscale = FixedDiv(AutomapPic->height, mapheight);
zoom = FixedMul(min(xscale, yscale), FRACUNIT-FRACUNIT/20);
amnumxpos = (FixedMul(objx, zoom) - FixedMul(xoffset, zoom));
amnumypos = -(FixedMul(objy, zoom) - FixedMul(yoffset, zoom));
if (encoremode) if (encoremode)
amnumxpos = -amnumxpos; amnumxpos = -amnumxpos;
amxpos = amnumxpos + ((hudx + AutomapPic->width/2 - (icon->width/2))<<FRACBITS); amxpos = amnumxpos + ((hudx + (SHORT(minimapinfo.minimap_pic->width)-SHORT(icon->width))/2)<<FRACBITS);
amypos = amnumypos + ((hudy + AutomapPic->height/2 - (icon->height/2))<<FRACBITS); amypos = amnumypos + ((hudy + (SHORT(minimapinfo.minimap_pic->height)-SHORT(icon->height))/2)<<FRACBITS);
// do we want this? it feels unnecessary. easier to just modify the amnumxpos?
/*if (encoremode)
{
flags |= V_FLIP;
amxpos = -amnumxpos + ((hudx + AutomapPic->width/2 + (icon->width/2))<<FRACBITS);
}*/
V_DrawFixedPatch(amxpos, amypos, FRACUNIT, flags, icon, colormap); V_DrawFixedPatch(amxpos, amypos, FRACUNIT, flags, icon, colormap);
} }
static void K_drawKartMinimap(void) static void K_drawKartMinimap(void)
{ {
patch_t *AutomapPic, *workingPic; patch_t *workingPic;
INT32 i = 0; INT32 i = 0;
INT32 x, y; INT32 x, y;
INT32 minimaptrans = 4; INT32 minimaptrans = 4;
@ -3829,9 +3781,7 @@ static void K_drawKartMinimap(void)
if (stplyr != &players[displayplayers[0]]) if (stplyr != &players[displayplayers[0]])
return; return;
AutomapPic = mapheaderinfo[gamemap-1]->minimapPic; if (minimapinfo.minimap_pic == NULL)
if (!AutomapPic)
{ {
return; // no pic, just get outta here return; // no pic, just get outta here
} }
@ -3854,28 +3804,25 @@ static void K_drawKartMinimap(void)
if (!minimaptrans) if (!minimaptrans)
return; return;
x = MINI_X - (AutomapPic->width/2); x = MINI_X - (SHORT(minimapinfo.minimap_pic->width)/2);
y = MINI_Y - (AutomapPic->height/2); y = MINI_Y - (SHORT(minimapinfo.minimap_pic->height)/2);
minimaptrans = ((10-minimaptrans)<<FF_TRANSSHIFT); minimaptrans = ((10-minimaptrans)<<FF_TRANSSHIFT);
splitflags |= minimaptrans;
if (encoremode) if (encoremode)
V_DrawScaledPatch(x+(AutomapPic->width), y, splitflags|V_FLIP, AutomapPic); V_DrawScaledPatch(x+SHORT(minimapinfo.minimap_pic->width), y, splitflags|minimaptrans|V_FLIP, minimapinfo.minimap_pic);
else else
V_DrawScaledPatch(x, y, splitflags, AutomapPic); V_DrawScaledPatch(x, y, splitflags|minimaptrans, minimapinfo.minimap_pic);
{ // most icons will be rendered semi-ghostly.
splitflags &= ~minimaptrans; splitflags |= V_HUDTRANSHALF;
splitflags |= V_HUDTRANSHALF;
}
// let offsets transfer to the heads, too! // let offsets transfer to the heads, too!
if (encoremode) if (encoremode)
x += SHORT(AutomapPic->leftoffset); x += SHORT(minimapinfo.minimap_pic->leftoffset);
else else
x -= SHORT(AutomapPic->leftoffset); x -= SHORT(minimapinfo.minimap_pic->leftoffset);
y -= SHORT(AutomapPic->topoffset); y -= SHORT(minimapinfo.minimap_pic->topoffset);
// Draw the super item in Battle // Draw the super item in Battle
if ((gametyperules & GTR_OVERTIME) && battleovertime.enabled) if ((gametyperules & GTR_OVERTIME) && battleovertime.enabled)
@ -3886,7 +3833,7 @@ static void K_drawKartMinimap(void)
splitflags &= ~V_HUDTRANSHALF; splitflags &= ~V_HUDTRANSHALF;
splitflags |= V_HUDTRANS; splitflags |= V_HUDTRANS;
colormap = R_GetTranslationColormap(TC_RAINBOW, K_RainbowColor(leveltime), GTC_CACHE); colormap = R_GetTranslationColormap(TC_RAINBOW, K_RainbowColor(leveltime), GTC_CACHE);
K_drawKartMinimapIcon(battleovertime.x, battleovertime.y, x, y, splitflags, kp_itemminimap, colormap, AutomapPic); K_drawKartMinimapIcon(battleovertime.x, battleovertime.y, x, y, splitflags, kp_itemminimap, colormap);
splitflags = prevsplitflags; splitflags = prevsplitflags;
} }
} }
@ -3918,7 +3865,7 @@ static void K_drawKartMinimap(void)
interpx = R_InterpolateFixed(g->mo->old_x, g->mo->x); interpx = R_InterpolateFixed(g->mo->old_x, g->mo->x);
interpy = R_InterpolateFixed(g->mo->old_y, g->mo->y); interpy = R_InterpolateFixed(g->mo->old_y, g->mo->y);
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap);
g = g->next; g = g->next;
} }
@ -3985,13 +3932,13 @@ static void K_drawKartMinimap(void)
interpx = R_InterpolateFixed(mobj->old_x, mobj->x); interpx = R_InterpolateFixed(mobj->old_x, mobj->x);
interpy = R_InterpolateFixed(mobj->old_y, mobj->y); interpy = R_InterpolateFixed(mobj->old_y, mobj->y);
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap);
// Target reticule // Target reticule
if (((gametyperules & GTR_CIRCUIT) && players[i].position == spbplace) if (((gametyperules & GTR_CIRCUIT) && players[i].position == spbplace)
|| ((gametyperules & (GTR_BOSS|GTR_POINTLIMIT)) == GTR_POINTLIMIT && K_IsPlayerWanted(&players[i]))) || ((gametyperules & (GTR_BOSS|GTR_POINTLIMIT)) == GTR_POINTLIMIT && K_IsPlayerWanted(&players[i])))
{ {
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL);
} }
} }
} }
@ -4037,7 +3984,7 @@ static void K_drawKartMinimap(void)
interpx = R_InterpolateFixed(mobj->old_x, mobj->x); interpx = R_InterpolateFixed(mobj->old_x, mobj->x);
interpy = R_InterpolateFixed(mobj->old_y, mobj->y); interpy = R_InterpolateFixed(mobj->old_y, mobj->y);
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap, AutomapPic); K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap);
} }
// draw our local players here, opaque. // draw our local players here, opaque.
@ -4070,7 +4017,7 @@ static void K_drawKartMinimap(void)
interpy = R_InterpolateFixed(bossinfo.weakspots[i].spot->old_y, bossinfo.weakspots[i].spot->y); interpy = R_InterpolateFixed(bossinfo.weakspots[i].spot->old_y, bossinfo.weakspots[i].spot->y);
// temporary graphic? // temporary graphic?
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, colormap, AutomapPic); K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, colormap);
} }
} }
@ -4112,13 +4059,13 @@ static void K_drawKartMinimap(void)
interpx = R_InterpolateFixed(mobj->old_x, mobj->x); interpx = R_InterpolateFixed(mobj->old_x, mobj->x);
interpy = R_InterpolateFixed(mobj->old_y, mobj->y); interpy = R_InterpolateFixed(mobj->old_y, mobj->y);
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap, AutomapPic); K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, workingPic, colormap);
// Target reticule // Target reticule
if (((gametyperules & GTR_CIRCUIT) && players[localplayers[i]].position == spbplace) if (((gametyperules & GTR_CIRCUIT) && players[localplayers[i]].position == spbplace)
|| ((gametyperules & (GTR_BOSS|GTR_POINTLIMIT)) == GTR_POINTLIMIT && K_IsPlayerWanted(&players[localplayers[i]]))) || ((gametyperules & (GTR_BOSS|GTR_POINTLIMIT)) == GTR_POINTLIMIT && K_IsPlayerWanted(&players[localplayers[i]])))
{ {
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_wantedreticle, NULL);
} }
} }
} }

View file

@ -1755,7 +1755,6 @@ void M_MinimapGenerate(void)
char *filepath; char *filepath;
boolean ret = false; boolean ret = false;
minigen_t *minigen = NULL; minigen_t *minigen = NULL;
INT32 wh = 100;
size_t option_scale; size_t option_scale;
INT32 mul = 1; INT32 mul = 1;
@ -1793,7 +1792,6 @@ void M_MinimapGenerate(void)
return; return;
} }
wh *= mul;
filepath = va("%s" PATHSEP "MINIMAP-%d.png", srb2home, mul); filepath = va("%s" PATHSEP "MINIMAP-%d.png", srb2home, mul);
} }
else else
@ -1801,7 +1799,7 @@ void M_MinimapGenerate(void)
filepath = va("%s" PATHSEP "MINIMAP.png", srb2home); filepath = va("%s" PATHSEP "MINIMAP.png", srb2home);
} }
minigen = AM_MinimapGenerate(wh); minigen = AM_MinimapGenerate(mul);
if (minigen == NULL || minigen->buf == NULL) if (minigen == NULL || minigen->buf == NULL)
goto failure; goto failure;

View file

@ -504,6 +504,18 @@ extern fixed_t bmaporgx;
extern fixed_t bmaporgy; // origin of block map extern fixed_t bmaporgy; // origin of block map
extern mobj_t **blocklinks; // for thing chains extern mobj_t **blocklinks; // for thing chains
extern struct minimapinfo
{
patch_t *minimap_pic;
UINT8 mapthingcount;
INT32 min_x, min_y;
INT32 max_x, max_y;
INT32 map_w, map_h;
INT32 minimap_w, minimap_h;
fixed_t offs_x, offs_y;
fixed_t zoom;
} minimapinfo;
// //
// P_INTER // P_INTER
// //

View file

@ -7345,6 +7345,68 @@ static void P_InitGametype(void)
CV_SetValue(&cv_menujam_update, 1); CV_SetValue(&cv_menujam_update, 1);
} }
struct minimapinfo minimapinfo;
static void P_InitMinimapInfo(void)
{
fixed_t a;
fixed_t b;
node_t *bsp = &nodes[numnodes-1];
minimapinfo.minimap_pic = mapheaderinfo[gamemap-1]->minimapPic;
minimapinfo.mapthingcount = 0;
// TODO iterate over mapthings to look for possible user-defined bounds
minimapinfo.min_x = bsp->bbox[0][BOXLEFT];
minimapinfo.max_x = bsp->bbox[0][BOXRIGHT];
minimapinfo.min_y = bsp->bbox[0][BOXBOTTOM];
minimapinfo.max_y = bsp->bbox[0][BOXTOP];
if (bsp->bbox[1][BOXLEFT] < minimapinfo.min_x)
minimapinfo.min_x = bsp->bbox[1][BOXLEFT];
if (bsp->bbox[1][BOXRIGHT] > minimapinfo.max_x)
minimapinfo.max_x = bsp->bbox[1][BOXRIGHT];
if (bsp->bbox[1][BOXBOTTOM] < minimapinfo.min_y)
minimapinfo.min_y = bsp->bbox[1][BOXBOTTOM];
if (bsp->bbox[1][BOXTOP] > minimapinfo.max_y)
minimapinfo.max_y = bsp->bbox[1][BOXTOP];
// You might be wondering why these are being bitshift here
// it's because mapwidth and height would otherwise overflow for maps larger than half the size possible...
// map boundaries and sizes will ALWAYS be whole numbers thankfully
// later calculations take into consideration that these are actually not in terms of FRACUNIT though
minimapinfo.map_w = (minimapinfo.max_x >>= FRACBITS) - (minimapinfo.min_x >>= FRACBITS);
minimapinfo.map_h = (minimapinfo.max_y >>= FRACBITS) - (minimapinfo.min_y >>= FRACBITS);
minimapinfo.minimap_w = minimapinfo.minimap_h = 100;
a = FixedDiv(minimapinfo.minimap_w<<FRACBITS, minimapinfo.map_w<<4);
b = FixedDiv(minimapinfo.minimap_h<<FRACBITS, minimapinfo.map_h<<4);
if (a < b)
{
minimapinfo.minimap_h = FixedMul(a, minimapinfo.map_h)>>(FRACBITS-4);
minimapinfo.zoom = a;
}
else
{
if (a != b)
{
minimapinfo.minimap_w = FixedMul(b, minimapinfo.map_w)>>(FRACBITS-4);
}
minimapinfo.zoom = b;
}
minimapinfo.zoom >>= (FRACBITS-4);
minimapinfo.zoom -= (minimapinfo.zoom/20);
// These should always be small enough to be bitshift back right now
minimapinfo.offs_x = FixedMul((minimapinfo.min_x + minimapinfo.map_w/2) << FRACBITS, minimapinfo.zoom);
minimapinfo.offs_y = FixedMul((minimapinfo.min_y + minimapinfo.map_h/2) << FRACBITS, minimapinfo.zoom);
}
/** Loads a level from a lump or external wad. /** Loads a level from a lump or external wad.
* *
* \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot. * \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot.
@ -7633,6 +7695,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
P_SpawnMapThings(!fromnetsave); P_SpawnMapThings(!fromnetsave);
P_InitMinimapInfo();
for (numcoopstarts = 0; numcoopstarts < MAXPLAYERS; numcoopstarts++) for (numcoopstarts = 0; numcoopstarts < MAXPLAYERS; numcoopstarts++)
if (!playerstarts[numcoopstarts]) if (!playerstarts[numcoopstarts])
break; break;