Skip to content

Commit

Permalink
Bug fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
lostsquirrel1 committed Jun 16, 2024
1 parent bfdbe19 commit 92ff543
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 216 deletions.
198 changes: 123 additions & 75 deletions rts/Sim/Path/QTPFS/PathCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@

#include "System/Misc/TracyDefs.h"

// #pragma GCC push_options
// #pragma GCC optimize ("O0")

static void GetRectangleCollisionVolume(const SRectangle& r, CollisionVolume& v, float3& rm) {
RECOIL_DETAILED_TRACY_ZONE;
float3 vScales;
Expand All @@ -48,6 +51,11 @@ bool QTPFS::PathCache::MarkDeadPaths(const SRectangle& r, const NodeLayer& nodeL
if (pathView.empty())
return false;

// Used only for raw paths.
CollisionVolume rv;
float3 rm;
GetRectangleCollisionVolume(r, rv, rm);

// get root node - get layer as input, not the pathType
int pathType = nodeLayer.GetNodelayer();

Expand All @@ -61,10 +69,9 @@ bool QTPFS::PathCache::MarkDeadPaths(const SRectangle& r, const NodeLayer& nodeL
const uint32_t damageDepthShift = (QTPFS::QTNode::MAX_DEPTH - damageDepth) * QTPFS_NODE_NUMBER_SHIFT_STEP;
const uint32_t damageDepthMask = (-1U) << (damageDepthShift);


// LOG("%s: damaged %x", __func__
// , damagedNodeNumber);

// if (nodeLayer.GetNodelayer() == 16)
// LOG("%s: area damaged [%d,%d]-[%d,%d]: %x", __func__
// , r.x1, r.z1, r.x2, r.z2, damagedNodeNumber);

// "mark" any live path crossing the area of a terrain
// deformation, for which some or all of its waypoints
Expand All @@ -76,7 +83,7 @@ bool QTPFS::PathCache::MarkDeadPaths(const SRectangle& r, const NodeLayer& nodeL
, const IPath* path
, int i
) {
// if (path->GetID() == 131) {
// if (path->GetID() == 357564596) {
// LOG("%s: %d does [%x] overlap [%x] %d ?", __func__, i
// , damagedNodeNumber
// , node.nodeNumber
Expand Down Expand Up @@ -111,6 +118,9 @@ bool QTPFS::PathCache::MarkDeadPaths(const SRectangle& r, const NodeLayer& nodeL

// if (registry.any_of<PathIsDirty, PathSearchRef>(entity)) { continue; }

// path hasn't been built yet.
if (registry.any_of<PathIsTemp>(entity)) { continue; }

IPath* path = &pathView.get<IPath>(entity);

if (path->IsSynced() == false) { continue; }
Expand All @@ -123,104 +133,142 @@ bool QTPFS::PathCache::MarkDeadPaths(const SRectangle& r, const NodeLayer& nodeL
// LOG("%s: %x is processing", __func__, (int)entity);

const float3& pathMins = path->GetBoundingBoxMins();
const float3& pathMaxs = path->GetBoundingBoxMaxs();
const float3& pathMaxs = path->GetBoundingBoxMaxs(); // why is node wrong size?

// if rectangle does not overlap bounding-box, skip this path
if ((r.x2 * SQUARE_SIZE) < pathMins.x) { continue; }
if ((r.z2 * SQUARE_SIZE) < pathMins.z) { continue; }
if ((r.x1 * SQUARE_SIZE) > pathMaxs.x) { continue; }
if ((r.z1 * SQUARE_SIZE) > pathMaxs.z) { continue; }

// First check the boundary boxes
bool intersectsQuads = false;
auto& pathNodeList = path->GetNodeList();
const bool pathWasClean = path->IsBoundingBoxOverriden();

bool intersectsQuads = false;
bool intersectsPath = false;
int autoRefreshOnNode = 0;
const unsigned int minIdx = std::max(path->GetNextPointIndex(), 2U) - 2;
unsigned int pathGoodFromNodeId = path->GetFirstNodeIdOfCleanPath();
// if (path->GetID() == 290455867) {
// LOG("%s: %d nodeSize=%d start=%d", __func__, pathType, int(pathNodeList.size()), pathGoodFromNodeId);
// LOG("%s: pathNodeList=%d, NumPoints=%d", __func__, int(pathNodeList.size()), int(path->NumPoints()));
// }

// reverse search to determine where any path repair will be needed up to.
for (int i = pathNodeList.size(); i > pathGoodFromNodeId; --i) {
const QTPFS::IPath::PathNodeData& node = pathNodeList[i-1];
if (path->IsRawPath() || pathNodeList.size() == 0) {
assert(path->NumPoints() == 2);
const float3& p0 = path->GetPoint(0);
const float3& p1 = path->GetPoint(1);

const bool p0InRect =
((p0.x >= (r.x1 * SQUARE_SIZE) && p0.x < (r.x2 * SQUARE_SIZE)) &&
(p0.z >= (r.z1 * SQUARE_SIZE) && p0.z < (r.z2 * SQUARE_SIZE)));
const bool p1InRect =
((p1.x >= (r.x1 * SQUARE_SIZE) && p1.x < (r.x2 * SQUARE_SIZE)) &&
(p1.z >= (r.z1 * SQUARE_SIZE) && p1.z < (r.z2 * SQUARE_SIZE)));
const bool havePointInRect = (p0InRect || p1InRect);

// NOTE:
// box-volume tests in its own space, but points are
// in world-space so we must inv-transform them first
// (p0 --> p0 - rm, p1 --> p1 - rm)
const bool
xRangeInRect = (p0.x >= (r.x1 * SQUARE_SIZE) && p1.x < (r.x2 * SQUARE_SIZE)),
xRangeExRect = (p0.x < (r.x1 * SQUARE_SIZE) && p1.x >= (r.x2 * SQUARE_SIZE)),
zRangeInRect = (p0.z >= (r.z1 * SQUARE_SIZE) && p1.z < (r.z2 * SQUARE_SIZE)),
zRangeExRect = (p0.z < (r.z1 * SQUARE_SIZE) && p1.z >= (r.z2 * SQUARE_SIZE));
const bool edgeCrossesRect =
(xRangeExRect && zRangeInRect) ||
(xRangeInRect && zRangeExRect) ||
CCollisionHandler::IntersectBox(&rv, p0 - rm, p1 - rm, NULL);

// LOG("%s: %x havePointInRect=%d edgeCrossesRect=%d", __func__, (int)entity
// , (int)havePointInRect, (int)edgeCrossesRect);

// remember the ID of each path affected by the deformation
intersectsPath = (havePointInRect || edgeCrossesRect);
}
else
{
// First check the boundary boxes
const bool pathWasClean = path->IsBoundingBoxOverriden();

// if (path->GetID() == 357564596) {
// LOG("%s: %d nodeSize=%d start=%d", __func__, pathType, int(pathNodeList.size()), pathGoodFromNodeId);
// LOG("%s: pathNodeList=%d, NumPoints=%d", __func__, int(pathNodeList.size()), int(path->NumPoints()));
// }

// If the path is shared, then we need to check bad nodes so that path sharing can be stopped if required.
// Otherwise, bad nodes can be ignored.
if (node.IsNodeBad()) {
if (pathWasClean & !intersectsQuads) {
if (testNodeDamage(node, path, i-1))
intersectsQuads = true;
const uint32_t pathNodeStart = (pathWasClean) ? pathNodeList.size() : path->GetGoodNodeCount();

// reverse search to determine where any path repair will be needed up to.
for (int i = pathNodeStart; i > pathGoodFromNodeId; --i) {
const QTPFS::IPath::PathNodeData& node = pathNodeList[i-1];

// If the path is shared, then we need to check bad nodes so that path sharing can be stopped if required.
// Otherwise, bad nodes can be ignored.
if (node.IsNodeBad()) {
assert(pathWasClean);
if (/*pathWasClean &*/ !intersectsQuads) {
if (testNodeDamage(node, path, i-1))
intersectsQuads = true;
}
continue;
}
continue;
}

if (!testNodeDamage(node, path, i-1)) { continue; }

// int pIndex = (i - 1) + int(path->NumPoints() - pathNodeList.size());
// if (pIndex > 0) {
// const float3& p0 = path->GetPoint(pIndex);
// const float3& p1 = path->GetPoint(pIndex - 1);

// LOG("%s: node [%d,%d][%d,%d] p0 = (%f,%f)[%d,%d] p1 = (%f,%f)[%d,%d]", __func__
// , node.xmin, node.zmin, node.xmax, node.zmax
// , p0.x, p0.z, int(p0.x / SQUARE_SIZE), int(p0.z / SQUARE_SIZE)
// , p1.x, p1.z, int(p1.x / SQUARE_SIZE), int(p1.z / SQUARE_SIZE)
// );
// }
if (!testNodeDamage(node, path, i-1)) { continue; }

// LOG("%s: node %d is hit", __func__, i-1);
// int pIndex = (i - 1) + int(path->NumPoints() - pathNodeList.size());
// if (pIndex > 0) {
// const float3& p0 = path->GetPoint(pIndex);
// const float3& p1 = path->GetPoint(pIndex - 1);

pathGoodFromNodeId = i;
intersectsQuads = true;
break;
}
// if (path->GetID() == 290455867)
// LOG("%s: now pathGoodFromNodeId=%d", __func__, pathGoodFromNodeId);
// LOG("%s: node [%d,%d][%d,%d] p0 = (%f,%f)[%d,%d] p1 = (%f,%f)[%d,%d]", __func__
// , node.xmin, node.zmin, node.xmax, node.zmax
// , p0.x, p0.z, int(p0.x / SQUARE_SIZE), int(p0.z / SQUARE_SIZE)
// , p1.x, p1.z, int(p1.x / SQUARE_SIZE), int(p1.z / SQUARE_SIZE)
// );
// }

bool intersectsPath = false;
int autoRefreshOnNode = 0;
// LOG("%s: node %d is hit", __func__, i-1);

const unsigned int minIdx = std::max(path->GetNextPointIndex(), 2U) - 2;
pathGoodFromNodeId = i;
intersectsQuads = true;
break;
}
// if (path->GetID() == 290455867)
// LOG("%s: now pathGoodFromNodeId=%d", __func__, pathGoodFromNodeId);

// If a reverse search finds no collisions through the whole path, then a forward search isn't needed.
if (pathGoodFromNodeId > 0) {
// figure out if <path> has at least one edge crossing <r>
// we only care about the segments we have not yet visited
// If a reverse search finds no collisions through the whole path, then a forward search isn't needed.
if (pathGoodFromNodeId > 0) {
// figure out if <path> has at least one edge crossing <r>
// we only care about the segments we have not yet visited

// Forward search. A hit here tells us, when the path needs to be regenerated.
// The last two path points reside in the last node.
const unsigned int triggerIndex = path->GetRepathTriggerIndex();
const unsigned int maxIdx = (triggerIndex > 0) ? triggerIndex : pathNodeList.size();
const unsigned int rPathBadAtNodeId = pathGoodFromNodeId - 1;
// Forward search. A hit here tells us, when the path needs to be regenerated.
// The last two path points reside in the last node.
const unsigned int triggerIndex = path->GetRepathTriggerIndex();
const unsigned int maxIdx = (triggerIndex > 0) ? triggerIndex : pathNodeList.size();
const unsigned int rPathBadAtNodeId = pathGoodFromNodeId - 1;

// if (path->GetID() == 131)
// LOG("%s: minIdx %d, maxIdx %d", __func__, minIdx, maxIdx);
// if (path->GetID() == 357564596)
// LOG("%s: minIdx %d, maxIdx %d", __func__, minIdx, maxIdx);

for (unsigned int i = minIdx; i < maxIdx; i++) {
const QTPFS::IPath::PathNodeData& node = pathNodeList[i];
for (unsigned int i = minIdx; i < maxIdx; i++) {
const QTPFS::IPath::PathNodeData& node = pathNodeList[i];

// Bad nodes only occur at the end, if found, then stop. They do not affect the path the unit is
// following.
if (node.IsNodeBad()) { break; }
// Bad nodes only occur at the end, if found, then stop. They do not affect the path the unit is
// following.
if (node.IsNodeBad()) { break; }

intersectsPath = (i >= rPathBadAtNodeId) || testNodeDamage(node, path, i);
intersectsPath = (i >= rPathBadAtNodeId) || testNodeDamage(node, path, i);

// remember the ID of each path affected by the deformation
if (intersectsPath) {
bool triggerImmediateRepath = ( i <= (minIdx + 1) );
if (!triggerImmediateRepath)
autoRefreshOnNode = i + 1; // trigger happens when waypoints are requested, which always grabs one ahead.
// remember the ID of each path affected by the deformation
if (intersectsPath) {
bool triggerImmediateRepath = ( i <= (minIdx + 1) );
if (!triggerImmediateRepath)
autoRefreshOnNode = i + 1; // trigger happens when waypoints are requested, which always grabs one ahead.

// LOG("%s: %x is Dirtied (pathType %d)", __func__, (int)entity, pathType);
break;
// LOG("%s: %x is Dirtied (pathType %d)", __func__, (int)entity, pathType);
break;
}
}
}
}

if (intersectsQuads || intersectsPath) {
bool remainingPathIsDirty = (pathGoodFromNodeId > minIdx);
bool remainingPathIsDirty = (pathGoodFromNodeId > minIdx) || path->IsRawPath();

DirtyPathDetail dirtyPathDetail;
dirtyPathDetail.pathEntity = entity;
Expand All @@ -232,7 +280,7 @@ bool QTPFS::PathCache::MarkDeadPaths(const SRectangle& r, const NodeLayer& nodeL
// out the path before the owner's position.
dirtyPathDetail.nodesAreCleanFromNodeId = std::max(pathGoodFromNodeId, minIdx);

// if (path->GetID() == 131)
// if (path->GetID() == 357564596)
// LOG("%s: trig=%d, clearPath=%d, clean=%d", __func__
// , dirtyPathDetail.autoRepathTrigger
// , int(dirtyPathDetail.clearPath)
Expand All @@ -247,4 +295,4 @@ bool QTPFS::PathCache::MarkDeadPaths(const SRectangle& r, const NodeLayer& nodeL
return true;
}


// #pragma GCC pop_options
19 changes: 14 additions & 5 deletions rts/Sim/Path/QTPFS/PathManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,15 +760,19 @@ void QTPFS::PathManager::Update() {
if (dirtyPathDetail.autoRepathTrigger > 0) {
// Rather than repath immediately we can defer the repath until the unit
// gets closer to the damaged area.
unsigned int currRepathTrigger = path.GetRepathTriggerIndex();
const unsigned int currRepathTrigger = path.GetRepathTriggerIndex();
if (currRepathTrigger == 0 || currRepathTrigger > dirtyPathDetail.autoRepathTrigger) {
path.SetRepathTriggerIndex(dirtyPathDetail.autoRepathTrigger);
path.SetBoundingBox();
}
}
// LOG("%s: clean path pos %d -> %d", __func__
// , path.GetFirstNodeIdOfCleanPath(), dirtyPathDetail.nodesAreCleanFromNodeId);
path.SetFirstNodeIdOfCleanPath(dirtyPathDetail.nodesAreCleanFromNodeId);

// Ensure the last clean node is always taken in case multiple nodes were processed this frame.
const int curCleanNodeId = path.GetFirstNodeIdOfCleanPath();
const int nextCleanNodeId = dirtyPathDetail.nodesAreCleanFromNodeId;
path.SetFirstNodeIdOfCleanPath(std::max(curCleanNodeId, nextCleanNodeId));
// if (path.IsBoundingBoxOverriden())
path.SetBoundingBox();
//}
Expand Down Expand Up @@ -905,7 +909,7 @@ void QTPFS::PathManager::ExecuteQueuedSearches() {
registry.remove<PathSearchRef>(pathEntity);

// If the node data wasn't recorded, then the path isn't shareable.
if (!path->IsBoundingBoxOverriden()) {
if (!path->IsBoundingBoxOverriden() || path->GetNodeList().size() == 0) {
RemovePathFromShared(pathEntity);
RemovePathFromPartialShared(pathEntity);
}
Expand Down Expand Up @@ -1165,6 +1169,9 @@ void QTPFS::PathManager::QueueDeadPathSearches() {
}
}

// #pragma GCC push_options
// #pragma GCC optimize ("O0")

unsigned int QTPFS::PathManager::QueueSearch(
const CSolidObject* object,
const MoveDef* moveDef,
Expand Down Expand Up @@ -1250,17 +1257,19 @@ unsigned int QTPFS::PathManager::QueueSearch(
return (newPath->GetID());
}

// #pragma GCC pop_options

unsigned int QTPFS::PathManager::RequeueSearch(
IPath* oldPath, const bool allowRawSearch, const bool allowPartialSearch, const bool allowRepair
) {
RECOIL_DETAILED_TRACY_ZONE;
assert(!ThreadPool::inMultiThreadedSection);
entt::entity pathEntity = entt::entity(oldPath->GetID());

assert(!registry.all_of<PathDelayedDelete>(pathEntity));
// assert(!registry.all_of<PathDelayedDelete>(pathEntity));

// If a path request is already in progress then don't create another one.
if (registry.all_of<PathSearchRef>(pathEntity))
if (registry.any_of<PathSearchRef, PathDelayedDelete>(pathEntity))
return (oldPath->GetID());

if (oldPath->GetOwner()->objectUsable == false) {
Expand Down
Loading

0 comments on commit 92ff543

Please sign in to comment.