Open SkybuckFlying opened 2 years ago
This algorithm seems somewhat flawed ? Tried to translate it to Delphi, getting some slightly skewed rays: procedure getHelpers ( const cellSize : integer; const pos, dir : double; out Tile : integer; out dTile : integer; out dt, ddt : double ); begin tile := floor(pos / cellSize) + 1;
if dir > 0 then
begin
dTile := 1;
dt := ((tile+0)*cellSize - pos) / dir
end else
if dir = 0 then
begin
dt := 10000000000000;
end else
begin
dTile := -1;
dt := ((tile-1)*cellSize - pos) / dir
end;
if dir <> 0 then
begin
ddt := dTile * cellSize / dir;
end else
begin
ddt := 1000000000000;
end;
end;
procedure TForm1.castRay_clearer_alldirs_improved_transformed ( rayStartX, rayStartY, rayStopX, rayStopY : double;
gridCellWidth,
gridCellHeight,
gridWidth,
gridHeight : integer
); var tileX : integer; dtileX : integer; dtX, ddtX : double; tileY : integer; dtileY : integer; dtY, ddtY : double; t : double; dt : double;
Length : double;
DeltaX, DeltaY : double;
rayDirX, rayDirY : double;
begin DeltaX := rayStopX - rayStartX; DeltaY := rayStopY - rayStartX;
if (DeltaX = 0) and (DeltaY = 0) then exit;
Length := sqrt( (DeltaX * DeltaX) + (DeltaY * DeltaY) );
rayDirX := DeltaX {/ Length};
rayDirY := DeltaY {/ Length};
getHelpers( gridCellWidth, rayStartX, rayDirX, tileX, dtileX, dtX, ddtX);
getHelpers( gridCellHeight, rayStartY, rayDirY, tileY, dtileY, dtY, ddtY);
t := 0;
if rayDirX*rayDirX + rayDirY*rayDirY > 0 then
begin
//-- start and end should not be at the same point
while (tileX > 0) and (tileX <= GridWidth) and
(tileY > 0) and (tileY <= GridHeight) do
begin
//grid[tileY][tileX] = true
//mark(ray.startX + ray.dirX * t, ray.startY + ray.dirY * t)
ProcessVoxel( tileX, tileY, 0, 0,0,0, 0);
if dtX < dtY then
begin
tileX := tileX + dtileX;
dt := dtX;
t := t + dt;
dtX := dtX + ddtX - dt;
dtY := dtY - dt;
end else
begin
tileY := tileY + dtileY;
dt := dtY;
t := t + dt;
dtX := dtX - dt;
dtY := dtY + ddtY - dt;
end;
end;
end else
begin
// grid[tileY][tileX] = true
ProcessVoxel( tileX, tileY, 0, 0,0,0, 0);
end;
end;
Also tried to fix the by zero division by setting it big.
Another version to compensate for my grid boundary min x basically grid start:
procedure getHelpers ( const GridStart : integer; const cellSize : integer; const pos, dir : double; out Tile : integer; out dTile : integer; out dt, ddt : double ); begin tile := floor(pos / cellSize) + 1 - GridStart;
if dir > 0 then
begin
dTile := 1;
dt := ((tile+0+GridStart)*cellSize - pos) / dir
end else
if dir = 0 then
begin
dt := 1000000000000000;
end else
begin
dTile := -1;
dt := ((tile-1 + GridStart)*cellSize - pos) / dir
end;
if dir <> 0 then
begin
ddt := (dTile * cellSize) / dir;
end else
begin
ddt := 100000000000000;
end;
end;
procedure TForm1.castRay_clearer_alldirs_improved_transformed ( rayStartX, rayStartY, rayStopX, rayStopY : double;
gridCellWidth,
gridCellHeight,
gridWidth,
gridHeight : integer
); var tileX : integer; dtileX : integer; dtX, ddtX : double; tileY : integer; dtileY : integer; dtY, ddtY : double; t : double; dt : double;
Length : double;
DeltaX, DeltaY : double;
rayDirX, rayDirY : double;
begin
DeltaX := rayStopX - rayStartX;
DeltaY := rayStopY - rayStartX;
if (DeltaX = 0) and (DeltaY = 0) then exit;
Length := sqrt( (DeltaX * DeltaX) + (DeltaY * DeltaY) );
rayDirX := DeltaX / Length;
rayDirY := DeltaY / Length;
getHelpers( mBoundaryMinX, gridCellWidth, rayStartX, rayDirX, tileX, dtileX, dtX, ddtX);
getHelpers( mBoundaryMinY, gridCellHeight, rayStartY, rayDirY, tileY, dtileY, dtY, ddtY);
t := 0;
if rayDirX*rayDirX + rayDirY*rayDirY > 0 then
begin
//-- start and end should not be at the same point
while (tileX > 0) and (tileX <= GridWidth) and
(tileY > 0) and (tileY <= GridHeight) do
begin
//grid[tileY][tileX] = true
//mark(ray.startX + ray.dirX * t, ray.startY + ray.dirY * t)
ProcessVoxel( tileX, tileY, 0, 0,0,0, 0);
if dtX < dtY then
begin
tileX := tileX + dtileX;
dt := dtX;
t := t + dt;
dtX := dtX + ddtX - dt;
dtY := dtY - dt;
end else
begin
tileY := tileY + dtileY;
dt := dtY;
t := t + dt;
dtX := dtX - dt;
dtY := dtY + ddtY - dt;
end;
end;
end else
begin
// grid[tileY][tileX] = true
ProcessVoxel( tileX, tileY, 0, 0,0,0, 0);
end;
end;
Line goes like a birds eye, doesn't go to Y/below kind strange and funny/eye like looking.
Sorry, but you can't just say the code is flawed without any further description of the problem, paste Delphi code, which I cannot try out, since I don't have anything set up and expect me to spend time on it. Even the formatting is all messed up. Please try to have a more concise, easily reproducible description of your problem next time.
Regarding the division by zero problem, you are likely right. When I try it out, it still works though, but I cannot figure why exactly or how to fix it properly without spending more than a few minutes on it. Considering I am not very interested in this at all anymore, I will archive this repository.
I decided that it would be good to keep PRs open, so someone could fix the code in here and people don't look up/use wrong code, but I myself won't do it. So I won't archive the repo for now. If you want, you can download love 10 and come up with a fix using the example application (and PR it). I will leave this issue open as long as the code is wrong, but I won't spend time on it, sorry.
I am not sure if your code is wrong or if the translation to Delphi went wrong.
Meanwhile I tried somebody elses solution, somebody who creates webgl2 lesssons on youtube.
Converted his code, integrated mine and had a pretty good working piece of code. So it's not like I need this code fixed, just pointing out the troubles I had with it, it's interesting to try different solutions to see adventages and disadventages of each solution.
I don't even know in what language this was programmed, apperently some language I never programmed in, though I did my best to try and convert it. So take it all with a grain of salt for now, however divide by zero mistakes/short comings are easy to spot, maybe that language auto solves it, seen many examples with these kinds of problems, usually it's solved by other skipping that code with a branch to skip over it, so to completely ignore that dimension or most code set the value that was supposed to be calculated to very high like 1000000000.
I see a lot of these fast voxel traversal algorithms. A lot of them have divide by zero problems.
For example:
function getHelpers(cellSize, pos, dir) local tile = math.floor(pos / cellSize) + 1
end
dir could be zero
Fortunately this seems to be the only divisions in this algorithm... so maybe solveable ;)