Use quick select for balanced BVH building.
This gets rid of a crate dependency, and also is faster.
This commit is contained in:
parent
024ca560af
commit
fbeadfce29
56
Cargo.lock
generated
56
Cargo.lock
generated
|
@ -7,7 +7,6 @@ dependencies = [
|
|||
"lodepng 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quickersort 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -79,11 +78,6 @@ name = "nom"
|
|||
version = "1.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.0.0"
|
||||
|
@ -92,15 +86,6 @@ dependencies = [
|
|||
"libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quickersort"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.1.73"
|
||||
|
@ -170,24 +155,11 @@ dependencies = [
|
|||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unreachable"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
|
@ -198,3 +170,31 @@ name = "winapi-build"
|
|||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum aho-corasick 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2b3fb52b09c1710b961acb35390d514be82e4ac96a9969a8e38565a29b878dc9"
|
||||
"checksum c_vec 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "aa9e1d9f7d49e289f36f19effbf3d5a5e30163ecf9c7a3c9be94d5374dec5b9a"
|
||||
"checksum crossbeam 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "fb974f835e90390c5f9dfac00f05b06dc117299f5ea4e85fbc7bb443af4911cc"
|
||||
"checksum docopt 0.6.81 (registry+https://github.com/rust-lang/crates.io-index)" = "323b5c50646d8d3f26c826eb62c15659b2bc031831d56bcdb02e0e49c5b73829"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum libc 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "39dfaaa0f4da0f1a06876c5d94329d739ad0150868069cc235f1ddf80a0480e7"
|
||||
"checksum lodepng 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2949340106c6ddacb872a8bceb940e39e332739873d56c1315917778527f8779"
|
||||
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
|
||||
"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
|
||||
"checksum num-traits 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "95e58eac34596aac30ab134c8a8da9aa2dc99caa4b4b4838e6fc6e298016278f"
|
||||
"checksum num_cpus 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a859041cbf7a70ea1ece4b87d1a2c6ef364dcb68749c88db1f97304b9ec09d5f"
|
||||
"checksum quickersort 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5950b7cb98904f6f7856bdff5b0987821f8a4ec4a67f4be892ddc8ed244ce89d"
|
||||
"checksum regex 0.1.73 (registry+https://github.com/rust-lang/crates.io-index)" = "56b7ee9f764ecf412c6e2fff779bca4b22980517ae335a21aeaf4e32625a5df2"
|
||||
"checksum regex-syntax 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "31040aad7470ad9d8c46302dcffba337bb4289ca5da2e3cd6e37b64109a85199"
|
||||
"checksum rgb 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b5b3c2c5af3cafb6dad34a02c7a5b8818f71992663f5a8b1e1d1e27c5e782dd"
|
||||
"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b"
|
||||
"checksum scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef399c8893e8cb7aa9696e895427fab3a6bf265977bb96e126f24ddd2cda85a"
|
||||
"checksum simd 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63b5847c2d766ca7ce7227672850955802fabd779ba616aeabead4c2c3877023"
|
||||
"checksum strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e4d73a2c36a4d095ed1a6df5cbeac159863173447f7a82b3f4757426844ab825"
|
||||
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
|
||||
"checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d"
|
||||
"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
|
||||
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
|
||||
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
|
|
@ -17,7 +17,6 @@ nom = "1.2"
|
|||
scoped_threadpool = "0.1"
|
||||
crossbeam = "0.2"
|
||||
num_cpus = "1.0"
|
||||
quickersort = "2.0"
|
||||
lodepng = "0.8"
|
||||
|
||||
simd = { version = "0.1.1", optional = true }
|
||||
simd = { version = "0.1.1", optional = true }
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std;
|
||||
use std::cmp;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use lerp::{Lerp, lerp_slice};
|
||||
|
||||
/// Partitions a slice in-place with the given unary predicate, returning
|
||||
|
@ -113,6 +113,35 @@ pub fn partition_pair<A, B, F>(slc1: &mut [A], slc2: &mut [B], mut pred: F) -> u
|
|||
}
|
||||
}
|
||||
|
||||
/// Partitions the slice of items to place the nth-ordered item in the nth place,
|
||||
/// and the items less than it before and the items more than it after.
|
||||
pub fn quick_select<T, F>(slc: &mut [T], n: usize, mut order: F)
|
||||
where F: FnMut(&T, &T) -> Ordering
|
||||
{
|
||||
let mut left = 0;
|
||||
let mut right = slc.len();
|
||||
|
||||
loop {
|
||||
let i = (left + right) / 2;
|
||||
|
||||
slc.swap(i, right - 1);
|
||||
let ii = left +
|
||||
{
|
||||
let (val, list) = (&mut slc[left..right]).split_last_mut().unwrap();
|
||||
partition(list, |n| order(n, val) == Ordering::Less)
|
||||
};
|
||||
slc.swap(ii, right - 1);
|
||||
|
||||
if ii == n {
|
||||
return;
|
||||
} else if ii > n {
|
||||
right = ii;
|
||||
} else {
|
||||
left = ii + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Merges two slices of things, appending the result to vec_out
|
||||
pub fn merge_slices_append<T: Lerp + Copy, F>(slice1: &[T],
|
||||
slice2: &[T],
|
||||
|
@ -174,3 +203,42 @@ pub fn merge_slices_to<T: Lerp + Copy, F>(slice1: &[T],
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::cmp::Ordering;
|
||||
use super::*;
|
||||
|
||||
fn quick_select_ints(list: &mut [i32], i: usize) {
|
||||
quick_select(list, i, |a, b| {
|
||||
if a < b {
|
||||
Ordering::Less
|
||||
} else if a == b {
|
||||
Ordering::Equal
|
||||
} else {
|
||||
Ordering::Greater
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn quick_select_1() {
|
||||
let mut list = [8, 9, 7, 4, 6, 1, 0, 5, 3, 2];
|
||||
quick_select_ints(&mut list, 5);
|
||||
assert_eq!(list[5], 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn quick_select_2() {
|
||||
let mut list = [8, 9, 7, 4, 6, 1, 0, 5, 3, 2];
|
||||
quick_select_ints(&mut list, 3);
|
||||
assert_eq!(list[3], 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn quick_select_3() {
|
||||
let mut list = [8, 9, 7, 4, 6, 1, 0, 5, 3, 2];
|
||||
quick_select_ints(&mut list, 0);
|
||||
assert_eq!(list[0], 0);
|
||||
}
|
||||
}
|
||||
|
|
18
src/bvh.rs
18
src/bvh.rs
|
@ -2,12 +2,11 @@
|
|||
|
||||
use std;
|
||||
use std::cmp::Ordering;
|
||||
use quickersort::sort_by;
|
||||
use lerp::lerp_slice;
|
||||
use bbox::BBox;
|
||||
use boundable::Boundable;
|
||||
use ray::AccelRay;
|
||||
use algorithm::{partition, merge_slices_append};
|
||||
use algorithm::{partition, quick_select, merge_slices_append};
|
||||
use math::log2_64;
|
||||
use sah::sah_split;
|
||||
|
||||
|
@ -156,10 +155,15 @@ impl BVH {
|
|||
axis
|
||||
};
|
||||
|
||||
// TODO: use a select algorithm like introselect instead of a
|
||||
// full sort.
|
||||
sort_by(objects,
|
||||
&|a, b| {
|
||||
let place = {
|
||||
let place = objects.len() / 2;
|
||||
if place > 0 {
|
||||
place
|
||||
} else {
|
||||
1
|
||||
}
|
||||
};
|
||||
quick_select(objects, place, |a, b| {
|
||||
let tb_a = lerp_slice(bounder(a), 0.5);
|
||||
let tb_b = lerp_slice(bounder(b), 0.5);
|
||||
let centroid_a = (tb_a.min.get_n(split_axis) + tb_a.max.get_n(split_axis)) *
|
||||
|
@ -176,7 +180,7 @@ impl BVH {
|
|||
}
|
||||
});
|
||||
|
||||
(objects.len() / 2, split_axis)
|
||||
(place, split_axis)
|
||||
};
|
||||
|
||||
// Create child nodes
|
||||
|
|
|
@ -4,7 +4,6 @@ extern crate docopt;
|
|||
extern crate scoped_threadpool;
|
||||
extern crate crossbeam;
|
||||
extern crate num_cpus;
|
||||
extern crate quickersort;
|
||||
extern crate lodepng;
|
||||
|
||||
#[cfg(feature = "simd_perf")]
|
||||
|
|
Loading…
Reference in New Issue
Block a user