fn trace_ray(
        &self,
        scene: &Scene,
        ray: &Ray,
        current_depth: usize,
        current_value: Spectrum,
        denom_samples: usize,
        contribution: &mut ColourMatrix,
        rng: &mut RandGen,
    ) {
        // Limit bounces
        if current_depth > self.max_depth {
            return;
        }

        // let one_over_samples = 1./ self.n_ambient_samples as Float;
        // If hits an object
        if let Some(interaction) = scene.cast_ray(ray) {
            if let Interaction::Surface(data) = &interaction {
                let object = &scene.objects[data.prim_index];
                // get the normal... can be textured.

                let normal = data.geometry_shading.normal; //.get_normalized();
                let e1 = data.geometry_shading.dpdu.get_normalized();
                let e2 = normal.cross(e1);
                debug_assert!((1.0 - normal.length()).abs() < 0.000001);
                debug_assert!((1.0 - e1.length()).abs() < 0.000001);
                debug_assert!((1.0 - e2.length()).abs() < 0.000001);

                let material = match data.geometry_shading.side {
                    SurfaceSide::Front => &scene.materials[object.front_material_index],
                    SurfaceSide::Back => &scene.materials[object.back_material_index],
                    SurfaceSide::NonApplicable => {
                        return;
                    }
                };

                // let intersection_pt = ray.geometry.project(t);
                let intersection_pt = data.point;
                // let ray_dir = ray.geometry.direction;

                // for now, emmiting materials don't reflect
                if !material.emits_direct_light() {
                    // Run each spawned ray

                    /* Adapted From Radiance's samp_hemi() at src/rt/ambcomp.c */
                    let mut intens = current_value.red;
                    if current_value.green > intens {
                        intens = current_value.green;
                    }
                    if current_value.blue > intens {
                        intens = current_value.blue;
                    }
                    let mut wt = intens;

                    let d = intens * intens * 0.8 /* *one_over_samples*/ / self.limit_weight / denom_samples as Float;
                    if wt > d {
                        wt = d;
                    }
                    let mut n = ((denom_samples as Float * wt).sqrt() + 0.5).round() as usize;
                    if n < 1 {
                        n = 1;
                    }
                    /* End of Adapted Radiance's code*/

                    (0..n).for_each(|_| {
                    
                
                        let (new_ray, _bsdf_value, _is_specular) = material.sample_bsdf(normal, e1, e2, intersection_pt, *ray, rng);                            
                        
                        let new_ray_dir = new_ray.geometry.direction;
                        debug_assert!((1. as Float-new_ray_dir.length()).abs() < 1e-5, "Length is {}", new_ray_dir.length());

                        let cos_theta = (normal * new_ray_dir).abs();
                        let refl = material.colour();

                        // current_value * refl * cos_theta * bsdf_value / pdf == bsdf_value
                        let new_value = current_value * refl * cos_theta  /* * bsdf_value   * one_over_samples * 1.5*/ ;

                        // Check reflection limits... as described in RTRACE's man
                        // if  self.limit_reflections > 0 && new_value < self.limit_weight {
                        //     return;
                        // } 
                        intens = new_value.red;
                        if new_value.green > intens {
                            intens = new_value.green;
                        }
                        if new_value.blue > intens {
                            intens = new_value.blue;
                        }
                        if self.limit_weight > 0. && intens < self.limit_weight {
                            // russian roulette
                            let q : Float = rng.gen();
                            if q > intens/self.limit_weight {
                                return;
                            }
                        }
                        self.trace_ray(scene, &new_ray, current_depth + 1, new_value * 1.5, denom_samples * n, contribution, rng);
                    }); // End the foreach spawned ray
                }
            } else {
                panic!("Found light-emmiting material when calculating Daylight Coefficients");
            }
        } else {
            let bin_n = self.reinhart.dir_to_bin(ray.geometry.direction);

            let li = Spectrum::gray(3.);
            let old_value = contribution.get(0, bin_n).unwrap();

            contribution
                .set(
                    0,
                    bin_n,
                    old_value + li * current_value / denom_samples as Float,
                )
                .unwrap();
        }
    }
