Render buckets in hilbert curve order.
Provides a slight speed-up.
This commit is contained in:
parent
5bc97f69b8
commit
ec75f11206
87
src/hilbert.rs
Normal file
87
src/hilbert.rs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
#![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) {
|
||||||
|
if ry == 0 {
|
||||||
|
if rx == 1 {
|
||||||
|
*x = (n - 1).wrapping_sub(*x);
|
||||||
|
*y = (n - 1).wrapping_sub(*y);
|
||||||
|
}
|
||||||
|
let t = *x;
|
||||||
|
*x = *y;
|
||||||
|
*y = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 xy2d(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 d2xy(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) = d2xy(d);
|
||||||
|
let d2 = xy2d(x, y);
|
||||||
|
|
||||||
|
assert_eq!(d, d2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ extern crate lodepng;
|
||||||
extern crate nom;
|
extern crate nom;
|
||||||
|
|
||||||
mod math;
|
mod math;
|
||||||
|
mod hilbert;
|
||||||
mod algorithm;
|
mod algorithm;
|
||||||
mod lerp;
|
mod lerp;
|
||||||
mod float4;
|
mod float4;
|
||||||
|
|
|
@ -39,7 +39,18 @@ pub fn fast_ln(x: f32) -> f32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Rounds an integer up to the next power of two.
|
||||||
|
pub fn upper_power_of_two(mut v: u32) -> u32 {
|
||||||
|
v -= 1;
|
||||||
|
v |= v >> 1;
|
||||||
|
v |= v >> 2;
|
||||||
|
v |= v >> 4;
|
||||||
|
v |= v >> 8;
|
||||||
|
v |= v >> 16;
|
||||||
|
v + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the log base 2 of the given integer
|
||||||
pub fn log2_64(value: u64) -> u64 {
|
pub fn log2_64(value: u64) -> u64 {
|
||||||
const TAB64: [u64; 64] = [63, 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61, 51,
|
const TAB64: [u64; 64] = [63, 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61, 51,
|
||||||
37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62, 57, 46,
|
37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62, 57, 46,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::cmp;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
@ -10,7 +11,8 @@ use algorithm::partition_pair;
|
||||||
use ray::Ray;
|
use ray::Ray;
|
||||||
use tracer::Tracer;
|
use tracer::Tracer;
|
||||||
use halton;
|
use halton;
|
||||||
use math::fast_logit;
|
use hilbert;
|
||||||
|
use math::{fast_logit, upper_power_of_two};
|
||||||
use image::Image;
|
use image::Image;
|
||||||
use surface;
|
use surface;
|
||||||
use scene::Scene;
|
use scene::Scene;
|
||||||
|
@ -184,20 +186,27 @@ impl Renderer {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Populate job queue
|
// Populate job queue
|
||||||
for by in 0..((img_height / bucket_h) + 1) {
|
let bucket_n = {
|
||||||
for bx in 0..((img_width / bucket_w) + 1) {
|
let bucket_count_x = ((img_width / bucket_w) + 1) as u32;
|
||||||
let x = bx * bucket_w;
|
let bucket_count_y = ((img_height / bucket_h) + 1) as u32;
|
||||||
let y = by * bucket_h;
|
let larger = cmp::max(bucket_count_x, bucket_count_y);
|
||||||
let w = min(bucket_w, img_width - x);
|
let pow2 = upper_power_of_two(larger);
|
||||||
let h = min(bucket_h, img_height - y);
|
pow2 * pow2
|
||||||
if w > 0 && h > 0 {
|
};
|
||||||
job_queue.push(BucketJob {
|
for hilbert_d in 0..bucket_n {
|
||||||
x: x as u32,
|
let (bx, by) = hilbert::d2xy(hilbert_d);
|
||||||
y: y as u32,
|
|
||||||
w: w as u32,
|
let x = bx as usize * bucket_w;
|
||||||
h: h as u32,
|
let y = by as usize * bucket_h;
|
||||||
});
|
let w = min(bucket_w, img_width - x);
|
||||||
}
|
let h = min(bucket_h, img_height - y);
|
||||||
|
if x < img_width && y < img_height && w > 0 && h > 0 {
|
||||||
|
job_queue.push(BucketJob {
|
||||||
|
x: x as u32,
|
||||||
|
y: y as u32,
|
||||||
|
w: w as u32,
|
||||||
|
h: h as u32,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user