Hi everyone,
I have tried looking for a solution online and tried a variety of implementations of a DDA algorithm, but none of them seem to give the result I need.
I am programming in Unreal Engine 4, and I generate a 2D grid of 200x200 (UE equivalent to 2mx2m) grid squares over the level. The grid starts at the minimum world XY coordinates for the nav mesh (if one is present) and ends at the max XY extent. The grid size is rounded to the nearest 200 units (so if the minimum X extent is -15680 then it is rounded to -15800 for example). It then generates however many 200x200 grid squares are needed to cover the nav mesh area.
I want to test trace collisions against objects on the grid, and I want to use a DDA algorithm as a means to filter the number of checks. The reason I do this instead of using UE4's default capsule components is because I'm making a Total War type of game where there could be 10k soldiers moving around at once, and 10k moving collision components chokes the engine to a crawl. The basic premise is: iterate through the grid squares intersected by the trace (converted to a 2D line) in order of proximity to the trace origin, and then perform 3D ray-capsule collision checks against any soldiers in those grid squares, ending when a collision is found.
My DDA algorithm isn't quite working however, as you can see below:
https://gyazo.com/9c474ad5c8e2c1dea4edd4360804471f
There are very clear gaps where the blue trace line passes through a grid square but it is not highlighted.
Below is the code I am using:
void ACollisionGridGenerator::TestDDATrace(FVector StartLocation, FVector EndLocation) {
DrawDebugLine(GetWorld(), StartLocation, EndLocation, FColor::Blue, false, 5.0f, 0, 2.0f);
// Find the Grid X and Y index for the start of the trace
double StartIndexX = (double)FMath::FloorToInt(FMath::Abs(MinGridExtents.X - StartLocation.X) * Multiplier);
double StartIndexY = (double)FMath::FloorToInt(FMath::Abs(MinGridExtents.Y - StartLocation.Y) * Multiplier);
// Find the Grid X and Y index for the end of the trace
double EndIndexX = (double)FMath::FloorToInt(FMath::Abs(MinGridExtents.X - EndLocation.X) * Multiplier);
double EndIndexY = (double)FMath::FloorToInt(FMath::Abs(MinGridExtents.Y - EndLocation.Y) * Multiplier);
double dx = (double)(EndIndexX - StartIndexX);
double dy = (double)(EndIndexY - StartIndexY);
double Step = 0.0f;
int StepIndex = 1;
double x, y = 0.0f;
if (FMath::Abs(dx) >= FMath::Abs(dy)) {
Step = FMath::Abs(dx);
}
else {
Step = FMath::Abs(dy);
}
dx = dx / Step;
dy = dy / Step;
x = StartIndexX;
y = StartIndexY;
StepIndex = 1;
FBox CollisionBox;
while (StepIndex <= Step) {
int32 CurrGridIndex = (x * NumGridSectionsY) + y;
DrawGridSquareAtIndex(CurrGridIndex, StartLocation.Z, 5.0f);
x = x + dx;
y = y + dy;
StepIndex++;
}
}
DrawGridSquareAtIndex is what draws the yellow squares, so as you can see, some grid squares are just missed entirely in the while loop.
Any help would be much appreciated, as I've tried several implementations of DDA and this is the one that comes the closest, but is still not acceptable.
Thanks!