From 809ae20558529092694544bc615628d32f8a24cf Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 23 Oct 2024 02:37:08 +0200 Subject: [PATCH 1/5] use highly optmized (but slightly inaccurate) version of R_PointOnSide for rendering --- src/hardware/hw_main.c | 2 +- src/r_bsp.c | 3 ++- src/r_main.h | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 8c10f1eec..cfb9636d6 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3103,7 +3103,7 @@ static void HWR_RenderBSPNode(INT32 bspnum) bsp = &nodes[bspnum]; // Decide which side the view point is on. - side = R_PointOnSide(viewx, viewy, bsp); + side = R_PointOnSideRender(viewx, viewy, bsp); // Recursively divide front space. if (HWR_PortalCheckBBox(bsp->bbox[side])) diff --git a/src/r_bsp.c b/src/r_bsp.c index 500a58035..a6530ce21 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -1320,7 +1320,8 @@ void R_RenderBSPNode(INT32 bspnum) bsp = &nodes[bspnum]; // Decide which side the view point is on. - side = R_PointOnSide(viewx, viewy, bsp); + side = R_PointOnSideRender(viewx, viewy, bsp); + // Recursively divide front space. R_RenderBSPNode(bsp->children[side]); diff --git a/src/r_main.h b/src/r_main.h index cfca7e1a4..6b7c88de3 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -74,6 +74,12 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // Utility functions. INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t *node); +FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSideRender(fixed_t x, fixed_t y, const node_t *node) +{ + // use cross product to determine side quickly + return (INT64)(y - node->y) * node->dx - (INT64)(x - node->x) * node->dy > 0; +} + FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line) { fixed_t lx = line->v1->x; -- 2.54.0 From e66d215dd309fb6c9892c80ee90035efb485d97c Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 20 Nov 2024 20:36:22 +0100 Subject: [PATCH 2/5] Fix integer overflows on very large numbers --- src/r_main.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_main.h b/src/r_main.h index 6b7c88de3..f173307b7 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -77,7 +77,7 @@ INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t *node); FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSideRender(fixed_t x, fixed_t y, const node_t *node) { // use cross product to determine side quickly - return (INT64)(y - node->y) * node->dx - (INT64)(x - node->x) * node->dy > 0; + return ((INT64)y - node->y) * node->dx - ((INT64)x - node->x) * node->dy > 0; } FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line) @@ -88,7 +88,7 @@ FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSegSide(fixed_t x, fixed_t fixed_t ldy = line->v2->y - ly; // use cross product to determine side quickly - return (INT64)(y - ly) * ldx - (INT64)(x - lx) * ldy > 0; + return ((INT64)y - ly) * ldx - ((INT64)x - lx) * ldy > 0; } angle_t R_PointToAngle(fixed_t x, fixed_t y); -- 2.54.0 From a14c2f59b80eb404a5369b0a9419077b812afa74 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 20 Nov 2024 21:25:18 +0100 Subject: [PATCH 3/5] rename to R_PointOnSideFast --- src/hardware/hw_main.c | 2 +- src/r_bsp.c | 2 +- src/r_main.h | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index cfb9636d6..45660af0b 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3103,7 +3103,7 @@ static void HWR_RenderBSPNode(INT32 bspnum) bsp = &nodes[bspnum]; // Decide which side the view point is on. - side = R_PointOnSideRender(viewx, viewy, bsp); + side = R_PointOnSideFast(viewx, viewy, bsp); // Recursively divide front space. if (HWR_PortalCheckBBox(bsp->bbox[side])) diff --git a/src/r_bsp.c b/src/r_bsp.c index a6530ce21..a8e5b8551 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -1320,7 +1320,7 @@ void R_RenderBSPNode(INT32 bspnum) bsp = &nodes[bspnum]; // Decide which side the view point is on. - side = R_PointOnSideRender(viewx, viewy, bsp); + side = R_PointOnSideFast(viewx, viewy, bsp); // Recursively divide front space. R_RenderBSPNode(bsp->children[side]); diff --git a/src/r_main.h b/src/r_main.h index f173307b7..d27530f41 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -74,7 +74,9 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // Utility functions. INT32 R_PointOnSide(fixed_t x, fixed_t y, const node_t *node); -FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSideRender(fixed_t x, fixed_t y, const node_t *node) +// This is not as accurate +// SHOULD NOT BE USED FOR ANYTHING GAMEPLAY RELATED!! +FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSideFast(fixed_t x, fixed_t y, const node_t *node) { // use cross product to determine side quickly return ((INT64)y - node->y) * node->dx - ((INT64)x - node->x) * node->dy > 0; -- 2.54.0 From bec632800de6dbca9476f7c193c906f746a5a5d6 Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 20 Nov 2024 21:26:18 +0100 Subject: [PATCH 4/5] use it for R_IsPointInSubsector this is fine since R_IsPointInSubsector is only used for precip spawn unless you disable noclipcam lol --- src/r_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/r_main.c b/src/r_main.c index 1c45d4112..c47095078 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1076,7 +1076,8 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y) while (!(nodenum & NF_SUBSECTOR)) { node = &nodes[nodenum]; - side = R_PointOnSide(x, y, node); + //side = R_PointOnSide(x, y, node); + side = R_PointOnSideFast(x, y, node); // this is fine since R_IsPointInSubsector is only used for precip spawn unless you disable noclipcam lol nodenum = node->children[side]; } -- 2.54.0 From f499b1111393846ea11b9b01ed94a82e1caa491e Mon Sep 17 00:00:00 2001 From: Alug Date: Wed, 20 Nov 2024 21:27:29 +0100 Subject: [PATCH 5/5] add R_PointInSubsectorFast for non critical gameplay stuff like sounds and camera and some parts of rendering --- src/d_clisrv.c | 2 +- src/hardware/hw_main.c | 2 +- src/hardware/hw_portal.c | 2 +- src/p_mobj.c | 4 ++-- src/p_setup.c | 4 ++-- src/p_user.c | 4 ++-- src/r_fps.c | 2 +- src/r_main.h | 13 ++++++++++++- src/s_sound.c | 4 ++-- 9 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 6efeffc6f..f8f47f4ae 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -2013,7 +2013,7 @@ static void CL_ReloadReceivedSavegame(void) for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - camera[i].subsector = R_PointInSubsector(camera[i].x, camera[i].y); + camera[i].subsector = R_PointInSubsectorFast(camera[i].x, camera[i].y); } cl_redownloadinggamestate = false; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 45660af0b..a0059f184 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3177,7 +3177,7 @@ static gl_vissprite_t *HWR_NewVisSprite(void) // Finds a floor through which light does not pass. static fixed_t HWR_OpaqueFloorAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) { - const sector_t *sec = R_PointInSubsector(x, y)->sector; + const sector_t *sec = R_PointInSubsectorFast(x, y)->sector; fixed_t floorz = sec->floorheight; if (sec->ffloors) diff --git a/src/hardware/hw_portal.c b/src/hardware/hw_portal.c index 96a1b300a..fb4d88cb3 100644 --- a/src/hardware/hw_portal.c +++ b/src/hardware/hw_portal.c @@ -132,7 +132,7 @@ void HWR_PortalFrame(gl_portal_t* portal) { portalclipline = NULL; portalcullsector = NULL; - viewsector = R_PointInSubsector(viewx, viewy)->sector; + viewsector = R_PointInSubsectorFast(viewx, viewy)->sector; } } diff --git a/src/p_mobj.c b/src/p_mobj.c index 9da7b0235..75746118e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3318,7 +3318,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled P_CheckCameraPosition(thiscam->x, thiscam->y, thiscam); - thiscam->subsector = R_PointInSubsector(thiscam->x, thiscam->y); + thiscam->subsector = R_PointInSubsectorFast(thiscam->x, thiscam->y); thiscam->floorz = tmfloorz; thiscam->ceilingz = tmceilingz; @@ -10368,7 +10368,7 @@ void P_PrecipitationEffects(void) for (y = yl; y <= yh; y += RADIUSSTEP) for (x = xl; x <= xh; x += RADIUSSTEP) { - if (R_PointInSubsector((fixed_t)x, (fixed_t)y)->sector->ceilingpic != skyflatnum) // Found the outdoors! + if (R_PointInSubsectorFast((fixed_t)x, (fixed_t)y)->sector->ceilingpic != skyflatnum) // Found the outdoors! continue; newdist = S_CalculateSoundDistance(players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y, 0, (fixed_t)x, (fixed_t)y, 0); diff --git a/src/p_setup.c b/src/p_setup.c index 93207a3c1..e304aa7f3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2430,7 +2430,7 @@ static void P_SetupCamera(UINT8 pnum, camera_t *cam) cam->y = players[pnum].mo->y; cam->z = players[pnum].mo->z; cam->angle = players[pnum].mo->angle; - cam->subsector = R_PointInSubsector(cam->x, cam->y); // make sure camera has a subsector set -- Monster Iestyn (12/11/18) + cam->subsector = R_PointInSubsectorFast(cam->x, cam->y); // make sure camera has a subsector set -- Monster Iestyn (12/11/18) } else { @@ -2455,7 +2455,7 @@ static void P_SetupCamera(UINT8 pnum, camera_t *cam) cam->y = thing->y; cam->z = thing->z; cam->angle = FixedAngle((fixed_t)thing->angle << FRACBITS); - cam->subsector = R_PointInSubsector(cam->x, cam->y); // make sure camera has a subsector set -- Monster Iestyn (12/11/18) + cam->subsector = R_PointInSubsectorFast(cam->x, cam->y); // make sure camera has a subsector set -- Monster Iestyn (12/11/18) } } diff --git a/src/p_user.c b/src/p_user.c index 4041c17d6..2c061e7ce 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3357,7 +3357,7 @@ void P_DemoCameraMovement(camera_t *cam) democam.soundmobj = awayviewmobj_hack; // update subsector to avoid crashes; - cam->subsector = R_PointInSubsector(cam->x, cam->y); + cam->subsector = R_PointInSubsectorFast(cam->x, cam->y); } void P_ResetCamera(player_t *player, camera_t *thiscam) @@ -3398,7 +3398,7 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) } thiscam->relativex = 0; - thiscam->subsector = R_PointInSubsector(thiscam->x,thiscam->y); + thiscam->subsector = R_PointInSubsectorFast(thiscam->x,thiscam->y); thiscam->radius = 20*FRACUNIT; thiscam->height = 16*FRACUNIT; diff --git a/src/r_fps.c b/src/r_fps.c index 0f86160a6..15c3f2259 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -193,7 +193,7 @@ void R_InterpolateView(fixed_t frac, boolean forceinvalid) viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); viewplayer = newview->player; - viewsector = R_PointInSubsector(viewx, viewy)->sector; + viewsector = R_PointInSubsectorFast(viewx, viewy)->sector; R_SetupFreelook(); } diff --git a/src/r_main.h b/src/r_main.h index d27530f41..6d4546f39 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -102,10 +102,21 @@ fixed_t R_ScaleFromGlobalAngle(angle_t visangle); subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y); +// uses R_PointOnSideFast +// SHOULD NOT BE USED FOR ANYTHING GAMEPLAY RELATED!! +FUNCINLINE static ATTRINLINE subsector_t *R_PointInSubsectorFast(fixed_t x, fixed_t y) +{ + size_t nodenum = numnodes-1; + + while (!(nodenum & NF_SUBSECTOR)) + nodenum = nodes[nodenum].children[R_PointOnSideFast(x, y, nodes+nodenum)]; + + return &subsectors[nodenum & ~NF_SUBSECTOR]; +} + #define R_PointToDist(x, y) R_PointToDist2(viewx, viewy, x, y) #define R_PointToDist2(px2, py2, px1, py1) FixedHypot((px1) - (px2), (py1) - (py2)) - 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); diff --git a/src/s_sound.c b/src/s_sound.c index 868bccc77..d54ee2884 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1046,7 +1046,7 @@ boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 INT64 x, y, yl, yh, xl, xh; fixed_t newdist; - if (R_PointInSubsector(listensource.x, listensource.y)->sector->ceilingpic == skyflatnum) + if (R_PointInSubsectorFast(listensource.x, listensource.y)->sector->ceilingpic == skyflatnum) approx_dist = 0; else { @@ -1059,7 +1059,7 @@ boolean S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 for (y = yl; y <= yh; y += FRACUNIT*64) for (x = xl; x <= xh; x += FRACUNIT*64) { - if (R_PointInSubsector(x, y)->sector->ceilingpic == skyflatnum) + if (R_PointInSubsectorFast(x, y)->sector->ceilingpic == skyflatnum) { // Found the outdoors! newdist = S_CalculateSoundDistance(listensource.x, listensource.y, 0, x, y, 0); -- 2.54.0