/// Recursively traces a ray until it excedes the `max_depth` of the
/// `DCFactory` or the ray does not hit anything (i.e., it reaches either
/// the sky or the ground)
Recursively traces a ray until it excedes the `max_depth` of the
`DCFactory` or the ray does not hit anything
Recursively traces a ray until it excedes the ` max_depth ` of the ` DCFactory ` or the ray does not hit anything
fn trace_ray(
        &self,
        scene: &Scene,
        ray: &Ray,
        current_depth: usize,
        current_value: Spectrum,
        denom_samples: usize,
        contribution: &mut ColourMatrix,
        rng: &mut RandGen,
    ) {
        // Limit bounces
        if current_depth > self.max_depth {
            return;
        }
        // let one_over_samples = 1./ self.n_ambient_samples as Float;
        // If hits an object
        if let Some(interaction) = scene.cast_ray(ray) {
            if let Interaction::Surface(data) = &interaction {
                let object = &scene.objects[data.prim_index];
                // get the normal... can be textured.
                let normal = data.geometry_shading.normal; //.get_normalized();
                let e1 = data.geometry_shading.dpdu.get_normalized();
                let e2 = normal.cross(e1);
                debug_assert!((1.0 - normal.length()).abs() < 0.000001);
                debug_assert!((1.0 - e1.length()).abs() < 0.000001);
                debug_assert!((1.0 - e2.length()).abs() < 0.000001);
                let material = match data.geometry_shading.side {
                    SurfaceSide::Front => &scene.materials[object.front_material_index],
                    SurfaceSide::Back => &scene.materials[object.back_material_index],
                    SurfaceSide::NonApplicable => {
                        return;
                    }
                };
                // let intersection_pt = ray.geometry.project(t);
                let intersection_pt = data.point;
                // let ray_dir = ray.geometry.direction;
                // for now, emmiting materials don't reflect
                if !material.emits_direct_light() {
                    // Run each spawned ray
                    /* Adapted From Radiance's samp_hemi() at src/rt/ambcomp.c */
                    let mut intens = current_value.red;
                    if current_value.green > intens {
                        intens = current_value.green;
                    }
                    if current_value.blue > intens {
                        intens = current_value.blue;
                    }
                    let mut wt = intens;
                    let d = intens * intens * 0.8 /* *one_over_samples*/ / self.limit_weight / denom_samples as Float;
                    if wt > d {
                        wt = d;
                    }
                    let mut n = ((denom_samples as Float * wt).sqrt() + 0.5).round() as usize;
                    if n < 1 {
                        n = 1;
                    }
                    /* End of Adapted Radiance's code*/
                    (0..n).for_each(|_| {
                        let (new_ray, _bsdf_value, _is_specular) = material.sample_bsdf(normal, e1, e2, intersection_pt, *ray, rng);                            
                        let new_ray_dir = new_ray.geometry.direction;
                        debug_assert!((1. as Float-new_ray_dir.length()).abs() < 1e-5, "Length is {}", new_ray_dir.length());
                        let cos_theta = (normal * new_ray_dir).abs();
                        let refl = material.colour();
                        // current_value * refl * cos_theta * bsdf_value / pdf == bsdf_value
                        let new_value = current_value * refl * cos_theta  /* * bsdf_value   * one_over_samples * 1.5*/ ;
                        // Check reflection limits... as described in RTRACE's man
                        // if  self.limit_reflections > 0 && new_value < self.limit_weight {
                        //     return;
                        // } 
                        intens = new_value.red;
                        if new_value.green > intens {
                            intens = new_value.green;
                        }
                        if new_value.blue > intens {
                            intens = new_value.blue;
                        }
                        if self.limit_weight > 0. && intens < self.limit_weight {
                            // russian roulette
                            let q : Float = rng.gen();
                            if q > intens/self.limit_weight {
                                return;
                            }
                        }
                        self.trace_ray(scene, &new_ray, current_depth + 1, new_value * 1.5, denom_samples * n, contribution, rng);
                    }); // End the foreach spawned ray
                }
            } else {
                panic!("Found light-emmiting material when calculating Daylight Coefficients");
            }
        } else {
            let bin_n = self.reinhart.dir_to_bin(ray.geometry.direction);
            let li = Spectrum::gray(3.);
            let old_value = contribution.get(0, bin_n).unwrap();
            contribution
                .set(
                    0,
                    bin_n,
                    old_value + li * current_value / denom_samples as Float,
                )
                .unwrap();
        }
    }
