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 fp_utils;
|
||||
mod hash;
|
||||
mod hilbert;
|
||||
mod image;
|
||||
mod lerp;
|
||||
mod light;
|
||||
mod math;
|
||||
mod mis;
|
||||
mod morton;
|
||||
mod parse;
|
||||
mod ray;
|
||||
mod renderer;
|
||||
|
@ -37,6 +35,7 @@ mod sampling;
|
|||
mod scene;
|
||||
mod scramble;
|
||||
mod shading;
|
||||
mod space_fill;
|
||||
mod surface;
|
||||
mod timer;
|
||||
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,
|
||||
color::{map_0_1_to_wavelength, SpectralSample, XYZ},
|
||||
fp_utils::robust_ray_origin,
|
||||
hilbert,
|
||||
image::Image,
|
||||
math::{probit, upper_power_of_two, Float4},
|
||||
mis::power_heuristic,
|
||||
morton,
|
||||
ray::{Ray, RayBatch},
|
||||
scene::{Scene, SceneLightSample},
|
||||
scramble::owen4,
|
||||
space_fill::{hilbert, morton},
|
||||
surface,
|
||||
timer::Timer,
|
||||
tracer::Tracer,
|
||||
|
@ -154,7 +153,7 @@ impl<'a> Renderer<'a> {
|
|||
pow2 * pow2
|
||||
};
|
||||
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 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
|
||||
// the samplers themselves.
|
||||
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 {
|
||||
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