common: bvh: arbitrary traversal
This commit is contained in:
@@ -3,7 +3,7 @@ use std::collections::BTreeMap;
|
|||||||
|
|
||||||
use crate::aabb::Aabb;
|
use crate::aabb::Aabb;
|
||||||
use crate::ray::Ray;
|
use crate::ray::Ray;
|
||||||
use crate::integer::{Ratio,Planar64};
|
use crate::integer::{Ratio,Planar64,Planar64Vec3};
|
||||||
use crate::instruction::{InstructionCollector,TimedInstruction};
|
use crate::instruction::{InstructionCollector,TimedInstruction};
|
||||||
|
|
||||||
//da algaritum
|
//da algaritum
|
||||||
@@ -140,33 +140,34 @@ impl<L> BvhNode<L>{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn populate_nodes<'a,T,F>(
|
fn populate_nodes<'a,T,IntersectLeaf,IntersectAabb>(
|
||||||
&'a self,
|
&'a self,
|
||||||
collector:&mut InstructionCollector<&'a L,Ratio<Planar64,Planar64>>,
|
start_point:Planar64Vec3,
|
||||||
nodes:&mut BTreeMap<Ratio<Planar64,Planar64>,&'a BvhNode<L>>,
|
collector:&mut InstructionCollector<&'a L,T>,
|
||||||
ray:&Ray,
|
nodes:&mut BTreeMap<T,&'a BvhNode<L>>,
|
||||||
start_time:Ratio<Planar64,Planar64>,
|
start_time:T,
|
||||||
f:&F,
|
intersect_leaf:&IntersectLeaf,
|
||||||
|
intersect_aabb:&IntersectAabb,
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
T:Ord+Copy,
|
T:Ord+Copy,
|
||||||
Ratio<Planar64,Planar64>:From<T>,
|
IntersectLeaf:Fn(&L)->Option<T>,
|
||||||
F:Fn(&L,&Ray)->Option<T>,
|
IntersectAabb:Fn(&Aabb)->Option<T>,
|
||||||
{
|
{
|
||||||
match &self.content{
|
match &self.content{
|
||||||
RecursiveContent::Leaf(leaf)=>if let Some(time)=f(leaf,ray){
|
RecursiveContent::Leaf(leaf)=>if let Some(time)=intersect_leaf(leaf){
|
||||||
let ins=TimedInstruction{time:time.into(),instruction:leaf};
|
let ins=TimedInstruction{time,instruction:leaf};
|
||||||
if start_time.lt_ratio(ins.time)&&ins.time.lt_ratio(collector.time()){
|
if start_time<ins.time&&ins.time<collector.time(){
|
||||||
collector.collect(Some(ins));
|
collector.collect(Some(ins));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
RecursiveContent::Branch(children)=>for child in children{
|
RecursiveContent::Branch(children)=>for child in children{
|
||||||
if child.aabb.contains(ray.origin){
|
if child.aabb.contains(start_point){
|
||||||
child.populate_nodes(collector,nodes,ray,start_time,f);
|
child.populate_nodes(start_point,collector,nodes,start_time,intersect_leaf,intersect_aabb);
|
||||||
}else{
|
}else{
|
||||||
// Am I an upcoming superstar?
|
// Am I an upcoming superstar?
|
||||||
if let Some(t)=intersect_aabb(ray,&child.aabb){
|
if let Some(t)=intersect_aabb(&child.aabb){
|
||||||
if start_time.lt_ratio(t)&&t.lt_ratio(collector.time()){
|
if start_time<t&&t<collector.time(){
|
||||||
nodes.insert(t,child);
|
nodes.insert(t,child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,27 +175,29 @@ impl<L> BvhNode<L>{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn sample_ray<T,F>(
|
/// Traverse the BVH using the given sampling functions.
|
||||||
|
/// Nodes are tested in order of T returned by IntersectAabb.
|
||||||
|
/// The algorithm ends when T for the next node to test is
|
||||||
|
/// greater than the current best collected T from IntersectLeaf.
|
||||||
|
pub fn traverse<T,IntersectLeaf,IntersectAabb>(
|
||||||
&self,
|
&self,
|
||||||
ray:&Ray,
|
start_point:Planar64Vec3,
|
||||||
start_time:T,
|
start_time:T,
|
||||||
time_limit:T,
|
time_limit:T,
|
||||||
f:F,
|
intersect_leaf:IntersectLeaf,
|
||||||
|
intersect_aabb:IntersectAabb,
|
||||||
)->Option<(T,&L)>
|
)->Option<(T,&L)>
|
||||||
where
|
where
|
||||||
T:Ord+Copy,
|
T:Ord+Copy,
|
||||||
T:From<Ratio<Planar64,Planar64>>,
|
IntersectLeaf:Fn(&L)->Option<T>,
|
||||||
Ratio<Planar64,Planar64>:From<T>,
|
IntersectAabb:Fn(&Aabb)->Option<T>,
|
||||||
F:Fn(&L,&Ray)->Option<T>,
|
|
||||||
{
|
{
|
||||||
// source of nondeterminism when Aabb boundaries are coplanar
|
// source of nondeterminism when Aabb boundaries are coplanar
|
||||||
let mut nodes=BTreeMap::new();
|
let mut nodes=BTreeMap::new();
|
||||||
|
|
||||||
let start_time=start_time.into();
|
|
||||||
let time_limit=time_limit.into();
|
|
||||||
let mut collector=InstructionCollector::new(time_limit);
|
let mut collector=InstructionCollector::new(time_limit);
|
||||||
// break open all nodes that contain ray.origin and populate nodes with future intersection times
|
// break open all nodes that contain ray.origin and populate nodes with future intersection times
|
||||||
self.populate_nodes(&mut collector,&mut nodes,ray,start_time,&f);
|
self.populate_nodes(start_point,&mut collector,&mut nodes,start_time,&intersect_leaf,&intersect_aabb);
|
||||||
|
|
||||||
// swim through nodes one at a time
|
// swim through nodes one at a time
|
||||||
while let Some((t,node))=nodes.pop_first(){
|
while let Some((t,node))=nodes.pop_first(){
|
||||||
@@ -202,18 +205,18 @@ impl<L> BvhNode<L>{
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
match &node.content{
|
match &node.content{
|
||||||
RecursiveContent::Leaf(leaf)=>if let Some(time)=f(leaf,ray){
|
RecursiveContent::Leaf(leaf)=>if let Some(time)=intersect_leaf(leaf){
|
||||||
let ins=TimedInstruction{time:time.into(),instruction:leaf};
|
let ins=TimedInstruction{time:time.into(),instruction:leaf};
|
||||||
// this lower bound can also be omitted
|
// this lower bound can also be omitted
|
||||||
// but it causes type inference errors lol
|
// but it causes type inference errors lol
|
||||||
if start_time.lt_ratio(ins.time)&&ins.time.lt_ratio(collector.time()){
|
if start_time<ins.time&&ins.time<collector.time(){
|
||||||
collector.collect(Some(ins));
|
collector.collect(Some(ins));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// break open the node and predict collisions with the child nodes
|
// break open the node and predict collisions with the child nodes
|
||||||
RecursiveContent::Branch(children)=>for child in children{
|
RecursiveContent::Branch(children)=>for child in children{
|
||||||
// Am I an upcoming superstar?
|
// Am I an upcoming superstar?
|
||||||
if let Some(t)=intersect_aabb(ray,&child.aabb){
|
if let Some(t)=intersect_aabb(&child.aabb){
|
||||||
// we don't need to check the lower bound
|
// we don't need to check the lower bound
|
||||||
// because child aabbs are guaranteed to be within the parent bounds.
|
// because child aabbs are guaranteed to be within the parent bounds.
|
||||||
if t<collector.time(){
|
if t<collector.time(){
|
||||||
|
|||||||
Reference in New Issue
Block a user