Put hilbert and morton code into one module.
This commit is contained in:
parent
0df18ce908
commit
40d643b334
|
@ -1,77 +0,0 @@
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
const N: u32 = 1 << 16;
|
|
||||||
|
|
||||||
// Utility function used by the functions below.
|
|
||||||
fn hil_rot(n: u32, rx: u32, ry: u32, x: &mut u32, y: &mut u32) {
|
|
||||||
use std::mem;
|
|
||||||
if ry == 0 {
|
|
||||||
if rx == 1 {
|
|
||||||
*x = (n - 1).wrapping_sub(*x);
|
|
||||||
*y = (n - 1).wrapping_sub(*y);
|
|
||||||
}
|
|
||||||
mem::swap(x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert (x,y) to hilbert curve index.
|
|
||||||
///
|
|
||||||
/// x: The x coordinate. Must be a positive integer no greater than 2^16-1.
|
|
||||||
/// y: The y coordinate. Must be a positive integer no greater than 2^16-1.
|
|
||||||
///
|
|
||||||
/// Returns the hilbert curve index corresponding to the (x,y) coordinates given.
|
|
||||||
pub fn xy2i(x: u32, y: u32) -> u32 {
|
|
||||||
assert!(x < N);
|
|
||||||
assert!(y < N);
|
|
||||||
|
|
||||||
let (mut x, mut y) = (x, y);
|
|
||||||
let mut d = 0;
|
|
||||||
let mut s = N >> 1;
|
|
||||||
while s > 0 {
|
|
||||||
let rx = if (x & s) > 0 { 1 } else { 0 };
|
|
||||||
let ry = if (y & s) > 0 { 1 } else { 0 };
|
|
||||||
d += s * s * ((3 * rx) ^ ry);
|
|
||||||
hil_rot(s, rx, ry, &mut x, &mut y);
|
|
||||||
|
|
||||||
s >>= 1
|
|
||||||
}
|
|
||||||
|
|
||||||
d
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert hilbert curve index to (x,y).
|
|
||||||
///
|
|
||||||
/// d: The hilbert curve index.
|
|
||||||
///
|
|
||||||
/// Returns the (x, y) coords at the given index.
|
|
||||||
pub fn i2xy(d: u32) -> (u32, u32) {
|
|
||||||
let (mut x, mut y) = (0, 0);
|
|
||||||
let mut s = 1;
|
|
||||||
let mut t = d;
|
|
||||||
while s < N {
|
|
||||||
let rx = 1 & (t >> 1);
|
|
||||||
let ry = 1 & (t ^ rx);
|
|
||||||
hil_rot(s, rx, ry, &mut x, &mut y);
|
|
||||||
x += s * rx;
|
|
||||||
y += s * ry;
|
|
||||||
t >>= 2;
|
|
||||||
|
|
||||||
s <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn reversible() {
|
|
||||||
let d = 54;
|
|
||||||
let (x, y) = i2xy(d);
|
|
||||||
let d2 = xy2i(x, y);
|
|
||||||
|
|
||||||
assert_eq!(d, d2);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -23,13 +23,11 @@ mod camera;
|
||||||
mod color;
|
mod color;
|
||||||
mod fp_utils;
|
mod fp_utils;
|
||||||
mod hash;
|
mod hash;
|
||||||
mod hilbert;
|
|
||||||
mod image;
|
mod image;
|
||||||
mod lerp;
|
mod lerp;
|
||||||
mod light;
|
mod light;
|
||||||
mod math;
|
mod math;
|
||||||
mod mis;
|
mod mis;
|
||||||
mod morton;
|
|
||||||
mod parse;
|
mod parse;
|
||||||
mod ray;
|
mod ray;
|
||||||
mod renderer;
|
mod renderer;
|
||||||
|
@ -37,6 +35,7 @@ mod sampling;
|
||||||
mod scene;
|
mod scene;
|
||||||
mod scramble;
|
mod scramble;
|
||||||
mod shading;
|
mod shading;
|
||||||
|
mod space_fill;
|
||||||
mod surface;
|
mod surface;
|
||||||
mod timer;
|
mod timer;
|
||||||
mod tracer;
|
mod tracer;
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
#![allow(dead_code)]
|
|
||||||
|
|
||||||
const N: u32 = 1 << 16;
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn part_1_by_1(mut x: u32) -> u32 {
|
|
||||||
x &= 0x0000ffff;
|
|
||||||
x = (x ^ (x << 8)) & 0x00ff00ff;
|
|
||||||
x = (x ^ (x << 4)) & 0x0f0f0f0f;
|
|
||||||
x = (x ^ (x << 2)) & 0x33333333;
|
|
||||||
x = (x ^ (x << 1)) & 0x55555555;
|
|
||||||
x
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn part_1_by_2(mut x: u32) -> u32 {
|
|
||||||
x &= 0x000003ff;
|
|
||||||
x = (x ^ (x << 16)) & 0xff0000ff;
|
|
||||||
x = (x ^ (x << 8)) & 0x0300f00f;
|
|
||||||
x = (x ^ (x << 4)) & 0x030c30c3;
|
|
||||||
x = (x ^ (x << 2)) & 0x09249249;
|
|
||||||
x
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn compact_1_by_1(mut x: u32) -> u32 {
|
|
||||||
x &= 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
|
|
||||||
x = (x ^ (x >> 1)) & 0x33333333;
|
|
||||||
x = (x ^ (x >> 2)) & 0x0f0f0f0f;
|
|
||||||
x = (x ^ (x >> 4)) & 0x00ff00ff;
|
|
||||||
x = (x ^ (x >> 8)) & 0x0000ffff;
|
|
||||||
x
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn compact_1_by_2(mut x: u32) -> u32 {
|
|
||||||
x &= 0x09249249;
|
|
||||||
x = (x ^ (x >> 2)) & 0x030c30c3;
|
|
||||||
x = (x ^ (x >> 4)) & 0x0300f00f;
|
|
||||||
x = (x ^ (x >> 8)) & 0xff0000ff;
|
|
||||||
x = (x ^ (x >> 16)) & 0x000003ff;
|
|
||||||
x
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert (x,y) to morton curve index.
|
|
||||||
///
|
|
||||||
/// x: The x coordinate. Must be a positive integer no greater than 2^16-1.
|
|
||||||
/// y: The y coordinate. Must be a positive integer no greater than 2^16-1.
|
|
||||||
///
|
|
||||||
/// Returns the morton curve index corresponding to the (x,y) coordinates given.
|
|
||||||
pub fn xy2i(x: u32, y: u32) -> u32 {
|
|
||||||
debug_assert!(x < N);
|
|
||||||
debug_assert!(y < N);
|
|
||||||
|
|
||||||
part_1_by_1(x) | (part_1_by_1(y) << 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert morton curve index to (x,y).
|
|
||||||
///
|
|
||||||
/// i: The morton curve index.
|
|
||||||
///
|
|
||||||
/// Returns the (x, y) coords at the given index.
|
|
||||||
pub fn i2xy(i: u32) -> (u32, u32) {
|
|
||||||
(compact_1_by_1(i), compact_1_by_1(i >> 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: 3D morton curves.
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn reversible() {
|
|
||||||
let d = 54;
|
|
||||||
let (x, y) = i2xy(d);
|
|
||||||
let d2 = xy2i(x, y);
|
|
||||||
|
|
||||||
assert_eq!(d, d2);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -13,14 +13,13 @@ use crate::{
|
||||||
accel::ACCEL_NODE_RAY_TESTS,
|
accel::ACCEL_NODE_RAY_TESTS,
|
||||||
color::{map_0_1_to_wavelength, SpectralSample, XYZ},
|
color::{map_0_1_to_wavelength, SpectralSample, XYZ},
|
||||||
fp_utils::robust_ray_origin,
|
fp_utils::robust_ray_origin,
|
||||||
hilbert,
|
|
||||||
image::Image,
|
image::Image,
|
||||||
math::{probit, upper_power_of_two, Float4},
|
math::{probit, upper_power_of_two, Float4},
|
||||||
mis::power_heuristic,
|
mis::power_heuristic,
|
||||||
morton,
|
|
||||||
ray::{Ray, RayBatch},
|
ray::{Ray, RayBatch},
|
||||||
scene::{Scene, SceneLightSample},
|
scene::{Scene, SceneLightSample},
|
||||||
scramble::owen4,
|
scramble::owen4,
|
||||||
|
space_fill::{hilbert, morton},
|
||||||
surface,
|
surface,
|
||||||
timer::Timer,
|
timer::Timer,
|
||||||
tracer::Tracer,
|
tracer::Tracer,
|
||||||
|
@ -154,7 +153,7 @@ impl<'a> Renderer<'a> {
|
||||||
pow2 * pow2
|
pow2 * pow2
|
||||||
};
|
};
|
||||||
for hilbert_d in 0..bucket_n {
|
for hilbert_d in 0..bucket_n {
|
||||||
let (bx, by) = hilbert::i2xy(hilbert_d);
|
let (bx, by) = hilbert::decode(hilbert_d);
|
||||||
|
|
||||||
let x = bx as usize * bucket_w;
|
let x = bx as usize * bucket_w;
|
||||||
let y = by as usize * bucket_h;
|
let y = by as usize * bucket_h;
|
||||||
|
@ -249,7 +248,7 @@ impl<'a> Renderer<'a> {
|
||||||
// and golden ratio sampling, we do this up-front here rather than in
|
// and golden ratio sampling, we do this up-front here rather than in
|
||||||
// the samplers themselves.
|
// the samplers themselves.
|
||||||
let si_offset =
|
let si_offset =
|
||||||
owen4(morton::xy2i(x, y), self.seed).wrapping_mul(self.spp as u32);
|
owen4(morton::encode(x, y), self.seed).wrapping_mul(self.spp as u32);
|
||||||
for si in 0..self.spp {
|
for si in 0..self.spp {
|
||||||
let si = (si as u32).wrapping_add(si_offset);
|
let si = (si as u32).wrapping_add(si_offset);
|
||||||
|
|
||||||
|
|
144
src/space_fill.rs
Normal file
144
src/space_fill.rs
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
//! Space-filling curves and other related functionality.
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
pub mod hilbert {
|
||||||
|
const N: u32 = 1 << 16;
|
||||||
|
|
||||||
|
/// Convert (x,y) to hilbert curve index.
|
||||||
|
///
|
||||||
|
/// x: The x coordinate. Must be no greater than 2^16-1.
|
||||||
|
/// y: The y coordinate. Must be no greater than 2^16-1.
|
||||||
|
///
|
||||||
|
/// Returns the hilbert curve index corresponding to the (x,y) coordinates given.
|
||||||
|
pub fn encode(x: u32, y: u32) -> u32 {
|
||||||
|
assert!(x < N);
|
||||||
|
assert!(y < N);
|
||||||
|
|
||||||
|
let (mut x, mut y) = (x, y);
|
||||||
|
let mut d = 0;
|
||||||
|
let mut s = N >> 1;
|
||||||
|
while s > 0 {
|
||||||
|
let rx = if (x & s) > 0 { 1 } else { 0 };
|
||||||
|
let ry = if (y & s) > 0 { 1 } else { 0 };
|
||||||
|
d += s * s * ((3 * rx) ^ ry);
|
||||||
|
(x, y) = hilbert_rotate(s, rx, ry, x, y);
|
||||||
|
|
||||||
|
s >>= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
d
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert hilbert curve index to (x,y).
|
||||||
|
///
|
||||||
|
/// d: The hilbert curve index.
|
||||||
|
///
|
||||||
|
/// Returns the (x, y) coords at the given index.
|
||||||
|
pub fn decode(d: u32) -> (u32, u32) {
|
||||||
|
let (mut x, mut y) = (0, 0);
|
||||||
|
let mut s = 1;
|
||||||
|
let mut t = d;
|
||||||
|
while s < N {
|
||||||
|
let rx = 1 & (t >> 1);
|
||||||
|
let ry = 1 & (t ^ rx);
|
||||||
|
(x, y) = hilbert_rotate(s, rx, ry, x, y);
|
||||||
|
x += s * rx;
|
||||||
|
y += s * ry;
|
||||||
|
t >>= 2;
|
||||||
|
|
||||||
|
s <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------
|
||||||
|
// Utilities.
|
||||||
|
|
||||||
|
fn hilbert_rotate(n: u32, rx: u32, ry: u32, x: u32, y: u32) -> (u32, u32) {
|
||||||
|
if ry == 0 {
|
||||||
|
if rx == 1 {
|
||||||
|
((n - 1).wrapping_sub(y), (n - 1).wrapping_sub(x))
|
||||||
|
} else {
|
||||||
|
(y, x)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod morton {
|
||||||
|
const N: u32 = 1 << 16;
|
||||||
|
|
||||||
|
/// Convert (x,y) to morton curve index.
|
||||||
|
///
|
||||||
|
/// x: The x coordinate. Should be no greater than 2^16-1.
|
||||||
|
/// y: The y coordinate. Should be no greater than 2^16-1.
|
||||||
|
///
|
||||||
|
/// Returns the morton curve index corresponding to the (x,y) coordinates given.
|
||||||
|
pub fn encode(x: u32, y: u32) -> u32 {
|
||||||
|
debug_assert!(x < N);
|
||||||
|
debug_assert!(y < N);
|
||||||
|
|
||||||
|
part_1_by_1(x) | (part_1_by_1(y) << 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert morton curve index to (x,y).
|
||||||
|
///
|
||||||
|
/// i: The morton curve index.
|
||||||
|
///
|
||||||
|
/// Returns the (x, y) coords at the given index.
|
||||||
|
pub fn decode(i: u32) -> (u32, u32) {
|
||||||
|
(compact_1_by_1(i), compact_1_by_1(i >> 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------
|
||||||
|
// Utilities.
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn part_1_by_1(mut x: u32) -> u32 {
|
||||||
|
x &= 0x0000ffff;
|
||||||
|
x = (x ^ (x << 8)) & 0x00ff00ff;
|
||||||
|
x = (x ^ (x << 4)) & 0x0f0f0f0f;
|
||||||
|
x = (x ^ (x << 2)) & 0x33333333;
|
||||||
|
x = (x ^ (x << 1)) & 0x55555555;
|
||||||
|
x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn compact_1_by_1(mut x: u32) -> u32 {
|
||||||
|
x &= 0x55555555;
|
||||||
|
x = (x ^ (x >> 1)) & 0x33333333;
|
||||||
|
x = (x ^ (x >> 2)) & 0x0f0f0f0f;
|
||||||
|
x = (x ^ (x >> 4)) & 0x00ff00ff;
|
||||||
|
x = (x ^ (x >> 8)) & 0x0000ffff;
|
||||||
|
x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hilbert_reversible() {
|
||||||
|
let i = 0x4c8587a2;
|
||||||
|
let (x, y) = hilbert::decode(i);
|
||||||
|
let i2 = hilbert::encode(x, y);
|
||||||
|
|
||||||
|
assert_eq!(i, i2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn morton_reversible() {
|
||||||
|
let i = 0x4c8587a2;
|
||||||
|
let (x, y) = morton::decode(i);
|
||||||
|
let i2 = morton::encode(x, y);
|
||||||
|
|
||||||
|
assert_eq!(i, i2);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user