diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 5feef98b2..cc1b6b8f3 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1843,7 +1843,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/d_think.h b/src/d_think.h index b907c17fd..6b8ee113a 100644 --- a/src/d_think.h +++ b/src/d_think.h @@ -49,6 +49,7 @@ typedef struct thinker_s // killough 11/98: count of how many other objects reference // this one using pointers. Used for garbage collection. INT32 references; + boolean cachable; } thinker_t; #endif diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 40b488a8e..06d4e75a6 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_PointOnSideFast(viewx, viewy, bsp); // Recursively divide front space. if (HWR_PortalCheckBBox(bsp->bbox[side])) @@ -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 d433b78cd..120e59e6c 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_local.h b/src/p_local.h index 4a7da680f..7cf7c4389 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -63,6 +63,7 @@ // both the head and tail of the thinker list extern thinker_t thinkercap; +extern mobj_t *mobjcache; void P_InitThinkers(void); void P_AddThinker(thinker_t *thinker); diff --git a/src/p_mobj.c b/src/p_mobj.c index 2420d2a50..afd3f8331 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -48,6 +48,7 @@ actioncache_t actioncachehead; static mobj_t *overlaycap = NULL; static mobj_t *shadowcap = NULL; mobj_t *waypointcap = NULL; +mobj_t *mobjcache = NULL; void P_InitCachedActions(void) { @@ -3307,7 +3308,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled P_CheckCameraPosition(thiscam->x, thiscam->y, thiscam); #endif - thiscam->subsector = R_PointInSubsector(thiscam->x, thiscam->y); + thiscam->subsector = R_PointInSubsectorFast(thiscam->x, thiscam->y); thiscam->floorz = tmfloorz; thiscam->ceilingz = tmceilingz; @@ -9348,7 +9349,18 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { const mobjinfo_t *info = &mobjinfo[type]; state_t *st; - mobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + mobj_t *mobj; + + if (mobjcache != NULL) + { + mobj = mobjcache; + mobjcache = mobjcache->hnext; + memset(mobj, 0, sizeof(*mobj)); + } + else + { + mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + } // this is officially a mobj, declared as soon as possible. mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; @@ -9809,7 +9821,18 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster) { const mobjinfo_t *info = &mobjinfo[MT_SHADOW]; state_t *st; - mobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + mobj_t *mobj; + + if (mobjcache != NULL) + { + mobj = mobjcache; + mobjcache = mobjcache->hnext; + memset(mobj, 0, sizeof(*mobj)); + } + else + { + mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); + } // this is officially a mobj, declared as soon as possible. mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; @@ -10083,7 +10106,9 @@ void P_RemoveMobj(mobj_t *mobj) // Invalidate mobj_t data to cause crashes if accessed! memset(mobj, 0xff, sizeof(mobj_t)); #endif - Z_Free(mobj); // No refrences? Can be removed immediately! :D + // no references, dump it directly in the mobj cache + mobj->hnext = mobjcache; + mobjcache = mobj; } else { // Add thinker just to delay removing it until refrences are gone. @@ -10354,7 +10379,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_polyobj.c b/src/p_polyobj.c index 5ea1e4074..ffc6651b8 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -155,6 +155,7 @@ FUNCINLINE static ATTRINLINE void PolyObj_AddThinker(thinker_t *th) thinkercap.next = th; th->references = 0; + th->cachable = false; // not initialising this made the mobjcache die thx! } static void FreeSideLists(void) diff --git a/src/p_setup.c b/src/p_setup.c index 27bd62eb7..36c9f319c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2338,7 +2338,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 { @@ -2362,7 +2362,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) } } @@ -2647,6 +2647,8 @@ boolean P_SetupLevel(boolean skipprecip, boolean reloadinggamestate) R_ClearLevelSplats(); #endif + mobjcache = NULL; + R_InitializeLevelInterpolators(); P_InitThinkers(); diff --git a/src/p_tick.c b/src/p_tick.c index f4d75683b..0286fa958 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -196,6 +196,8 @@ void P_AddThinker(thinker_t *thinker) thinkercap.prev = thinker; thinker->references = 0; // killough 11/98: init reference counter to 0 + + thinker->cachable = (thinker->function.acp1 == (actionf_p1)P_MobjThinker); } // @@ -235,7 +237,17 @@ void P_RemoveThinkerDelayed(thinker_t *thinker) * thinker->prev->next = thinker->next */ (next->prev = currentthinker = thinker->prev)->next = next; R_DestroyLevelInterpolators(thinker); - Z_Free(thinker); + + if (thinker->cachable == true) + { + // put cachable thinkers in the mobj cache, so we can avoid allocations + ((mobj_t *)thinker)->hnext = mobjcache; + mobjcache = (mobj_t *)thinker; + } + else + { + Z_Free(thinker); + } } // @@ -250,9 +262,20 @@ void P_UnlinkThinker(thinker_t *thinker) I_Assert(thinker->references == 0); (next->prev = thinker->prev)->next = next; - Z_Free(thinker); + + if (thinker->cachable == true) + { + // put cachable thinkers in the mobj cache, so we can avoid allocations + ((mobj_t *)thinker)->hnext = mobjcache; + mobjcache = (mobj_t *)thinker; + } + else + { + Z_Free(thinker); + } } + // // P_RemoveThinker // diff --git a/src/p_user.c b/src/p_user.c index 49916ce77..3f6ab2d4a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3228,7 +3228,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) @@ -3263,7 +3263,7 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) thiscam->aiming = 0; 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_bsp.c b/src/r_bsp.c index 989939860..490540eaa 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -1335,7 +1335,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_PointOnSideFast(viewx, viewy, bsp); + // Recursively divide front space. R_RenderBSPNode(bsp->children[side]); diff --git a/src/r_fps.c b/src/r_fps.c index feb2ac8f2..4dd7fa044 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.c b/src/r_main.c index 59e5c5e90..28b31de5b 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1080,7 +1080,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]; } diff --git a/src/r_main.h b/src/r_main.h index 804dd543c..553f6a79f 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -74,6 +74,14 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // Utility functions. INT32 R_PointOnSide(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; +} + FUNCINLINE static ATTRINLINE PUREFUNC INT32 R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line) { fixed_t lx = line->v1->x; @@ -94,6 +102,18 @@ 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)) diff --git a/src/s_sound.c b/src/s_sound.c index 065d56082..33fe7d0a4 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -987,7 +987,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 { @@ -1000,7 +1000,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);