Skip to content

Commit 87b12d7

Browse files
authored
VoxelRayTrace: logic & doc cleanup
The old version of this function was unnecessarily confusing due to working around bugs in the original ported code, which didn't handle negative direction vectors properly.
1 parent fde6654 commit 87b12d7

File tree

1 file changed

+14
-22
lines changed

1 file changed

+14
-22
lines changed

src/VoxelRayTrace.php

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ public static function betweenPoints(Vector3 $start, Vector3 $end) : \Generator{
8080

8181
//Initialize the step accumulation variables depending how far into the current block the start position is. If
8282
//the start position is on the corner of the block, these will be zero.
83-
$tMaxX = self::rayTraceDistanceToBoundary($start->x, $directionVector->x);
84-
$tMaxY = self::rayTraceDistanceToBoundary($start->y, $directionVector->y);
85-
$tMaxZ = self::rayTraceDistanceToBoundary($start->z, $directionVector->z);
83+
$tMaxX = self::distanceFactorToBoundary($start->x, $directionVector->x);
84+
$tMaxY = self::distanceFactorToBoundary($start->y, $directionVector->y);
85+
$tMaxZ = self::distanceFactorToBoundary($start->z, $directionVector->z);
8686

8787
//The change in t on each axis when taking a step on that axis (always positive).
8888
$tDeltaX = $directionVector->x == 0 ? 0 : $stepX / $directionVector->x;
@@ -118,34 +118,26 @@ public static function betweenPoints(Vector3 $start, Vector3 $end) : \Generator{
118118
}
119119

120120
/**
121-
* Returns the distance that must be travelled on an axis from the start point with the direction vector component to
122-
* cross a block boundary.
121+
* Used to decide which direction to move in first when beginning a ray trace.
123122
*
124-
* For example, given an X coordinate inside a block and the X component of a direction vector, will return the distance
125-
* travelled by that direction component to reach a block with a different X coordinate.
126-
*
127-
* Find the smallest positive t such that s+t*ds is an integer.
123+
* Examples:
124+
* s=0.25, ds=0.5 -> 0.25 + 1.5(0.5) = 1 -> returns 1.5
125+
* s=0.25, ds=-0.5 -> 0.25 + 0.5(-0.5) = 0 -> returns 0.5
126+
* s=1 ds=0.5 -> 1 + 2(0.5) = 2 -> returns 2
127+
* s=1 ds=-0.5 -> 1 + 0(-0.5) = 1 -> returns 0 (ds is negative and any subtraction will change 1 to 0.x)
128128
*
129129
* @param float $s Starting coordinate
130130
* @param float $ds Direction vector component of the relevant axis
131131
*
132-
* @return float Distance along the ray trace that must be travelled to cross a boundary.
132+
* @return float Number of times $ds must be added to $s to change its whole-number component.
133133
*/
134-
private static function rayTraceDistanceToBoundary(float $s, float $ds) : float{
134+
private static function distanceFactorToBoundary(float $s, float $ds) : float{
135135
if($ds == 0){
136136
return INF;
137137
}
138138

139-
if($ds < 0){
140-
$s = -$s;
141-
$ds = -$ds;
142-
143-
if(floor($s) == $s){ //exactly at coordinate, will leave the coordinate immediately by moving negatively
144-
return 0;
145-
}
146-
}
147-
148-
// problem is now s+t*ds = 1
149-
return (1 - ($s - floor($s))) / $ds;
139+
return $ds < 0 ?
140+
($s - floor($s)) / -$ds :
141+
(1 - ($s - floor($s))) / $ds;
150142
}
151143
}

0 commit comments

Comments
 (0)