Merge branch 'blockmap-precip' into 'master'

Render precip through blockmap instead of during BSP

See merge request KartKrew/Kart!1147
This commit is contained in:
toaster 2023-04-08 11:21:23 +00:00
commit 94e3803eb0
10 changed files with 165 additions and 65 deletions

View file

@ -69,6 +69,7 @@ struct hwdriver_s hwdriver;
static void HWR_AddSprites(sector_t *sec);
static void HWR_ProjectSprite(mobj_t *thing);
#ifdef HWPRECIP
static void HWR_AddPrecipitationSprites(void);
static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
#endif
static void HWR_ProjectBoundingBox(mobj_t *thing);
@ -5052,9 +5053,6 @@ static UINT8 sectorlight;
static void HWR_AddSprites(sector_t *sec)
{
mobj_t *thing;
#ifdef HWPRECIP
precipmobj_t *precipthing;
#endif
fixed_t limit_dist;
// BSP is traversed by subsector.
@ -5085,19 +5083,45 @@ static void HWR_AddSprites(sector_t *sec)
HWR_ProjectBoundingBox(thing);
}
}
}
#ifdef HWPRECIP
// --------------------------------------------------------------------------
// HWR_AddPrecipitationSprites
// This renders through the blockmap instead of BSP to avoid
// iterating a huge amount of precipitation sprites in sectors
// that are beyond drawdist.
// --------------------------------------------------------------------------
static void HWR_AddPrecipitationSprites(void)
{
const fixed_t drawdist = cv_drawdist_precip.value * mapobjectscale;
INT32 xl, xh, yl, yh, bx, by;
precipmobj_t *th;
// no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off
if ((limit_dist = (fixed_t)cv_drawdist_precip.value * mapobjectscale))
if (drawdist == 0)
{
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
return;
}
R_GetRenderBlockMapDimensions(drawdist, &xl, &xh, &yl, &yh);
for (bx = xl; bx <= xh; bx++)
{
for (by = yl; by <= yh; by++)
{
if (R_PrecipThingVisible(precipthing, limit_dist))
HWR_ProjectPrecipitationSprite(precipthing);
for (th = precipblocklinks[(by * bmapwidth) + bx]; th; th = th->bnext)
{
if (R_PrecipThingVisible(th))
{
HWR_ProjectPrecipitationSprite(th);
}
}
}
}
#endif
}
#endif
// --------------------------------------------------------------------------
// HWR_ProjectSprite
@ -6315,6 +6339,10 @@ static void HWR_RenderViewpoint(player_t *player, boolean drawSkyTexture, boolea
HWR_RenderBSPNode((INT32)numnodes-1);
#ifdef HWPRECIP
HWR_AddPrecipitationSprites();
#endif
#ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook
viewangle = localaiming[viewssnum];

View file

@ -510,6 +510,7 @@ extern INT32 bmapheight; // in mapblocks
extern fixed_t bmaporgx;
extern fixed_t bmaporgy; // origin of block map
extern mobj_t **blocklinks; // for thing chains
extern precipmobj_t **precipblocklinks; // special blockmap for precip rendering
extern struct minimapinfo
{

View file

@ -1006,15 +1006,45 @@ void P_UnsetThingPosition(mobj_t *thing)
void P_UnsetPrecipThingPosition(precipmobj_t *thing)
{
precipmobj_t **sprev = thing->sprev;
precipmobj_t *snext = thing->snext;
if ((*sprev = snext) != NULL) // unlink from sector list
snext->sprev = sprev;
precipmobj_t **bprev = thing->bprev;
precipmobj_t *bnext = thing->bnext;
if (bprev && (*bprev = bnext) != NULL) // unlink from block map
bnext->bprev = bprev;
precipsector_list = thing->touching_sectorlist;
thing->touching_sectorlist = NULL; //to be restored by P_SetPrecipThingPosition
}
static void P_LinkToBlockMap(mobj_t *thing, mobj_t **bmap)
{
const INT32 blockx = (unsigned)(thing->x - bmaporgx) >> MAPBLOCKSHIFT;
const INT32 blocky = (unsigned)(thing->y - bmaporgy) >> MAPBLOCKSHIFT;
if (blockx >= 0 && blockx < bmapwidth
&& blocky >= 0 && blocky < bmapheight)
{
// killough 8/11/98: simpler scheme using
// pointer-to-pointer prev pointers --
// allows head nodes to be treated like everything else
mobj_t **link = &bmap[(blocky * bmapwidth) + blockx];
mobj_t *bnext = *link;
thing->bnext = bnext;
if (bnext != NULL)
bnext->bprev = &thing->bnext;
thing->bprev = link;
*link = thing;
}
else // thing is off the map
{
thing->bnext = NULL, thing->bprev = NULL;
}
}
//
// P_SetThingPosition
// Links a thing into both a block and a subsector
@ -1071,24 +1101,7 @@ void P_SetThingPosition(mobj_t *thing)
if (!(thing->flags & MF_NOBLOCKMAP))
{
// inert things don't need to be in blockmap
const INT32 blockx = (unsigned)(thing->x - bmaporgx)>>MAPBLOCKSHIFT;
const INT32 blocky = (unsigned)(thing->y - bmaporgy)>>MAPBLOCKSHIFT;
if (blockx >= 0 && blockx < bmapwidth
&& blocky >= 0 && blocky < bmapheight)
{
// killough 8/11/98: simpler scheme using
// pointer-to-pointer prev pointers --
// allows head nodes to be treated like everything else
mobj_t **link = &blocklinks[blocky*bmapwidth + blockx];
mobj_t *bnext = *link;
if ((thing->bnext = bnext) != NULL)
bnext->bprev = &thing->bnext;
thing->bprev = link;
*link = thing;
}
else // thing is off the map
thing->bnext = NULL, thing->bprev = NULL;
P_LinkToBlockMap(thing, blocklinks);
}
// Allows you to 'step' on a new linedef exec when the previous
@ -1143,18 +1156,15 @@ void P_SetUnderlayPosition(mobj_t *thing)
void P_SetPrecipitationThingPosition(precipmobj_t *thing)
{
subsector_t *ss = thing->subsector = R_PointInSubsector(thing->x, thing->y);
precipmobj_t **link = &ss->sector->preciplist;
precipmobj_t *snext = *link;
if ((thing->snext = snext) != NULL)
snext->sprev = &thing->snext;
thing->sprev = link;
*link = thing;
thing->subsector = R_PointInSubsector(thing->x, thing->y);
P_CreatePrecipSecNodeList(thing, thing->x, thing->y);
thing->touching_sectorlist = precipsector_list; // Attach to Thing's precipmobj_t
precipsector_list = NULL; // clear for next time
// NOTE: this works because bnext/bprev are at the same
// offsets in precipmobj_t and mobj_t
P_LinkToBlockMap((mobj_t*)thing, (mobj_t**)precipblocklinks);
}
//

View file

@ -291,9 +291,10 @@ struct mobj_t
mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type]
// More list: links in sector (if needed)
mobj_t *snext;
mobj_t **sprev; // killough 8/11/98: change to ptr-to-ptr
// Interaction info, by BLOCKMAP.
// Links in blocks (if needed).
mobj_t *bnext;
mobj_t **bprev; // killough 8/11/98: change to ptr-to-ptr
// More drawing info: to determine current sprite.
angle_t angle, pitch, roll; // orientation
@ -347,10 +348,9 @@ struct mobj_t
// using an internal color lookup table for re-indexing.
UINT16 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation).
// Interaction info, by BLOCKMAP.
// Links in blocks (if needed).
mobj_t *bnext;
mobj_t **bprev; // killough 8/11/98: change to ptr-to-ptr
// More list: links in sector (if needed)
mobj_t *snext;
mobj_t **sprev; // killough 8/11/98: change to ptr-to-ptr
// Additional pointers for NiGHTS hoops
mobj_t *hnext;
@ -448,9 +448,10 @@ struct precipmobj_t
mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type]
// More list: links in sector (if needed)
precipmobj_t *snext;
precipmobj_t **sprev; // killough 8/11/98: change to ptr-to-ptr
// Links in blocks (if needed).
// The blockmap is only used by precip to render.
precipmobj_t *bnext;
precipmobj_t **bprev; // killough 8/11/98: change to ptr-to-ptr
// More drawing info: to determine current sprite.
angle_t angle, pitch, roll; // orientation

