Skip to content

Instantly share code, notes, and snippets.

@paniq
Last active April 22, 2020 17:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paniq/dce0d588fae29b6e56953d3026106195 to your computer and use it in GitHub Desktop.
Save paniq/dce0d588fae29b6e56953d3026106195 to your computer and use it in GitHub Desktop.
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