I am trying to implement the algorithm explained on this paper, used to traverse grid cells in order following a straight line, which is useful for ray tracing:
http
Initialization for X-coordinate variables (the same for Y)
DX = X2 - X1
tDeltaX = GridCellWidth / DX
tMaxX = tDeltaX * (1.0 - Frac(X1 / GridCellWidth))
//Frac if fractional part of float, for example, Frac(1.3) = 0.3, Frac(-1.7)=0.3
Example:
GridCellWidth, Height = 20
X1 = 5, X2 = 105
Y1 = 5, Y2 = 55
DX = 100, DY = 50
tDeltaX = 0.2, tDeltaY = 0.4
tMaxX = 0.2 * (1.0 - 0.25) = 0.15 //ray will meet first vertical line at this param
tMaxY = 0.4 * (1.0 - 0.25) = 0.3 //ray will meet first horizontal line at this param
We can see that first cell border will be met at parameter t = 0.15
The one that worked for me in 3D for both positive and negative directions (in CUDA C):
#define SIGN(x) (x > 0 ? 1 : (x < 0 ? -1 : 0))
#define FRAC0(x) (x - floorf(x))
#define FRAC1(x) (1 - x + floorf(x))
float tMaxX, tMaxY, tMaxZ, tDeltaX, tDeltaY, tDeltaZ;
int3 voxel;
float x1, y1, z1; // start point
float x2, y2, z2; // end point
dx = SIGN(x2 - x1);
if (dx != 0) tDeltaX = fmin(dx / (x2 - x1), 10000000.0f); else tDeltaX = 10000000.0f;
if (dx > 0) tMaxX = tDeltaX * FRAC1(x1); else tMaxX = tDeltaX * FRAC0(x1);
voxel.x = (int) x1;
int dy = SIGN(y2 - y1);
if (dy != 0) tDeltaY = fmin(dy / (y2 - y1), 10000000.0f); else tDeltaY = 10000000.0f;
if (dy > 0) tMaxY = tDeltaY * FRAC1(y1); else tMaxY = tDeltaY * FRAC0(y1);
voxel.y = (int) y1;
int dz = SIGN(z2 - z1);
if (dz != 0) tDeltaZ = fmin(dz / (z2 - z1), 10000000.0f); else tDeltaZ = 10000000.0f;
if (dz > 0) tMaxZ = tDeltaZ * FRAC1(z1); else tMaxZ = tDeltaZ * FRAC0(z1);
voxel.z = (int) z1;
while (true) {
if (tMaxX < tMaxY) {
if (tMaxX < tMaxZ) {
voxel.x += dx;
tMaxX += tDeltaX;
} else {
voxel.z += dz;
tMaxZ += tDeltaZ;
}
} else {
if (tMaxY < tMaxZ) {
voxel.y += dy;
tMaxY += tDeltaY;
} else {
voxel.z += dz;
tMaxZ += tDeltaZ;
}
}
if (tMaxX > 1 && tMaxY > 1 && tMaxZ > 1) break;
// process voxel here
}
Note, grid cell's width/height/depth are all equal to 1 in my case, but you can easily modify it for your needs.