Last active
April 22, 2020 17:54
-
-
Save paniq/dce0d588fae29b6e56953d3026106195 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fn iCube (ro rd) | |
""""For ``ro + rd * t`` returns near and far ``t`` that intersect with | |
a cube of unit size at origin, as well as a boolean indicating | |
whether a hit was made, and normal vectors for entry and exit point | |
which can also be used as integer offsets into the neighboring cubes. | |
let stp = (sign rd) | |
# avoid a situation where inf - inf = nan | |
let p = ((- ro) * stp) | |
let rdinv = (/ (abs rd)) | |
let h0 = ((p - 0.5) * rdinv) | |
let h1 = ((p + 0.5) * rdinv) | |
let near = (max (unpack h0)) | |
let far = (min (unpack h1)) | |
return near far | |
(near <= far) & (far >= 0.0) | |
- (stp * ((step h0.yzx h0) * (step h0.zxy h0))) | |
stp * ((step h1 h1.yzx) * (step h1 h1.zxy)) | |
fn iCubeFar (ro rd) | |
""""This is for situations where the entry point is already known and | |
we only need the exit point. | |
For ``ro + rd * t`` returns far ``t`` of the intersection with a | |
cube of unit size at origin. | |
let stp = (sign rd) | |
# avoid a situation where inf - inf = nan | |
let p = ((- ro) * stp) | |
let rdinv = (/ (abs rd)) | |
let h1 = ((p + 0.5) * rdinv) | |
let far = (min (unpack h1)) | |
return far | |
fn cast-ray (ro rd aperture) | |
let t0 t1 hit n0 n1 = | |
iCube ro rd | |
if (not hit) | |
return -1:u32 t0 0 -1:u32 | |
let t0 = | |
max 0.0 t0 | |
# move cube from -0.5 .. 0.5 to 0 .. 1 | |
let ro = (ro + 0.5) | |
let stp = (sign rd) | |
let rdinv = (/ (abs rd)) | |
local hit = -1:u32 | |
local t = t0 | |
local level = 0 | |
local code = 0:u32 | |
local steps = 0 | |
local hitcode = -1:u32 | |
local quit = false | |
loop (i = 0) | |
if ((i >= maxsteps) | ((deref quit) == true)) | |
break; | |
let distlevel = | |
(log2 (max 1.0 (aperture * (deref t)))) as i32 | |
let maxlevel = | |
LEVELS - (min LEVELS distlevel) | |
steps = i | |
let levelbit = (1:u32 << (voxel.level-bit ((deref level) as u32))) | |
let iscale = (1 << level) | |
let scale = (f32 iscale) | |
let key = | |
code | levelbit | |
if (test-cell key) | |
# crossing | |
if (level >= maxlevel) | |
# hit | |
hit = key | |
hitcode = code | |
quit = true | |
else | |
# descend | |
let pos = (ro + rd * (deref t)) | |
let c = ((unpack-morton3x10 code) * 2:u32 + 1:u32) | |
let p = (uvec3 (2.0 * scale * pos)) | |
let s = | |
? (p < c) | |
uvec3 0 | |
uvec3 1 | |
code = | |
voxel.leaf-key code | |
| s.x (s.y << 1:u32) (s.z << 2:u32) | |
level += 1 | |
else | |
# empty | |
if (level == 0) | |
# we are done | |
quit = true | |
elseif (test-cell (voxel.parent-key key)) | |
# parent is crossing, find neighboring cell and step forward | |
let cc = (ivec3 (unpack-morton3x10 code)) | |
let c = ((vec3 cc) + 0.5) | |
let t0 t1 hit n0 n1 = | |
iCube (ro * scale - c) (rd * scale) | |
let d = (ivec3 n1) | |
let cc = (cc + d) | |
t = t1 | |
code = | |
pack-morton3x10 (uvec3 cc) | |
if (code >= levelbit) | |
# we are done | |
quit = true | |
else | |
# parent is empty | |
level -= 1 | |
code = | |
voxel.parent-key code | |
i + 1 | |
return (deref hit) (deref t) (deref steps) (deref hitcode) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment