@@ -4,6 +4,8 @@ pub use camera::{Camera, CameraController, GpuCamera};
44mod material;
55pub use material:: { GpuMaterial , Material , Texture } ;
66
7+ mod aabb;
8+
79#[ derive( Clone , Debug ) ]
810pub struct Scene {
911 pub materials : Vec < Material > ,
@@ -132,6 +134,90 @@ impl Scene {
132134 camera_controller,
133135 }
134136 }
137+
138+ pub fn get_bvh ( & self ) -> Vec < aabb:: AABB > {
139+ let mut bvh = Vec :: new ( ) ;
140+
141+ let axis = rand:: random :: < u32 > ( ) % 3 ;
142+ let mut spheres = self . spheres . clone ( ) ;
143+
144+ spheres. sort_by ( |a, b| {
145+ let a = a. get_bounding_box ( ) ;
146+ let b = b. get_bounding_box ( ) ;
147+
148+ a. min [ axis as usize ]
149+ . partial_cmp ( & b. min [ axis as usize ] )
150+ . unwrap ( )
151+ } ) ;
152+
153+ let mut stack = Vec :: new ( ) ;
154+ stack. push ( ( 0 , spheres. len ( ) , 0 ) ) ;
155+
156+ while let Some ( ( start, end, _) ) = stack. pop ( ) {
157+ let mut min = glm:: vec3 ( std:: f32:: INFINITY , std:: f32:: INFINITY , std:: f32:: INFINITY ) ;
158+ let mut max = glm:: vec3 (
159+ std:: f32:: NEG_INFINITY ,
160+ std:: f32:: NEG_INFINITY ,
161+ std:: f32:: NEG_INFINITY ,
162+ ) ;
163+
164+ for i in start..end {
165+ let sphere = & spheres[ i] ;
166+ let aabb = sphere. get_bounding_box ( ) ;
167+
168+ min = glm:: vec3 (
169+ min. x . min ( aabb. min . x ) ,
170+ min. y . min ( aabb. min . y ) ,
171+ min. z . min ( aabb. min . z ) ,
172+ ) ;
173+
174+ max = glm:: vec3 (
175+ max. x . max ( aabb. max . x ) ,
176+ max. y . max ( aabb. max . y ) ,
177+ max. z . max ( aabb. max . z ) ,
178+ ) ;
179+ }
180+
181+ let mid = ( start + end) / 2 ;
182+
183+ let left_child = if mid - start == 1 {
184+ start as u32
185+ } else {
186+ bvh. len ( ) as u32 + 1
187+ } ;
188+
189+ let right_child = if end - mid == 1 {
190+ mid as u32
191+ } else {
192+ bvh. len ( ) as u32 + 2
193+ } ;
194+
195+ bvh. push ( aabb:: AABB {
196+ min,
197+ max,
198+ left_child,
199+ right_child,
200+ } ) ;
201+
202+ if mid - start > 1 {
203+ stack. push ( ( start, mid, bvh. len ( ) as u32 - 1 ) ) ;
204+ }
205+
206+ if end - mid > 1 {
207+ stack. push ( ( mid, end, bvh. len ( ) as u32 - 1 ) ) ;
208+ }
209+ }
210+
211+ // DEBUG: traverse bvh and print a tree
212+ for ( i, aabb) in bvh. iter ( ) . enumerate ( ) {
213+ println ! (
214+ "Node: {} min: {:?} max: {:?} left: {} right: {}" ,
215+ i, aabb. min, aabb. max, aabb. left_child, aabb. right_child
216+ ) ;
217+ }
218+
219+ bvh
220+ }
135221}
136222
137223#[ repr( C ) ]
@@ -191,4 +277,15 @@ impl Sphere {
191277 _padding : [ 0 ; 2 ] ,
192278 }
193279 }
280+ pub fn get_bounding_box ( & self ) -> aabb:: AABB {
281+ let radius = glm:: vec3 ( self . radius , self . radius , self . radius ) ;
282+ let center = self . center . xyz ( ) ;
283+
284+ aabb:: AABB {
285+ min : center - radius,
286+ max : center + radius,
287+ left_child : 0 ,
288+ right_child : 0 ,
289+ }
290+ }
194291}
0 commit comments