fn create_branch<R: Rng>(
        &mut self,
        rng: &mut R,
        start: Point3f,
        dir: Vector3f,
        depth: u16,
        parent_diam: f32,
        height_branchlength_dependence: fn(_: f32) -> f32,
    ) {
        if depth > 3 {
            // Limit recursion
            return;
        }
        // Current normalized growing direction, variated slightly as segments are
        // generated
        let mut dir = dir.normalize();

        // Determine starting diameter of the new branch
        let mut diam = range_sample(&self.preset.branch_diameter_factor, rng) * parent_diam;
        // Determine how much segment diameter is reduced
        let diam_factor = range_sample(&self.preset.branch_diam_reduction, rng) * parent_diam;
        // How many segments should this branch get?
        let segment_count = range_sample(&self.preset.branch_segment_count, rng);
        // How long should the segment be?
        let segment_length = range_sample(&self.preset.branch_segment_length, rng);
        let segment_length2 = range_sample(&self.preset.branch_segment_length2, rng);

        let mut points = vec![ControlPoint {
            point: start,
            diameter: diam,
        }];

        {
            let mut last = start;
            // Helper for adding a new point to this branch, which possibly grows a new
            // branch.
            let mut add_point = |dist, diam| {
                // First, get a random angle by which to variate this segment.
                let mut x_angle = range_sample(&self.preset.branch_segment_angle, rng);
                let mut y_angle = range_sample(&self.preset.branch_segment_angle, rng);

                // Invert sign with 50%, to mirror the specified range to the other side
                x_angle = if rng.gen() { -x_angle } else { x_angle };
                y_angle = if rng.gen() { -y_angle } else { y_angle };

                let rotation = Basis3::from(Euler {
                    x: Deg::new(x_angle),
                    y: Deg::new(y_angle),
                    z: Deg::new(0.0),
                });
                dir = rotation.rotate_vector(dir);

                // We need to add a point with a distance of `dist` from `last`.
                let point = last + dir * dist;
                last = point;

                if rng.gen_weighted_bool(depth as u32 * 2) {
                    // Build a vector for the branch direction (Z is up)
                    let dir = self.gen_branch_direction(rng, dir);
                    self.create_branch(
                        rng,
                        point,
                        dir,
                        depth + 1,
                        diam,
                        height_branchlength_dependence,
                    );
                }

                points.push(ControlPoint {
                    point: point,
                    diameter: diam,
                });
            };

            // In a loop, get the length of the next segment from the current diameter.
            for _ in 0..segment_count {
                assert!(height_branchlength_dependence(start.z) > 0.0);
                let length = height_branchlength_dependence(start.z)
                    * segment_dist(segment_length, segment_length2, diam, depth);
                diam *= diam_factor;

                add_point(length, diam);

                if diam < 0.005 {
                    // Bail out at 5mm
                    break;
                }
            }
        }

        assert!(
            points.len() >= 2,
            "should've generated at least 2 points :("
        );
        self.branches.push(Branch {
            points: points,
            is_trunk: self.preset.leaf_depth > depth,
        });
    }
/// Generates a new branch at the given start point.
///
/// # Parameters
///
/// * `rng`: The RNG to use
/// * `start`: The point at which the branch should start
/// * `dir`: Direction in which the branch should grow
/// * `depth`: Recursion depth, used to limit the maximum branch depth
/// * `parent_diam`: Diameter of the node of the parent branch where this
///   branch starts
Generates a new branch at the given start point.
Generates a new branch at the given start point .
fn create_branch<R: Rng>(
        &mut self,
        rng: &mut R,
        start: Point3f,
        dir: Vector3f,
        depth: u16,
        parent_diam: f32,
        height_branchlength_dependence: fn(_: f32) -> f32,
    ) {
        if depth > 3 {
            // Limit recursion
            return;
        }
        // Current normalized growing direction, variated slightly as segments are
        // generated
        let mut dir = dir.normalize();
        // Determine starting diameter of the new branch
        let mut diam = range_sample(&self.preset.branch_diameter_factor, rng) * parent_diam;
        // Determine how much segment diameter is reduced
        let diam_factor = range_sample(&self.preset.branch_diam_reduction, rng) * parent_diam;
        // How many segments should this branch get?
        let segment_count = range_sample(&self.preset.branch_segment_count, rng);
        // How long should the segment be?
        let segment_length = range_sample(&self.preset.branch_segment_length, rng);
        let segment_length2 = range_sample(&self.preset.branch_segment_length2, rng);
        let mut points = vec![ControlPoint {
            point: start,
            diameter: diam,
        }];
        {
            let mut last = start;
            // Helper for adding a new point to this branch, which possibly grows a new
            // branch.
            let mut add_point = |dist, diam| {
                // First, get a random angle by which to variate this segment.
                let mut x_angle = range_sample(&self.preset.branch_segment_angle, rng);
                let mut y_angle = range_sample(&self.preset.branch_segment_angle, rng);
                // Invert sign with 50%, to mirror the specified range to the other side
                x_angle = if rng.gen() { -x_angle } else { x_angle };
                y_angle = if rng.gen() { -y_angle } else { y_angle };
                let rotation = Basis3::from(Euler {
                    x: Deg::new(x_angle),
                    y: Deg::new(y_angle),
                    z: Deg::new(0.0),
                });
                dir = rotation.rotate_vector(dir);
                // We need to add a point with a distance of `dist` from `last`.
                let point = last + dir * dist;
                last = point;
                if rng.gen_weighted_bool(depth as u32 * 2) {
                    // Build a vector for the branch direction (Z is up)
                    let dir = self.gen_branch_direction(rng, dir);
                    self.create_branch(
                        rng,
                        point,
                        dir,
                        depth + 1,
                        diam,
                        height_branchlength_dependence,
                    );
                }
                points.push(ControlPoint {
                    point: point,
                    diameter: diam,
                });
            };
            // In a loop, get the length of the next segment from the current diameter.
            for _ in 0..segment_count {
                assert!(height_branchlength_dependence(start.z) > 0.0);
                let length = height_branchlength_dependence(start.z)
                    * segment_dist(segment_length, segment_length2, diam, depth);
                diam *= diam_factor;
                add_point(length, diam);
                if diam < 0.005 {
                    // Bail out at 5mm
                    break;
                }
            }
        }
        assert!(
            points.len() >= 2,
            "should've generated at least 2 points :("
        );
        self.branches.push(Branch {
            points: points,
            is_trunk: self.preset.leaf_depth > depth,
        });
    }
