private void AddBranchesToSegment(TreeSegment segment, double absoluteAngle) { if (segment.Depth == MaxDepth) { return; } if (segment.Thickness < 0.002) { return; } const double maxDevAngle = 0.1 * TAU; const double gravityNormal = 0.75 * TAU; var deltaAngle = Math.Atan2(Math.Sin(gravityNormal - absoluteAngle), Math.Cos(gravityNormal - absoluteAngle)); if (Math.Abs(deltaAngle) < maxDevAngle) { return; } var randomDeviationAngle = random.NextDouble() * 2 * MaxRotationFactor - MaxRotationFactor; var deviationAngle = BiasedValue(0, randomDeviationAngle, 1); var branchingSpread = random.UniformRandom(BranchSpreadMin, BranchSpreadMax); if (segment.Depth == 0) { AddAngledBranch(segment, deviationAngle - branchingSpread / 2, absoluteAngle); AddAngledBranch(segment, deviationAngle + branchingSpread / 2, absoluteAngle); AddAngledBranch(segment, deviationAngle, absoluteAngle); } else if (random.NextDouble() <= ProbabilitySingleBranch) { // no branching AddAngledBranch(segment, deviationAngle, absoluteAngle); } else { // branching var leftAngle = deviationAngle - branchingSpread / 2; var rightAngle = deviationAngle + branchingSpread / 2; if (random.NextDouble() < 0.8) { var rndAngle = random.UniformRandom(deviationAngle - branchingSpread, deviationAngle + branchingSpread); var thickness = random.UniformRandom(0.25, 0.5); AddAngledBranch(segment, rndAngle, absoluteAngle, extraThicknessFactor: thickness); } AddAngledBranch(segment, leftAngle, absoluteAngle); AddAngledBranch(segment, rightAngle, absoluteAngle); } }