fn trace_ray ( & self , scene : & Scene , ray : & Ray , current_depth : usize , current_value : Spectrum , denom_samples : usize , contribution : & mut ColourMatrix , rng : & mut RandGen , ) { // Limit bounces if current_depth > self . max_depth { return ; } // let one_over_samples = 1./ self.n_ambient_samples as Float; // If hits an object if let Some ( interaction ) = scene . cast_ray ( ray ) { if let Interaction :: Surface ( data ) = & interaction { let object = & scene . objects [ data . prim_index ] ; // get the normal... can be textured. let normal = data . geometry_shading . normal ; //.get_normalized(); let e1 = data . geometry_shading . dpdu . get_normalized ( ) ; let e2 = normal . cross ( e1 ) ; debug_assert ! ( ( 1.0 normal length ( ) ) abs ( ) 0.000001 ) ; debug_assert ! ( ( 1.0 e1 length ( ) ) abs ( ) 0.000001 ) ; debug_assert ! ( ( 1.0 e2 length ( ) ) abs ( ) 0.000001 ) ; let material = match data . geometry_shading . side { SurfaceSide :: Front => & scene . materials [ object . front_material_index ] , SurfaceSide :: Back => & scene . materials [ object . back_material_index ] , SurfaceSide :: NonApplicable => { return ; } } ; // let intersection_pt = ray.geometry.project(t); let intersection_pt = data . point ; // let ray_dir = ray.geometry.direction; // for now, emmiting materials don't reflect if ! material . emits_direct_light ( ) { // Run each spawned ray /* Adapted From Radiance's samp_hemi() at src/rt/ambcomp.c */ let mut intens = current_value . red ; if current_value . green > intens { intens = current_value . green ; } if current_value . blue > intens { intens = current_value . blue ; } let mut wt = intens ; let d = intens * intens * 0.8 /* *one_over_samples*/ / self . limit_weight / denom_samples as Float ; if wt > d { wt = d ; } let mut n = ( ( denom_samples as Float * wt ) . sqrt ( ) + 0.5 ) . round ( ) as usize ; if n < 1 { n = 1 ; } /* End of Adapted Radiance's code*/ ( 0 .. n ) . for_each ( | _ | { let ( new_ray , _bsdf_value , _is_specular ) = material . sample_bsdf ( normal , e1 , e2 , intersection_pt , * ray , rng ) ; let new_ray_dir = new_ray . geometry . direction ; debug_assert ! ( ( 1. as Float new_ray_dir length ( ) ) abs ( ) 1e-5 " " new_ray_dir length ( ) ) ; let cos_theta = ( normal * new_ray_dir ) . abs ( ) ; let refl = material . colour ( ) ; // current_value * refl * cos_theta * bsdf_value / pdf == bsdf_value let new_value = current_value * refl * cos_theta /* * bsdf_value   * one_over_samples * 1.5*/ ; // Check reflection limits... as described in RTRACE's man // if  self.limit_reflections > 0 && new_value < self.limit_weight { //     return; // }  intens = new_value . red ; if new_value . green > intens { intens = new_value . green ; } if new_value . blue > intens { intens = new_value . blue ; } if self . limit_weight > 0. && intens < self . limit_weight { // russian roulette let q : Float = rng . gen ( ) ; if q > intens / self . limit_weight { return ; } } self . trace_ray ( scene , & new_ray , current_depth + 1 , new_value * 1.5 , denom_samples * n , contribution , rng ) ; } ) ; // End the foreach spawned ray } } else { panic ! ( " " ) ; } } else { let bin_n = self . reinhart . dir_to_bin ( ray . geometry . direction ) ; let li = Spectrum :: gray ( 3. ) ; let old_value = contribution . get ( 0 , bin_n ) . unwrap ( ) ; contribution . set ( 0 , bin_n , old_value + li * current_value / denom_samples as Float , ) . unwrap ( ) ; } }
Recursively traces a ray until it excedes the `max_depth` of the
`DCFactory` or the ray does not hit anything (i.e., it reaches either
the sky or the ground)
Recursively traces a ray until it excedes the ` max_depth ` of the ` DCFactory ` or the ray does not hit anything ( i . e . it reaches either the sky or the ground )
&self
scene
&Scene
ray
&Ray
current_depth
usize
current_value
Spectrum
denom_samples
usize
contribution
&mut ColourMatrix
rng
&mut RandGen
&self
scene
&Scene
ray
&Ray
current_depth
usize
current_value
Spectrum
denom_samples
usize
contribution
&mut ColourMatrix
rng
&mut RandGen