Skip to content

Commit

Permalink
Fix GuiTraceRay for radardrift (#1764)
Browse files Browse the repository at this point in the history
* Introduce GetQuadsOnWideRay and use it for the purposes of tracing along a ray of certain width.
  • Loading branch information
saurtron authored Dec 1, 2024
1 parent 3647f78 commit 35c914e
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 1 deletion.
7 changes: 6 additions & 1 deletion rts/Game/TraceRay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,12 @@ float GuiTraceRay(
CollisionQuery cq;

QuadFieldQuery qfQuery;
quadField.GetQuadsOnRay(qfQuery, start, dir, maxRayLength);
if (useRadar) {
const float allyTeamError = losHandler->GetAllyTeamRadarErrorSize(gu->myAllyTeam);
quadField.GetQuadsOnWideRay(qfQuery, start, dir, maxRayLength, allyTeamError);
} else {
quadField.GetQuadsOnRay(qfQuery, start, dir, maxRayLength);
}

for (const int quadIdx: *qfQuery.quads) {
const CQuadField::Quad& quad = quadField.GetQuad(quadIdx);
Expand Down
91 changes: 91 additions & 0 deletions rts/Sim/Misc/QuadField.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,97 @@ void CQuadField::GetQuadsOnRay(QuadFieldQuery& qfq, const float3& start, const f
}


// Test with wide ray that also extends width at the extremes.
void CQuadField::GetQuadsOnWideRay(QuadFieldQuery& qfq, const float3& start, const float3& dir, float length, float width)
{
RECOIL_DETAILED_TRACY_ZONE;
dir.AssertNaNs();
start.AssertNaNs();

const float3 baseTo = start + (dir * length);

const bool noZdir = (math::floor(start.z * invQuadSize.y) == math::floor(baseTo.z * invQuadSize.y));

// special case, prevent div0.
if (noZdir) {
// Having noZdir will roughly result in a rectangle.
float startX = start.x;
float finalX = baseTo.x;
if (finalX < startX)
std::swap(startX, finalX);

float startZ = start.z;
float finalZ = baseTo.z;
if (finalZ < startZ)
std::swap(startZ, finalZ);

const float3 mins(startX - width, 0, startZ - width);
const float3 maxs(finalX + width, 0, finalZ + width);

return GetQuadsRectangle(qfq, mins, maxs);
}

auto& queryQuads = *(qfq.quads = tempQuads[qfq.threadOwner].ReserveVector());

// iterate z-range; compute which columns (x) are touched for each row (z)
const float3 normDirPlanar = float3(dir.x, 0.0, dir.z).UnsafeNormalize(); // we already checked for unsafe cases before
const float widthFactor = std::abs(normDirPlanar.z / dir.z) * width;

// Start and stop a bit further to account for width
const float3 to = baseTo + dir * widthFactor;
length = (to - start).Length();

// taking normDirPlanar.z since we want perpendicular proportion
const float mapMarginX = std::abs(width * normDirPlanar.z);

// From here on, basically a copy of the same section of GetQuadsOnRay, just here extending
// startX and finalX with mapMarginX before converting to quad indexes and pushing each row.

float startZuc = start.z * invQuadSize.y;
float finalZuc = to.z * invQuadSize.y;

if (finalZuc < startZuc)
std::swap(startZuc, finalZuc);

const int startZ = std::clamp <int> (startZuc, 0, numQuadsZ - 1);
const int finalZ = std::clamp <int> (finalZuc, 0, numQuadsZ - 1);

assert(finalZ < quadSizeZ);

const float invDirZ = 1.0f / dir.z;

for (int z = startZ; z <= finalZ; z++) {
float t0 = ((z ) * quadSizeZ - start.z) * invDirZ;
float t1 = ((z + 1) * quadSizeZ - start.z) * invDirZ;

if ((startZuc < 0 && z == 0) || (startZuc >= numQuadsZ && z == finalZ))
t0 = ((startZuc ) * quadSizeZ - start.z) * invDirZ;

if ((finalZuc < 0 && z == 0) || (finalZuc >= numQuadsZ && z == finalZ))
t1 = ((finalZuc + 1) * quadSizeZ - start.z) * invDirZ;

t0 = std::clamp(t0, 0.0f, length);
t1 = std::clamp(t1, 0.0f, length);

float mapStartX = dir.x * t0 + start.x;
float mapFinalX = dir.x * t1 + start.x;

if (mapFinalX < mapStartX)
std::swap(mapStartX, mapFinalX);

const unsigned startX = std::clamp <int> ((mapStartX - mapMarginX) * invQuadSize.x, 0, numQuadsX - 1);
const unsigned finalX = std::clamp <int> ((mapFinalX + mapMarginX) * invQuadSize.x, 0, numQuadsX - 1);

const int row = std::clamp(z, 0, numQuadsZ - 1) * numQuadsX;

for (unsigned x = startX; x <= finalX; x++) {
queryQuads.push_back(row + x);
assert(static_cast<unsigned>(queryQuads.back()) < baseQuads.size());
}
}
}



#ifndef UNIT_TEST
bool CQuadField::InsertUnitIf(CUnit* unit, const float3& wpos)
Expand Down
1 change: 1 addition & 0 deletions rts/Sim/Misc/QuadField.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class CQuadField : spring::noncopyable
void GetQuads(QuadFieldQuery& qfq, float3 pos, float radius);
void GetQuadsRectangle(QuadFieldQuery& qfq, const float3& mins, const float3& maxs);
void GetQuadsOnRay(QuadFieldQuery& qfq, const float3& start, const float3& dir, float length);
void GetQuadsOnWideRay(QuadFieldQuery& qfq, const float3& start, const float3& dir, float length, float width);

void GetUnitsAndFeaturesColVol(
const float3& pos,
Expand Down

0 comments on commit 35c914e

Please sign in to comment.