Merge branch 'seed-waypoint-search' into 'master'

Improve player waypoint search speed

See merge request KartKrew/Kart!1125
This commit is contained in:
Sal 2023-04-01 20:06:04 +00:00
commit e97068dc15
5 changed files with 40 additions and 29 deletions

View file

@ -117,7 +117,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
k_race.c k_race.c
k_battle.c k_battle.c
k_pwrlv.c k_pwrlv.c
k_waypoint.c k_waypoint.cpp
k_pathfind.c k_pathfind.c
k_bheap.c k_bheap.c
k_bot.c k_bot.c

View file

@ -8358,7 +8358,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
if ((player != NULL) && (player->mo != NULL) && (P_MobjWasRemoved(player->mo) == false)) if ((player != NULL) && (player->mo != NULL) && (P_MobjWasRemoved(player->mo) == false))
{ {
waypoint_t *waypoint = K_GetBestWaypointForMobj(player->mo); waypoint_t *waypoint = K_GetBestWaypointForMobj(player->mo, player->currentwaypoint);
boolean updaterespawn = false; boolean updaterespawn = false;
// Our current waypoint. // Our current waypoint.

View file

@ -7,7 +7,7 @@
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details. // See the 'LICENSE' file for more details.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \file k_waypoint.c /// \file k_waypoint.cpp
/// \brief Waypoint handling from the relevant mobjs /// \brief Waypoint handling from the relevant mobjs
/// Setup and interfacing with waypoints for the main game /// Setup and interfacing with waypoints for the main game
@ -343,11 +343,11 @@ static void K_CompareOverlappingWaypoint
} }
/*-------------------------------------------------- /*--------------------------------------------------
waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj, waypoint_t *const hint)
See header file for description. See header file for description.
--------------------------------------------------*/ --------------------------------------------------*/
waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj, waypoint_t *const hint)
{ {
waypoint_t *bestwaypoint = NULL; waypoint_t *bestwaypoint = NULL;
@ -357,21 +357,15 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
} }
else else
{ {
size_t i = 0U;
waypoint_t *checkwaypoint = NULL;
fixed_t closestdist = INT32_MAX; fixed_t closestdist = INT32_MAX;
fixed_t checkdist = INT32_MAX; fixed_t checkdist = INT32_MAX;
fixed_t bestfindist = INT32_MAX; fixed_t bestfindist = INT32_MAX;
for (i = 0; i < numwaypoints; i++) auto sort_waypoint = [&](waypoint_t *const checkwaypoint)
{ {
fixed_t rad;
checkwaypoint = &waypointheap[i];
if (!K_GetWaypointIsEnabled(checkwaypoint)) if (!K_GetWaypointIsEnabled(checkwaypoint))
{ {
continue; return;
} }
checkdist = P_AproxDistance( checkdist = P_AproxDistance(
@ -379,7 +373,7 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
(mobj->y / FRACUNIT) - (checkwaypoint->mobj->y / FRACUNIT)); (mobj->y / FRACUNIT) - (checkwaypoint->mobj->y / FRACUNIT));
checkdist = P_AproxDistance(checkdist, ((mobj->z / FRACUNIT) - (checkwaypoint->mobj->z / FRACUNIT)) * 4); checkdist = P_AproxDistance(checkdist, ((mobj->z / FRACUNIT) - (checkwaypoint->mobj->z / FRACUNIT)) * 4);
rad = (checkwaypoint->mobj->radius / FRACUNIT); fixed_t rad = (checkwaypoint->mobj->radius / FRACUNIT);
// remember: huge radius // remember: huge radius
if (closestdist <= rad && checkdist <= rad && finishline != NULL) if (closestdist <= rad && checkdist <= rad && finishline != NULL)
@ -387,7 +381,7 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
if (!P_TraceWaypointTraversal(mobj, checkwaypoint->mobj)) if (!P_TraceWaypointTraversal(mobj, checkwaypoint->mobj))
{ {
// Save sight checks when all of the other checks pass, so we only do it if we have to // Save sight checks when all of the other checks pass, so we only do it if we have to
continue; return;
} }
// If the mobj is touching multiple waypoints at once, // If the mobj is touching multiple waypoints at once,
@ -405,12 +399,24 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
if (!P_TraceWaypointTraversal(mobj, checkwaypoint->mobj)) if (!P_TraceWaypointTraversal(mobj, checkwaypoint->mobj))
{ {
// Save sight checks when all of the other checks pass, so we only do it if we have to // Save sight checks when all of the other checks pass, so we only do it if we have to
continue; return;
} }
bestwaypoint = checkwaypoint; bestwaypoint = checkwaypoint;
closestdist = checkdist; closestdist = checkdist;
} }
};
if (hint != NULL)
{
// The hint is a waypoint that is already known to be close to the player. It is used to exclude
// most of the other waypoints by distance so fewer expensive sight checks are performed.
sort_waypoint(hint);
}
for (size_t i = 0U; i < numwaypoints; i++)
{
sort_waypoint(&waypointheap[i]);
} }
} }
@ -1768,7 +1774,7 @@ static waypoint_t *K_SearchWaypointGraph(
I_Assert(conditionalfunc != NULL); I_Assert(conditionalfunc != NULL);
I_Assert(firstwaypoint != NULL); I_Assert(firstwaypoint != NULL);
visitedarray = Z_Calloc(numwaypoints * sizeof(boolean), PU_STATIC, NULL); visitedarray = static_cast<boolean*>(Z_Calloc(numwaypoints * sizeof(boolean), PU_STATIC, NULL));
foundwaypoint = K_TraverseWaypoints(firstwaypoint, conditionalfunc, condition, visitedarray); foundwaypoint = K_TraverseWaypoints(firstwaypoint, conditionalfunc, condition, visitedarray);
Z_Free(visitedarray); Z_Free(visitedarray);
@ -1929,16 +1935,18 @@ static void K_AddPrevToWaypoint(waypoint_t *const waypoint, waypoint_t *const pr
I_Assert(prevwaypoint != NULL); I_Assert(prevwaypoint != NULL);
waypoint->numprevwaypoints++; waypoint->numprevwaypoints++;
waypoint->prevwaypoints = waypoint->prevwaypoints = static_cast<waypoint_t**>(
Z_Realloc(waypoint->prevwaypoints, waypoint->numprevwaypoints * sizeof(waypoint_t *), PU_LEVEL, NULL); Z_Realloc(waypoint->prevwaypoints, waypoint->numprevwaypoints * sizeof(waypoint_t *), PU_LEVEL, NULL)
);
if (!waypoint->prevwaypoints) if (!waypoint->prevwaypoints)
{ {
I_Error("K_AddPrevToWaypoint: Failed to reallocate memory for previous waypoints."); I_Error("K_AddPrevToWaypoint: Failed to reallocate memory for previous waypoints.");
} }
waypoint->prevwaypointdistances = waypoint->prevwaypointdistances = static_cast<UINT32*>(
Z_Realloc(waypoint->prevwaypointdistances, waypoint->numprevwaypoints * sizeof(fixed_t), PU_LEVEL, NULL); Z_Realloc(waypoint->prevwaypointdistances, waypoint->numprevwaypoints * sizeof(fixed_t), PU_LEVEL, NULL)
);
if (!waypoint->prevwaypointdistances) if (!waypoint->prevwaypointdistances)
{ {
@ -1994,14 +2002,16 @@ static waypoint_t *K_MakeWaypoint(mobj_t *const mobj)
if (madewaypoint->numnextwaypoints != 0) if (madewaypoint->numnextwaypoints != 0)
{ {
// Allocate memory to hold enough pointers to all of the next waypoints // Allocate memory to hold enough pointers to all of the next waypoints
madewaypoint->nextwaypoints = madewaypoint->nextwaypoints = static_cast<waypoint_t**>(
Z_Calloc(madewaypoint->numnextwaypoints * sizeof(waypoint_t *), PU_LEVEL, NULL); Z_Calloc(madewaypoint->numnextwaypoints * sizeof(waypoint_t *), PU_LEVEL, NULL)
);
if (madewaypoint->nextwaypoints == NULL) if (madewaypoint->nextwaypoints == NULL)
{ {
I_Error("K_MakeWaypoint: Out of Memory allocating next waypoints."); I_Error("K_MakeWaypoint: Out of Memory allocating next waypoints.");
} }
madewaypoint->nextwaypointdistances = madewaypoint->nextwaypointdistances = static_cast<UINT32*>(
Z_Calloc(madewaypoint->numnextwaypoints * sizeof(fixed_t), PU_LEVEL, NULL); Z_Calloc(madewaypoint->numnextwaypoints * sizeof(fixed_t), PU_LEVEL, NULL)
);
if (madewaypoint->nextwaypointdistances == NULL) if (madewaypoint->nextwaypointdistances == NULL)
{ {
I_Error("K_MakeWaypoint: Out of Memory allocating next waypoint distances."); I_Error("K_MakeWaypoint: Out of Memory allocating next waypoint distances.");
@ -2153,7 +2163,7 @@ static boolean K_AllocateWaypointHeap(void)
{ {
// Allocate space in the heap for every mobj, it's possible some mobjs aren't linked up and not all of the // Allocate space in the heap for every mobj, it's possible some mobjs aren't linked up and not all of the
// heap allocated will be used, but it's a fairly reasonable assumption that this isn't going to be awful // heap allocated will be used, but it's a fairly reasonable assumption that this isn't going to be awful
waypointheap = Z_Calloc(numwaypointmobjs * sizeof(waypoint_t), PU_LEVEL, NULL); waypointheap = static_cast<waypoint_t*>(Z_Calloc(numwaypointmobjs * sizeof(waypoint_t), PU_LEVEL, NULL));
if (waypointheap == NULL) if (waypointheap == NULL)
{ {

View file

@ -196,11 +196,12 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj);
Input Arguments:- Input Arguments:-
mobj - mobj to get the waypoint for. mobj - mobj to get the waypoint for.
hint - a previously known nearby waypoint to optimize searching.
Return:- Return:-
The best waypoint for the mobj, or NULL if there were no matches The best waypoint for the mobj, or NULL if there were no matches
--------------------------------------------------*/ --------------------------------------------------*/
waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj); waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj, waypoint_t *const hint);
/*-------------------------------------------------- /*--------------------------------------------------

View file

@ -403,7 +403,7 @@ static void SPBSeek(mobj_t *spb, mobj_t *bestMobj)
if (spb_curwaypoint(spb) == -1) if (spb_curwaypoint(spb) == -1)
{ {
// Determine first waypoint. // Determine first waypoint.
curWaypoint = K_GetBestWaypointForMobj(spb); curWaypoint = K_GetBestWaypointForMobj(spb, NULL);
spb_curwaypoint(spb) = (INT32)K_GetWaypointHeapIndex(curWaypoint); spb_curwaypoint(spb) = (INT32)K_GetWaypointHeapIndex(curWaypoint);
} }
else else
@ -421,7 +421,7 @@ static void SPBSeek(mobj_t *spb, mobj_t *bestMobj)
} }
else else
{ {
destWaypoint = K_GetBestWaypointForMobj(bestMobj); destWaypoint = K_GetBestWaypointForMobj(bestMobj, NULL);
} }
if (curWaypoint != NULL) if (curWaypoint != NULL)