Files
nodarium/nodes/max/plantarium/branch/src/lib.rs
2026-01-19 01:29:12 +01:00

109 lines
3.5 KiB
Rust

use nodarium_macros::nodarium_definition_file;
use nodarium_macros::nodarium_execute;
use nodarium_utils::{
concat_arg_vecs, evaluate_float, evaluate_int,
geometry::{
create_path, interpolate_along_path, rotate_vector_by_angle, wrap_path, wrap_path_mut,
},
log, split_args,
};
use std::f32::consts::PI;
nodarium_definition_file!("src/input.json");
#[nodarium_execute]
pub fn execute(input: &[i32]) -> Vec<i32> {
let args = split_args(input);
let paths = split_args(args[0]);
let mut output: Vec<Vec<i32>> = Vec::new();
let resolution = evaluate_int(args[8]).max(4) as usize;
let depth = evaluate_int(args[6]);
let mut max_depth = 0;
for path_data in paths.iter() {
if path_data[2] != 0 {
continue;
}
max_depth = max_depth.max(path_data[3]);
}
for path_data in paths.iter() {
// if this is not a path ignore it
if path_data[2] != 0 || path_data[3] < (max_depth - depth + 1) {
output.push(path_data.to_vec());
continue;
}
let path = wrap_path(path_data);
let branch_amount = evaluate_int(args[7]).max(1);
let lowest_branch = evaluate_float(args[4]);
let highest_branch = evaluate_float(args[5]);
for i in 0..branch_amount {
let a = i as f32 / (branch_amount - 1).max(1) as f32;
let length = evaluate_float(args[1]);
let thickness = evaluate_float(args[2]);
let offset_single = if i % 2 == 0 {
evaluate_float(args[3])
} else {
0.0
};
let root_alpha = (a * (highest_branch - lowest_branch) + lowest_branch)
.min(1.0)
.max(0.0);
let (branch_origin, orthogonal, direction) = interpolate_along_path(
path.points,
root_alpha + (offset_single - 0.5) * 6.0 / resolution as f32,
);
let rotation_angle = (evaluate_float(args[9]) * PI / 180.0) * i as f32;
// check if diration contains NaN
if orthogonal[0].is_nan() || orthogonal[1].is_nan() || orthogonal[2].is_nan() {
log!(
"BRANCH direction contains NaN: {:?}, branch_origin: {:?}, branch: {}",
direction,
branch_origin,
i
);
continue;
}
let branch_direction = rotate_vector_by_angle(orthogonal, direction, rotation_angle);
log!(
"BRANCH depth: {}, branch_origin: {:?}, direction_at: {:?}, branch_direction: {:?}",
depth,
branch_origin,
direction,
branch_direction
);
let mut branch_data = create_path(resolution, depth + 1);
let branch = wrap_path_mut(&mut branch_data);
for j in 0..resolution {
let _a = j as f32 / (resolution - 1) as f32;
branch.points[j * 4] = branch_origin[0] + branch_direction[0] * _a * length;
branch.points[j * 4 + 1] = branch_origin[1] + branch_direction[1] * _a * length;
branch.points[j * 4 + 2] = branch_origin[2] + branch_direction[2] * _a * length;
branch.points[j * 4 + 3] = branch_origin[3] * thickness * (1.0 - _a);
}
output.push(branch_data);
}
output.push(path_data.to_vec());
}
concat_arg_vecs(output)
}