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)
{
fixed_t a;
fixed_t b;
fixed_t a, 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_x = bsp->bbox[0][BOXRIGHT];
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);
max_w = minimapinfo.map_w << MAPBITS;
max_h = minimapinfo.map_h << MAPBITS;
a = FixedDiv(f_w<<FRACBITS, max_w);
b = FixedDiv(f_h<<FRACBITS, max_h);
//min_scale_mtof = a < b ? a : b;
if (a < b)
{
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);
min_scale_mtof = a < b ? a : b;
max_scale_mtof = FixedDiv(f_h<<FRACBITS, 2*PLAYERRADIUS);
}
static void AM_changeWindowLoc(void)
@ -1353,28 +1323,26 @@ void AM_Drawer(void)
if (!followplayer) AM_drawCrosshair(XHAIRCOLORS);
}
minigen_t *AM_MinimapGenerate(INT32 wh)
minigen_t *AM_MinimapGenerate(INT32 mul)
{
static minigen_t ret = {0};
if (automapactive)
return NULL;
ret.w = ret.h = 0;
ret.buf = NULL;
am_minigen = true;
AM_drawFline = AM_drawFline_soft; // yes, even in GL
//AM_FrameBufferInit();
f_x = f_y = 0;
f_w = f_h = wh;
am_buf = NULL;
ret.w = f_w = minimapinfo.minimap_w * mul;
ret.h = f_h = minimapinfo.minimap_h * mul;
am_buf = ret.buf = NULL;
//AM_LevelInit();
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);
//AM_initVariables();
@ -1399,8 +1367,6 @@ minigen_t *AM_MinimapGenerate(INT32 wh)
old_m_w = m_w;
old_m_h = m_h;
ret.w = f_w;
ret.h = f_h;
am_buf = ret.buf = malloc((f_w*f_h));
if (ret.buf == NULL)

View file

@ -55,7 +55,7 @@ struct minigen_t
};
// Minimap generation
minigen_t *AM_MinimapGenerate(INT32 wh);
minigen_t *AM_MinimapGenerate(INT32 mul);
#ifdef __cplusplus
} // 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.
// 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;
INT32 amxpos, amypos;
node_t *bsp = &nodes[numnodes-1];
fixed_t maxx, minx, maxy, miny;
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));
amnumxpos = (FixedMul(objx, minimapinfo.zoom) - minimapinfo.offs_x);
amnumypos = -(FixedMul(objy, minimapinfo.zoom) - minimapinfo.offs_y);
if (encoremode)
amnumxpos = -amnumxpos;
amxpos = amnumxpos + ((hudx + AutomapPic->width/2 - (icon->width/2))<<FRACBITS);
amypos = amnumypos + ((hudy + AutomapPic->height/2 - (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);
}*/
amxpos = amnumxpos + ((hudx + (SHORT(minimapinfo.minimap_pic->width)-SHORT(icon->width))/2)<<FRACBITS);
amypos = amnumypos + ((hudy + (SHORT(minimapinfo.minimap_pic->height)-SHORT(icon->height))/2)<<FRACBITS);
V_DrawFixedPatch(amxpos, amypos, FRACUNIT, flags, icon, colormap);
}
static void K_drawKartMinimap(void)
{
patch_t *AutomapPic, *workingPic;
patch_t *workingPic;
INT32 i = 0;
INT32 x, y;
INT32 minimaptrans = 4;
@ -3829,9 +3781,7 @@ static void K_drawKartMinimap(void)
if (stplyr != &players[displayplayers[0]])
return;
AutomapPic = mapheaderinfo[gamemap-1]->minimapPic;
if (!AutomapPic)
if (minimapinfo.minimap_pic == NULL)
{
return; // no pic, just get outta here
}
@ -3854,28 +3804,25 @@ static void K_drawKartMinimap(void)
if (!minimaptrans)
return;
x = MINI_X - (AutomapPic->width/2);
y = MINI_Y - (AutomapPic->height/2);
x = MINI_X - (SHORT(minimapinfo.minimap_pic->width)/2);
y = MINI_Y - (SHORT(minimapinfo.minimap_pic->height)/2);
minimaptrans = ((10-minimaptrans)<<FF_TRANSSHIFT);
splitflags |= minimaptrans;
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
V_DrawScaledPatch(x, y, splitflags, AutomapPic);
V_DrawScaledPatch(x, y, splitflags|minimaptrans, minimapinfo.minimap_pic);
{
splitflags &= ~minimaptrans;
splitflags |= V_HUDTRANSHALF;
}
// most icons will be rendered semi-ghostly.
splitflags |= V_HUDTRANSHALF;
// let offsets transfer to the heads, too!
if (encoremode)
x += SHORT(AutomapPic->leftoffset);
x += SHORT(minimapinfo.minimap_pic->leftoffset);
else
x -= SHORT(AutomapPic->leftoffset);
y -= SHORT(AutomapPic->topoffset);
x -= SHORT(minimapinfo.minimap_pic->leftoffset);
y -= SHORT(minimapinfo.minimap_pic->topoffset);
// Draw the super item in Battle
if ((gametyperules & GTR_OVERTIME) && battleovertime.enabled)
@ -3886,7 +3833,7 @@ static void K_drawKartMinimap(void)
splitflags &= ~V_HUDTRANSHALF;
splitflags |= V_HUDTRANS;
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;
}
}
@ -3918,7 +3865,7 @@ static void K_drawKartMinimap(void)
interpx = R_InterpolateFixed(g->mo->old_x, g->mo->x);
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;
}
@ -3985,13 +3932,13 @@ static void K_drawKartMinimap(void)
interpx = R_InterpolateFixed(mobj->old_x, mobj->x);
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
if (((gametyperules & GTR_CIRCUIT) && players[i].position == spbplace)
|| ((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);
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.
@ -4070,7 +4017,7 @@ static void K_drawKartMinimap(void)
interpy = R_InterpolateFixed(bossinfo.weakspots[i].spot->old_y, bossinfo.weakspots[i].spot->y);
// 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);
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
if (((gametyperules & GTR_CIRCUIT) && players[localplayers[i]].position == spbplace)
|| ((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;
boolean ret = false;
minigen_t *minigen = NULL;
INT32 wh = 100;
size_t option_scale;
INT32 mul = 1;
@ -1793,7 +1792,6 @@ void M_MinimapGenerate(void)
return;
}
wh *= mul;
filepath = va("%s" PATHSEP "MINIMAP-%d.png", srb2home, mul);
}
else
@ -1801,7 +1799,7 @@ void M_MinimapGenerate(void)
filepath = va("%s" PATHSEP "MINIMAP.png", srb2home);
}
minigen = AM_MinimapGenerate(wh);
minigen = AM_MinimapGenerate(mul);
if (minigen == NULL || minigen->buf == NULL)
goto failure;

View file

@ -504,6 +504,18 @@ extern fixed_t bmaporgx;
extern fixed_t bmaporgy; // origin of block map
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
//

View file

@ -7345,6 +7345,68 @@ static void P_InitGametype(void)
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.
*
* \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_InitMinimapInfo();
for (numcoopstarts = 0; numcoopstarts < MAXPLAYERS; numcoopstarts++)
if (!playerstarts[numcoopstarts])
break;