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_AddSprites(sector_t *sec);
static void HWR_ProjectSprite(mobj_t *thing); static void HWR_ProjectSprite(mobj_t *thing);
#ifdef HWPRECIP #ifdef HWPRECIP
static void HWR_AddPrecipitationSprites(void);
static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
#endif #endif
static void HWR_ProjectBoundingBox(mobj_t *thing); static void HWR_ProjectBoundingBox(mobj_t *thing);
@ -5052,9 +5053,6 @@ static UINT8 sectorlight;
static void HWR_AddSprites(sector_t *sec) static void HWR_AddSprites(sector_t *sec)
{ {
mobj_t *thing; mobj_t *thing;
#ifdef HWPRECIP
precipmobj_t *precipthing;
#endif
fixed_t limit_dist; fixed_t limit_dist;
// BSP is traversed by subsector. // BSP is traversed by subsector.
@ -5085,19 +5083,45 @@ static void HWR_AddSprites(sector_t *sec)
HWR_ProjectBoundingBox(thing); HWR_ProjectBoundingBox(thing);
} }
} }
}
#ifdef HWPRECIP #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 // 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)) for (th = precipblocklinks[(by * bmapwidth) + bx]; th; th = th->bnext)
HWR_ProjectPrecipitationSprite(precipthing); {
if (R_PrecipThingVisible(th))
{
HWR_ProjectPrecipitationSprite(th);
}
}
} }
} }
#endif
} }
#endif
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// HWR_ProjectSprite // HWR_ProjectSprite
@ -6315,6 +6339,10 @@ static void HWR_RenderViewpoint(player_t *player, boolean drawSkyTexture, boolea
HWR_RenderBSPNode((INT32)numnodes-1); HWR_RenderBSPNode((INT32)numnodes-1);
#ifdef HWPRECIP
HWR_AddPrecipitationSprites();
#endif
#ifndef NEWCLIP #ifndef NEWCLIP
// Make a viewangle int so we can render things based on mouselook // Make a viewangle int so we can render things based on mouselook
viewangle = localaiming[viewssnum]; viewangle = localaiming[viewssnum];

View file

@ -510,6 +510,7 @@ extern INT32 bmapheight; // in mapblocks
extern fixed_t bmaporgx; 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 precipmobj_t **precipblocklinks; // special blockmap for precip rendering
extern struct minimapinfo extern struct minimapinfo
{ {

View file

@ -1006,15 +1006,45 @@ void P_UnsetThingPosition(mobj_t *thing)
void P_UnsetPrecipThingPosition(precipmobj_t *thing) void P_UnsetPrecipThingPosition(precipmobj_t *thing)
{ {
precipmobj_t **sprev = thing->sprev; precipmobj_t **bprev = thing->bprev;
precipmobj_t *snext = thing->snext; precipmobj_t *bnext = thing->bnext;
if ((*sprev = snext) != NULL) // unlink from sector list
snext->sprev = sprev; if (bprev && (*bprev = bnext) != NULL) // unlink from block map
bnext->bprev = bprev;
precipsector_list = thing->touching_sectorlist; precipsector_list = thing->touching_sectorlist;
thing->touching_sectorlist = NULL; //to be restored by P_SetPrecipThingPosition 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 // P_SetThingPosition
// Links a thing into both a block and a subsector // 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)) if (!(thing->flags & MF_NOBLOCKMAP))
{ {
// inert things don't need to be in blockmap // inert things don't need to be in blockmap
const INT32 blockx = (unsigned)(thing->x - bmaporgx)>>MAPBLOCKSHIFT; P_LinkToBlockMap(thing, blocklinks);
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;
} }
// Allows you to 'step' on a new linedef exec when the previous // 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) void P_SetPrecipitationThingPosition(precipmobj_t *thing)
{ {
subsector_t *ss = thing->subsector = R_PointInSubsector(thing->x, thing->y); 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;
P_CreatePrecipSecNodeList(thing, thing->x, thing->y); P_CreatePrecipSecNodeList(thing, thing->x, thing->y);
thing->touching_sectorlist = precipsector_list; // Attach to Thing's precipmobj_t thing->touching_sectorlist = precipsector_list; // Attach to Thing's precipmobj_t
precipsector_list = NULL; // clear for next time 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; mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type] const mobjinfo_t *info; // &mobjinfo[mobj->type]
// More list: links in sector (if needed) // Interaction info, by BLOCKMAP.
mobj_t *snext; // Links in blocks (if needed).
mobj_t **sprev; // killough 8/11/98: change to ptr-to-ptr mobj_t *bnext;
mobj_t **bprev; // killough 8/11/98: change to ptr-to-ptr
// More drawing info: to determine current sprite. // More drawing info: to determine current sprite.
angle_t angle, pitch, roll; // orientation angle_t angle, pitch, roll; // orientation
@ -347,10 +348,9 @@ struct mobj_t
// using an internal color lookup table for re-indexing. // using an internal color lookup table for re-indexing.
UINT16 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation). UINT16 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation).
// Interaction info, by BLOCKMAP. // More list: links in sector (if needed)
// Links in blocks (if needed). mobj_t *snext;
mobj_t *bnext; mobj_t **sprev; // killough 8/11/98: change to ptr-to-ptr
mobj_t **bprev; // killough 8/11/98: change to ptr-to-ptr
// Additional pointers for NiGHTS hoops // Additional pointers for NiGHTS hoops
mobj_t *hnext; mobj_t *hnext;
@ -448,9 +448,10 @@ struct precipmobj_t
mobjtype_t type; mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type] const mobjinfo_t *info; // &mobjinfo[mobj->type]
// More list: links in sector (if needed) // Links in blocks (if needed).
precipmobj_t *snext; // The blockmap is only used by precip to render.
precipmobj_t **sprev; // killough 8/11/98: change to ptr-to-ptr precipmobj_t *bnext;
precipmobj_t **bprev; // killough 8/11/98: change to ptr-to-ptr
// More drawing info: to determine current sprite. // More drawing info: to determine current sprite.
angle_t angle, pitch, roll; // orientation angle_t angle, pitch, roll; // orientation

View file

@ -160,6 +160,7 @@ INT32 *blockmaplump; // Big blockmap
fixed_t bmaporgx, bmaporgy; fixed_t bmaporgx, bmaporgy;
// for thing chains // for thing chains
mobj_t **blocklinks; mobj_t **blocklinks;
precipmobj_t **precipblocklinks;
// REJECT // REJECT
// For fast sight rejection. // For fast sight rejection.
@ -882,7 +883,6 @@ static void P_InitializeSector(sector_t *ss)
ss->floorspeed = ss->ceilspeed = 0; ss->floorspeed = ss->ceilspeed = 0;
ss->preciplist = NULL;
ss->touching_preciplist = NULL; ss->touching_preciplist = NULL;
ss->f_slope = 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 // haleyjd 2/22/06: setup polyobject blockmap
count = sizeof(*polyblocklinks) * bmapwidth * bmapheight; count = sizeof(*polyblocklinks) * bmapwidth * bmapheight;
polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL); polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL);
count = sizeof (*precipblocklinks)* bmapwidth*bmapheight;
precipblocklinks = Z_Calloc(count, PU_LEVEL, NULL);
return true; return true;
} }
@ -3800,6 +3804,9 @@ static void P_CreateBlockMap(void)
// haleyjd 2/22/06: setup polyobject blockmap // haleyjd 2/22/06: setup polyobject blockmap
count = sizeof(*polyblocklinks) * bmapwidth * bmapheight; count = sizeof(*polyblocklinks) * bmapwidth * bmapheight;
polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL); 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; fixed_t floorspeed, ceilspeed;
// list of precipitation mobjs in sector // list of precipitation mobjs in sector
precipmobj_t *preciplist;
mprecipsecnode_t *touching_preciplist; mprecipsecnode_t *touching_preciplist;
// Eternity engine slope // Eternity engine slope

