Use ray tracing algorithm in BitmapTestLine

fix-squashed-planets
Rasmus Brönnegård 2022-02-02 20:15:30 +01:00
parent d9f3078396
commit e2d4dd6995
2 changed files with 52 additions and 41 deletions

View File

@ -1636,7 +1636,7 @@ int CTaskGoto::BeamShortcut()
for ( i=m_bmTotal ; i>=m_bmIndex+2 ; i-- ) // tries from the last for ( i=m_bmTotal ; i>=m_bmIndex+2 ; i-- ) // tries from the last
{ {
if ( BitmapTestLine(m_bmPoints[m_bmIndex], m_bmPoints[i], 0.0f, false) ) if ( BitmapTestLine(m_bmPoints[m_bmIndex], m_bmPoints[i]) )
{ {
return i; // bingo, found return i; // bingo, found
} }
@ -1866,62 +1866,73 @@ Error CTaskGoto::BeamSearch(const Math::Vector &start, const Math::Vector &goal,
// Tests if a path along a straight line is possible. // Tests if a path along a straight line is possible.
bool CTaskGoto::BitmapTestLine(const Math::Vector &start, const Math::Vector &goal, bool CTaskGoto::BitmapTestLine(const Math::Vector &start, const Math::Vector &goal)
float stepAngle, bool bSecond)
{ {
Math::Vector pos, inc;
float dist, step;
float distNoB2;
int i, max, x, y;
if ( m_bmArray == nullptr ) return true; if ( m_bmArray == nullptr ) return true;
dist = Math::DistanceProjected(start, goal); const Math::Point startInGrid = Math::Point((start.x+1600.0f)/BM_DIM_STEP, (start.z+1600.0f)/BM_DIM_STEP);
if ( dist == 0.0f ) return true; const Math::Point goalInGrid = Math::Point((goal.x+1600.0f)/BM_DIM_STEP, (goal.z+1600.0f)/BM_DIM_STEP);
step = BM_DIM_STEP*0.5f;
inc.x = (goal.x-start.x)*step/dist; const int startXInt = static_cast<int>(startInGrid.x);
inc.z = (goal.z-start.z)*step/dist; const int startYInt = static_cast<int>(startInGrid.y);
const int goalXInt = static_cast<int>(goalInGrid.x);
const int goalYInt = static_cast<int>(goalInGrid.y);
pos = start; if (startXInt == goalXInt && startYInt == goalYInt)
if ( bSecond )
{ {
x = static_cast<int>((pos.x+1600.0f)/BM_DIM_STEP); return true;
y = static_cast<int>((pos.z+1600.0f)/BM_DIM_STEP);
BitmapSetDot(1, x, y); // puts the flag as the starting point
} }
max = static_cast<int>(dist/step); // Grid traversal based on
if ( max == 0 ) max = 1; // Amanatides, John, and Andrew Woo. "A fast voxel traversal algorithm for ray tracing." Eurographics. Vol. 87. No. 3. 1987.
distNoB2 = BM_DIM_STEP*sqrtf(2.0f)/sinf(stepAngle); // http://www.cse.yorku.ca/~amana/research/grid.pdf
for ( i=0 ; i<max ; i++ )
Math::Point dirInGrid = goalInGrid - startInGrid;
dirInGrid /= std::hypot(dirInGrid.x, dirInGrid.y);
const int stepX = dirInGrid.x > 0.0f ? 1 : -1;
const int stepY = dirInGrid.y > 0.0f ? 1 : -1;
// At what t does the ray enter the next cell?
float tMaxX =
dirInGrid.x > 0.0 ? (std::floor(startInGrid.x) - startInGrid.x + 1) / dirInGrid.x :
dirInGrid.x < 0.0 ? (std::floor(startInGrid.x) - startInGrid.x) / dirInGrid.x :
std::numeric_limits<float>::infinity();
float tMaxY =
dirInGrid.y > 0.0 ? (std::floor(startInGrid.y) - startInGrid.y + 1) / dirInGrid.y :
dirInGrid.y < 0.0 ? (std::floor(startInGrid.y) - startInGrid.y) / dirInGrid.y :
std::numeric_limits<float>::infinity();
// How much t is needed to step from one column/row to another?
// stepX = dir.x * t
// stepX / dir.x = t
const float tDeltaX = static_cast<float>(stepX) / dirInGrid.x;
const float tDeltaY = static_cast<float>(stepY) / dirInGrid.y;
// Traverse the grid
const int numIntersections =
std::abs(goalXInt - startXInt) +
std::abs(goalYInt - startYInt);
int x = startXInt;
int y = startYInt;
for ( int i = 0; i < numIntersections; ++i )
{ {
if ( i == max-1 ) if ( tMaxX < tMaxY )
{ {
pos = goal; // tests the point of arrival tMaxX += tDeltaX;
x += stepX;
} }
else else
{ {
pos.x += inc.x; tMaxY += tDeltaY;
pos.z += inc.z; y += stepY;
} }
if ( BitmapTestDot(0, x, y) )
x = static_cast<int>((pos.x+1600.0f)/BM_DIM_STEP);
y = static_cast<int>((pos.z+1600.0f)/BM_DIM_STEP);
if ( bSecond )
{ {
if ( i > 2 && BitmapTestDot(1, x, y) ) return false; return false;
if ( step*(i+1) > distNoB2 && i < max-2 )
{
BitmapSetDot(1, x, y);
}
} }
if ( BitmapTestDot(0, x, y) ) return false;
} }
return true; return true;
} }

View File

@ -104,7 +104,7 @@ protected:
void BeamInit(); void BeamInit();
Error BeamSearch(const Math::Vector &start, const Math::Vector &goal, float goalRadius); Error BeamSearch(const Math::Vector &start, const Math::Vector &goal, float goalRadius);
bool BitmapTestLine(const Math::Vector &start, const Math::Vector &goal, float stepAngle, bool bSecond); bool BitmapTestLine(const Math::Vector &start, const Math::Vector &goal);
void BitmapObject(); void BitmapObject();
void BitmapTerrain(const Math::Vector &min, const Math::Vector &max); void BitmapTerrain(const Math::Vector &min, const Math::Vector &max);
void BitmapTerrain(int minx, int miny, int maxx, int maxy); void BitmapTerrain(int minx, int miny, int maxx, int maxy);