diff --git a/lib/common/src/bvh.rs b/lib/common/src/bvh.rs index fa12c32..a94b35f 100644 --- a/lib/common/src/bvh.rs +++ b/lib/common/src/bvh.rs @@ -59,33 +59,55 @@ impl<L> BvhNode<L>{ }, } } - fn populate_nodes<T:Ord>(&self,nodes:&mut BTreeMap<T,&BvhNode<L>>,ray:&Ray,start_time:T,time_limit:T,f:&F)->Option<TimedInstruction<&L,T>>{ + fn populate_nodes<T:Ord+Copy,F:Fn(&L,&Ray)->Option<T>>( + &self, + collector:&mut InstructionCollector<&L,T>, + nodes:&mut BTreeMap<T,&BvhNode<L>>, + ray:&Ray, + start_time:T, + f:&F, + ){ match &self.content{ - RecursiveContent::Leaf(leaf)=>Some(TimedInstruction{time:f(leaf),instruction:leaf}), - RecursiveContent::Branch(children)=>{ - let mut collector=InstructionCollector::new(time_limit); - for child in children{ - if child.aabb.contains(ray.origin){ - collector.collect(child.populate_nodes(nodes,ray,start_time,f)); - }else{ - // Am I an upcoming superstar? - if let Some(t)=child.aabb.intersect_ray(ray){ - if start_time<t{ - nodes.insert(t,child); - } + RecursiveContent::Leaf(leaf)=>collector.collect(f(leaf,ray).map(|time|TimedInstruction{time,instruction:leaf})), + RecursiveContent::Branch(children)=>for child in children{ + if child.aabb.contains(ray.origin){ + child.populate_nodes(collector,nodes,ray,start_time,f); + }else{ + // Am I an upcoming superstar? + if let Some(t)=child.aabb.intersect_ray(ray){ + if start_time<t&&t<collector.time(){ + nodes.insert(t,child); } } } - collector.take() }, } } - pub fn sample_ray<T:Ord,F:Fn(&L)->T>(&self,ray:&Ray,start_time:T,mut time_limit:Option<T>,f:&F)->Option<(T,&L)>{ + pub fn sample_ray<T:Ord+Copy,F:Fn(&L,&Ray)->Option<T>>(&self,ray:&Ray,start_time:T,time_limit:T,f:&F)->Option<(T,&L)>{ let mut nodes=BTreeMap::new(); + let mut collector=InstructionCollector::new(time_limit); // perform a normal sample aabb at point ray.origin - self.populate_nodes(&mut nodes,ray,start_time); + self.populate_nodes(&mut collector,&mut nodes,ray,start_time,f); // swim through nodes one at a time + while let Some((t,node))=nodes.pop_first(){ + if collector.time()<t{ + break; + } + match &node.content{ + RecursiveContent::Leaf(leaf)=>collector.collect(f(leaf,ray).map(|time|TimedInstruction{time,instruction:leaf})), + RecursiveContent::Branch(children)=>for child in children{ + // Am I an upcoming superstar? + if let Some(t)=child.aabb.intersect_ray(ray){ + if t<collector.time(){ + nodes.insert(t,child); + } + } + }, + } + } + + collector.take().map(|TimedInstruction{time,instruction:leaf}|(time,leaf)) } pub fn into_inner(self)->(RecursiveContent<BvhNode<L>,L>,Aabb){ (self.content,self.aabb)