View file

@ -493,6 +493,33 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe
return false; 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 // R_InitTextureMapping
// //
@ -1485,6 +1512,7 @@ static void R_RenderViewpoint(maskcount_t* mask)
curdrawsegs = ds_p; curdrawsegs = ds_p;
R_RenderBSPNode((INT32)numnodes - 1); R_RenderBSPNode((INT32)numnodes - 1);
R_AddPrecipitationSprites();
Mask_Post(mask); Mask_Post(mask);
} }
@ -1556,7 +1584,6 @@ void R_RenderPlayerView(void)
ps_bsptime = I_GetPreciseTime(); ps_bsptime = I_GetPreciseTime();
R_RenderViewpoint(&masks[nummasks - 1]); R_RenderViewpoint(&masks[nummasks - 1]);
ps_bsptime = I_GetPreciseTime() - ps_bsptime; ps_bsptime = I_GetPreciseTime() - ps_bsptime;
ps_numsprites = visspritecount;
#ifdef TIMING #ifdef TIMING
RDMSR(0x10, &mycount); RDMSR(0x10, &mycount);
mytotal += mycount; // 64bit add 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); 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 // Render stats
extern precise_t ps_prevframetime;// time when previous frame was rendered 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) void R_AddSprites(sector_t *sec, INT32 lightlevel)
{ {
mobj_t *thing; mobj_t *thing;
precipmobj_t *precipthing; // Tails 08-25-2002
INT32 lightnum; INT32 lightnum;
fixed_t limit_dist; 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 // 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)) for (th = precipblocklinks[(by * bmapwidth) + bx]; th; th = th->bnext)
R_ProjectPrecipitationSprite(precipthing); {
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. */ /* Check if precipitation may be drawn from our current view. */
boolean R_PrecipThingVisible (precipmobj_t *precipthing, boolean R_PrecipThingVisible (precipmobj_t *precipthing)
fixed_t limit_dist)
{ {
fixed_t approx_dist;
if (( precipthing->precipflags & PCF_INVISIBLE )) if (( precipthing->precipflags & PCF_INVISIBLE ))
return false; return false;
approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y); return true;
return ( approx_dist <= limit_dist );
} }
boolean R_ThingHorizontallyFlipped(mobj_t *thing) 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! //SoM: 6/5/2000: Light sprites correctly!
void R_AddSprites(sector_t *sec, INT32 lightlevel); void R_AddSprites(sector_t *sec, INT32 lightlevel);
void R_AddPrecipitationSprites(void);
void R_InitSprites(void); void R_InitSprites(void);
void R_ClearSprites(void); void R_ClearSprites(void);
@ -78,8 +79,7 @@ boolean R_ThingVisible (mobj_t *thing);
boolean R_ThingWithinDist (mobj_t *thing, boolean R_ThingWithinDist (mobj_t *thing,
fixed_t draw_dist); fixed_t draw_dist);
boolean R_PrecipThingVisible (precipmobj_t *precipthing, boolean R_PrecipThingVisible (precipmobj_t *precipthing);
fixed_t precip_draw_dist);
boolean R_ThingHorizontallyFlipped (mobj_t *thing); boolean R_ThingHorizontallyFlipped (mobj_t *thing);
boolean R_ThingVerticallyFlipped (mobj_t *thing); boolean R_ThingVerticallyFlipped (mobj_t *thing);