View file

@ -160,6 +160,7 @@ INT32 *blockmaplump; // Big blockmap
fixed_t bmaporgx, bmaporgy;
// for thing chains
mobj_t **blocklinks;
precipmobj_t **precipblocklinks;
// REJECT
// For fast sight rejection.
@ -882,7 +883,6 @@ static void P_InitializeSector(sector_t *ss)
ss->floorspeed = ss->ceilspeed = 0;
ss->preciplist = NULL;
ss->touching_preciplist = NULL;
ss->f_slope = NULL;
@ -3547,6 +3547,10 @@ static boolean P_LoadBlockMap(UINT8 *data, size_t count)
// haleyjd 2/22/06: setup polyobject blockmap
count = sizeof(*polyblocklinks) * bmapwidth * bmapheight;
polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL);
count = sizeof (*precipblocklinks)* bmapwidth*bmapheight;
precipblocklinks = Z_Calloc(count, PU_LEVEL, NULL);
return true;
}
@ -3800,6 +3804,9 @@ static void P_CreateBlockMap(void)
// haleyjd 2/22/06: setup polyobject blockmap
count = sizeof(*polyblocklinks) * bmapwidth * bmapheight;
polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL);
count = sizeof (*precipblocklinks)* bmapwidth*bmapheight;
precipblocklinks = Z_Calloc(count, PU_LEVEL, NULL);
}
}

View file

@ -524,7 +524,6 @@ struct sector_t
fixed_t floorspeed, ceilspeed;
// list of precipitation mobjs in sector
precipmobj_t *preciplist;
mprecipsecnode_t *touching_preciplist;
// Eternity engine slope

View file