fn create_branch < R : Rng > ( & mut self , rng : & mut R , start : Point3f , dir : Vector3f , depth : u16 , parent_diam : f32 , height_branchlength_dependence : fn ( _ : f32 ) -> f32 , ) { if depth > 3 { // Limit recursion return ; } // Current normalized growing direction, variated slightly as segments are // generated let mut dir = dir . normalize ( ) ; // Determine starting diameter of the new branch let mut diam = range_sample ( & self . preset . branch_diameter_factor , rng ) * parent_diam ; // Determine how much segment diameter is reduced let diam_factor = range_sample ( & self . preset . branch_diam_reduction , rng ) * parent_diam ; // How many segments should this branch get? let segment_count = range_sample ( & self . preset . branch_segment_count , rng ) ; // How long should the segment be? let segment_length = range_sample ( & self . preset . branch_segment_length , rng ) ; let segment_length2 = range_sample ( & self . preset . branch_segment_length2 , rng ) ; let mut points = vec ! [ ControlPoint { point start diameter diam } ] ; { let mut last = start ; // Helper for adding a new point to this branch, which possibly grows a new // branch. let mut add_point = | dist , diam | { // First, get a random angle by which to variate this segment. let mut x_angle = range_sample ( & self . preset . branch_segment_angle , rng ) ; let mut y_angle = range_sample ( & self . preset . branch_segment_angle , rng ) ; // Invert sign with 50%, to mirror the specified range to the other side x_angle = if rng . gen ( ) { - x_angle } else { x_angle } ; y_angle = if rng . gen ( ) { - y_angle } else { y_angle } ; let rotation = Basis3 :: from ( Euler { x : Deg :: new ( x_angle ) , y : Deg :: new ( y_angle ) , z : Deg :: new ( 0.0 ) , } ) ; dir = rotation . rotate_vector ( dir ) ; // We need to add a point with a distance of `dist` from `last`. let point = last + dir * dist ; last = point ; if rng . gen_weighted_bool ( depth as u32 * 2 ) { // Build a vector for the branch direction (Z is up) let dir = self . gen_branch_direction ( rng , dir ) ; self . create_branch ( rng , point , dir , depth + 1 , diam , height_branchlength_dependence , ) ; } points . push ( ControlPoint { point : point , diameter : diam , } ) ; } ; // In a loop, get the length of the next segment from the current diameter. for _ in 0 .. segment_count { assert ! ( height_branchlength_dependence ( start z ) 0.0 ) ; let length = height_branchlength_dependence ( start . z ) * segment_dist ( segment_length , segment_length2 , diam , depth ) ; diam *= diam_factor ; add_point ( length , diam ) ; if diam < 0.005 { // Bail out at 5mm break ; } } } assert ! ( points len ( ) 2 " " ) ; self . branches . push ( Branch { points : points , is_trunk : self . preset . leaf_depth > depth , } ) ; }
Generates a new branch at the given start point.
Generates a new branch at the given start point .
&mut self
rng
&mut R
start
Point3f
dir
Vector3f
depth
u16
parent_diam
f32
height_branchlength_dependence
f32