@ -493,6 +493,33 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe
return false;
}
// Returns search dimensions within a blockmap, in the direction of viewangle and out to a certain distance.
void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32 *yl, INT32 *yh)
{
const angle_t left = viewangle - clipangle[viewssnum];
const angle_t right = viewangle + clipangle[viewssnum];
const fixed_t vxleft = viewx + FixedMul(drawdist, FCOS(left));
const fixed_t vyleft = viewy + FixedMul(drawdist, FSIN(left));
const fixed_t vxright = viewx + FixedMul(drawdist, FCOS(right));
const fixed_t vyright = viewy + FixedMul(drawdist, FSIN(right));
// Try to narrow the search to within only the field of view
*xl = (unsigned)(min(viewx, min(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
*xh = (unsigned)(max(viewx, max(vxleft, vxright)) - bmaporgx)>>MAPBLOCKSHIFT;
*yl = (unsigned)(min(viewy, min(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
*yh = (unsigned)(max(viewy, max(vyleft, vyright)) - bmaporgy)>>MAPBLOCKSHIFT;
if (*xh >= bmapwidth)
*xh = bmapwidth - 1;
if (*yh >= bmapheight)
*yh = bmapheight - 1;
BMBOUNDFIX(*xl, *xh, *yl, *yh);
}
//
// R_InitTextureMapping
//
@ -1485,6 +1512,7 @@ static void R_RenderViewpoint(maskcount_t* mask)
curdrawsegs = ds_p;
R_RenderBSPNode((INT32)numnodes - 1);
R_AddPrecipitationSprites();
Mask_Post(mask);
}
@ -1556,7 +1584,6 @@ void R_RenderPlayerView(void)
ps_bsptime = I_GetPreciseTime();
R_RenderViewpoint(&masks[nummasks - 1]);
ps_bsptime = I_GetPreciseTime() - ps_bsptime;
ps_numsprites = visspritecount;
#ifdef TIMING
RDMSR(0x10, &mycount);
mytotal += mycount; // 64bit add

View file

@ -87,6 +87,8 @@ subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y);
boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph);
void R_GetRenderBlockMapDimensions(fixed_t drawdist, INT32 *xl, INT32 *xh, INT32 *yl, INT32 *yh);
// Render stats
extern precise_t ps_prevframetime;// time when previous frame was rendered

View file

@ -2639,7 +2639,6 @@ weatherthink:
void R_AddSprites(sector_t *sec, INT32 lightlevel)
{
mobj_t *thing;
precipmobj_t *precipthing; // Tails 08-25-2002
INT32 lightnum;
fixed_t limit_dist;
@ -2696,14 +2695,45 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
}
}
}
}
// R_AddPrecipitationSprites
// This renders through the blockmap instead of BSP to avoid
// iterating a huge amount of precipitation sprites in sectors
// that are beyond drawdist.
//
void R_AddPrecipitationSprites(void)
{
const fixed_t drawdist = cv_drawdist_precip.value * mapobjectscale;
INT32 xl, xh, yl, yh, bx, by;
precipmobj_t *th;
// no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off
if ((limit_dist = (fixed_t)cv_drawdist_precip.value * mapobjectscale) && !portalskipprecipmobjs)
if (drawdist == 0)
{
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
return;
}
// do not render in skybox
if (portalskipprecipmobjs)
{
return;
}
R_GetRenderBlockMapDimensions(drawdist, &xl, &xh, &yl, &yh);
for (bx = xl; bx <= xh; bx++)
{
for (by = yl; by <= yh; by++)
{
if (R_PrecipThingVisible(precipthing, limit_dist))
R_ProjectPrecipitationSprite(precipthing);
for (th = precipblocklinks[(by * bmapwidth) + bx]; th; th = th->bnext)
{
if (R_PrecipThingVisible(th))
{
R_ProjectPrecipitationSprite(th);
}
}
}
}
}
@ -3652,17 +3682,12 @@ boolean R_ThingWithinDist (mobj_t *thing, fixed_t limit_dist)
}
/* Check if precipitation may be drawn from our current view. */
boolean R_PrecipThingVisible (precipmobj_t *precipthing,
fixed_t limit_dist)
boolean R_PrecipThingVisible (precipmobj_t *precipthing)
{
fixed_t approx_dist;
if (( precipthing->precipflags & PCF_INVISIBLE ))
return false;
approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y);
return ( approx_dist <= limit_dist );
return true;
}
boolean R_ThingHorizontallyFlipped(mobj_t *thing)

View file

@ -67,6 +67,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
//SoM: 6/5/2000: Light sprites correctly!
void R_AddSprites(sector_t *sec, INT32 lightlevel);
void R_AddPrecipitationSprites(void);
void R_InitSprites(void);
void R_ClearSprites(void);
@ -78,8 +79,7 @@ boolean R_ThingVisible (mobj_t *thing);
boolean R_ThingWithinDist (mobj_t *thing,
fixed_t draw_dist);
boolean R_PrecipThingVisible (precipmobj_t *precipthing,
fixed_t precip_draw_dist);
boolean R_PrecipThingVisible (precipmobj_t *precipthing);
boolean R_ThingHorizontallyFlipped (mobj_t *thing);
boolean R_ThingVerticallyFlipped (mobj_t *thing);