From 070a5b52d06e4225b3d21f42fc7d9243747d5523 Mon Sep 17 00:00:00 2001 From: Max Richter Date: Tue, 23 Apr 2024 20:35:56 +0200 Subject: [PATCH] fix: random node now works as expected --- Cargo.lock | 2 + .../graph-interface/node/NodeParameter.svelte | 2 +- app/src/lib/settings/ActiveNode.svelte | 24 +++--- nodes/max/plantarium/math/src/input.json | 3 +- nodes/max/plantarium/noise/Cargo.toml | 1 + nodes/max/plantarium/noise/src/input.json | 1 + nodes/max/plantarium/noise/src/lib.rs | 33 +++++++- nodes/max/plantarium/random/src/lib.rs | 18 +---- nodes/max/plantarium/stem/src/input.json | 7 +- nodes/max/plantarium/stem/src/lib.rs | 81 ++++++++++--------- nodes/max/plantarium/vec3/src/input.json | 6 +- packages/macros/src/lib.rs | 14 +++- packages/types/src/lib.rs | 4 +- packages/utils/Cargo.toml | 1 + packages/utils/src/lib.rs | 1 + packages/utils/src/nodes.rs | 27 +++++-- 16 files changed, 141 insertions(+), 84 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 08521da..41faecc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -170,6 +170,7 @@ name = "nodes-noise" version = "0.1.0" dependencies = [ "console_error_panic_hook", + "glam", "macros", "noise", "serde", @@ -386,6 +387,7 @@ version = "0.1.0" dependencies = [ "console_error_panic_hook", "glam", + "noise", "serde", "serde_json", "wasm-bindgen", diff --git a/app/src/lib/graph-interface/node/NodeParameter.svelte b/app/src/lib/graph-interface/node/NodeParameter.svelte index 46d5772..180f98b 100644 --- a/app/src/lib/graph-interface/node/NodeParameter.svelte +++ b/app/src/lib/graph-interface/node/NodeParameter.svelte @@ -77,7 +77,7 @@ > {#key id && graphId}
- {#if inputType.label !== false} + {#if inputType.label !== ""} {/if} {#if inputType.external !== true} diff --git a/app/src/lib/settings/ActiveNode.svelte b/app/src/lib/settings/ActiveNode.svelte index 0ff05ce..75cdea8 100644 --- a/app/src/lib/settings/ActiveNode.svelte +++ b/app/src/lib/settings/ActiveNode.svelte @@ -16,11 +16,13 @@ props: Node["props"], inputs: Record, ) { - const store = {}; + const store: Record = {}; Object.keys(inputs).forEach((key) => { - store[key] = props[key] || inputs[key].value; + if (props) { + //@ts-ignore + store[key] = props[key] || inputs[key].value; + } }); - console.log({ store, props }); return writable(store); } @@ -35,24 +37,18 @@ function updateNode() { if (!node || !$store) return; + let needsUpdate = false; Object.keys($store).forEach((_key: string) => { node.props = node.props || {}; const key = _key as keyof typeof $store; - let needsUpdate = false; - console.log({ key }); - if ( - node && - $store && - key in node.props && - node.props[key] !== $store[key] - ) { + if (node && $store && node.props[key] !== $store[key]) { needsUpdate = true; node.props[key] = $store[key]; } - if (needsUpdate) { - manager.execute(); - } }); + if (needsUpdate) { + manager.execute(); + } } $: if (store && $store) { diff --git a/nodes/max/plantarium/math/src/input.json b/nodes/max/plantarium/math/src/input.json index 7861a1d..d746659 100644 --- a/nodes/max/plantarium/math/src/input.json +++ b/nodes/max/plantarium/math/src/input.json @@ -13,8 +13,7 @@ "multiply", "divide" ], - "internal": true, - "value": 0 + "internal": true }, "a": { "type": "float", diff --git a/nodes/max/plantarium/noise/Cargo.toml b/nodes/max/plantarium/noise/Cargo.toml index f1ad8ef..d57b3cf 100644 --- a/nodes/max/plantarium/noise/Cargo.toml +++ b/nodes/max/plantarium/noise/Cargo.toml @@ -24,6 +24,7 @@ serde-wasm-bindgen = "0.4" console_error_panic_hook = { version = "0.1.7", optional = true } web-sys = { version = "0.3.69", features = ["console"] } noise = "0.9.0" +glam = "0.27.0" [dev-dependencies] wasm-bindgen-test = "0.3.34" diff --git a/nodes/max/plantarium/noise/src/input.json b/nodes/max/plantarium/noise/src/input.json index 3f7b655..ac0fdb1 100644 --- a/nodes/max/plantarium/noise/src/input.json +++ b/nodes/max/plantarium/noise/src/input.json @@ -19,6 +19,7 @@ }, "fixBottom": { "type": "float", + "label": "Fixate bottom of plant", "hidden": true, "min": 0, "max": 1 diff --git a/nodes/max/plantarium/noise/src/lib.rs b/nodes/max/plantarium/noise/src/lib.rs index cfbdd0b..7978796 100644 --- a/nodes/max/plantarium/noise/src/lib.rs +++ b/nodes/max/plantarium/noise/src/lib.rs @@ -1,3 +1,4 @@ +use glam::Vec3; use macros::include_definition_file; use noise::{core::open_simplex::open_simplex_2d, permutationtable::PermutationTable, Vector2}; use utils::{ @@ -18,7 +19,7 @@ pub fn execute(input: &[i32]) -> Vec { let args = get_args(input); let plants = get_args(args[0]); - let scale = evaluate_float(args[1]); + let scale = (evaluate_float(args[1]) * 0.1) as f64; let strength = evaluate_float(args[2]); let _fix_bottom = evaluate_float(args[3]); let fix_bottom = if _fix_bottom.is_finite() { @@ -40,24 +41,48 @@ pub fn execute(input: &[i32]) -> Vec { let output: Vec> = plants .iter() - .map(|p| { + .enumerate() + .map(|(j, p)| { let mut plant = p.to_vec(); log!("plant: {:?}", plant); let points = (plant.len() - 5) / 4; + + let p0 = Vec3::new( + decode_float(plant[3]), + decode_float(plant[4]), + decode_float(plant[5]), + ); + + let p2 = Vec3::new( + decode_float(plant[plant.len() - 6]), + decode_float(plant[plant.len() - 5]), + decode_float(plant[plant.len() - 4]), + ); + // .... x, y, z, w, 1, 1 + // -4 -3 -2 -1 + + let length = (p2 - p0).length() as f64; + + log!("p0: {:?} p1: {:?} length: {}", p0, p2, length); + for i in 0..points { let a = i as f64 / (points - 1) as f64; - let px = Vector2::new(0.0, a * scale as f64); - let pz = Vector2::new(a * scale as f64, 0.0); + + let px = Vector2::new(j as f64 + a * length * scale, a * scale as f64); + let pz = Vector2::new(a * scale as f64, j as f64 + a * length * scale); + let nx = open_simplex_2d(px, &hasher) as f32 * strength * 0.1 * lerp(1.0, a as f32, fix_bottom); + let nz = open_simplex_2d(pz, &hasher) as f32 * strength * 0.1 * lerp(1.0, a as f32, fix_bottom); + plant[3 + i * 4] = encode_float(decode_float(plant[3 + i * 4]) + nx); plant[5 + i * 4] = encode_float(decode_float(plant[5 + i * 4]) + nz); } diff --git a/nodes/max/plantarium/random/src/lib.rs b/nodes/max/plantarium/random/src/lib.rs index a553ec8..3eef909 100644 --- a/nodes/max/plantarium/random/src/lib.rs +++ b/nodes/max/plantarium/random/src/lib.rs @@ -1,22 +1,12 @@ use macros::include_definition_file; +use utils::{concat_args, get_args, set_panic_hook}; use wasm_bindgen::prelude::*; include_definition_file!("src/definition.json"); #[wasm_bindgen] pub fn execute(args: &[i32]) -> Vec { - let mut result = Vec::with_capacity(args.len() + 7); - result.push(0); - result.push(1); - result.push(0); // encoding the [ bracket - result.push(args[1] + 1); - - result.push(1); // adding the node-type, random: 0 - result.extend_from_slice(&args[2..]); - - result.push(1); - result.push(1); // closing bracket - result.push(1); - result.push(1); // closing bracket - result + set_panic_hook(); + let args = get_args(args); + concat_args(vec![&[1], args[0], args[1], args[2]]) } diff --git a/nodes/max/plantarium/stem/src/input.json b/nodes/max/plantarium/stem/src/input.json index 0874f1d..733020a 100644 --- a/nodes/max/plantarium/stem/src/input.json +++ b/nodes/max/plantarium/stem/src/input.json @@ -13,13 +13,18 @@ ], "external": true }, + "amount": { + "type": "integer", + "min": 1, + "max": 64, + "value": 1 + }, "length": { "type": "float", "value": 2 }, "thickness": { "type": "float", - "element": "slider", "value": 2 }, "resolution_curve": { diff --git a/nodes/max/plantarium/stem/src/lib.rs b/nodes/max/plantarium/stem/src/lib.rs index 62e9cf8..781be10 100644 --- a/nodes/max/plantarium/stem/src/lib.rs +++ b/nodes/max/plantarium/stem/src/lib.rs @@ -1,5 +1,7 @@ use macros::include_definition_file; -use utils::{evaluate_float, evaluate_int, evaluate_vec3, get_args, log, set_panic_hook, wrap_arg}; +use utils::{ + evaluate_float, evaluate_int, evaluate_vec3, get_args, log, reset_call_count, set_panic_hook, +}; use wasm_bindgen::prelude::*; include_definition_file!("src/input.json"); @@ -8,57 +10,64 @@ include_definition_file!("src/input.json"); pub fn execute(input: &[i32]) -> Vec { set_panic_hook(); + reset_call_count(); + let args = get_args(input); log!("stem args: {:?}", args); - let origin = evaluate_vec3(args[0]); - let length = evaluate_float(args[1]); - let thickness = evaluate_float(args[2]); - let res_curve = evaluate_int(args[3]) as usize; + let amount = evaluate_int(args[1]) as usize; + let res_curve = evaluate_int(args[4]) as usize; - log!( - "origin: {:?} length: {} thickness: {} res_curve: {}", - origin, - length, - thickness, - res_curve - ); + log!("STEM: amount: {} res_curve: {}", amount, res_curve); - let amount_points = res_curve * 4; - // +4 for opening and closing brackets and +1 node-type - let output_size = amount_points + 9; + // 4 extra for opening and closing brackets + // and each stem has 5 extra for opening and closing brackets and node-type + let output_size = 4 + amount * (res_curve * 4 + 5); - // because we could potentially return multiple stems - // we need to encode two pairs of brackets - // let mut path: Vec = vec![0; output_size]; path[0] = 0; // encode opening bracket path[1] = 1; // encode opening bracket - path[2] = 0; // encode opening bracket - path[3] = res_curve as i32 * 4 + 2; // encode opening bracket - path[4] = 0; // encode node-type, stem: 0 - path[output_size - 4] = 1; // encode closing bracket - path[output_size - 3] = 1; // encode closing bracket path[output_size - 2] = 1; // encode closing bracket path[output_size - 1] = 1; // encode closing bracket - let slice = &mut path[5..5 + amount_points]; + for i in 0..amount { + let start_index = 2 + i * (res_curve * 4 + 5); + let end_index = 2 + (i + 1) * (res_curve * 4 + 5); - let path_p: &mut [f32] = unsafe { - assert_eq!(slice.len() % 4, 0); - std::slice::from_raw_parts_mut(slice.as_ptr() as *mut f32, slice.len()) - }; + let origin = evaluate_vec3(args[0]); + let length = evaluate_float(args[2]); + let thickness = evaluate_float(args[3]); - for i in 0..res_curve { - let a = i as f32 / (res_curve - 1) as f32; - path_p[i * 4] = origin[0]; - path_p[i * 4 + 1] = origin[1] + a * length; - path_p[i * 4 + 2] = origin[2]; - path_p[i * 4 + 3] = thickness * (1.0 - a); + log!( + "STEM {i}: origin: {:?} length: {} thickness: {}", + origin, + length, + thickness + ); + + path[start_index] = 0; // encode opening bracket + path[start_index + 1] = res_curve as i32 * 4 + 2; // encode opening bracket + path[start_index + 2] = 0; // encode node-type, stem: 0 + + path[end_index - 2] = 1; // encode closing bracket + path[end_index - 1] = 1; // encode closing bracket + + let path_slice = &mut path[3 + start_index..end_index - 2]; + + let path_p: &mut [f32] = unsafe { + assert_eq!(path_slice.len() % 4, 0); + std::slice::from_raw_parts_mut(path_slice.as_ptr() as *mut f32, path_slice.len()) + }; + + for i in 0..res_curve { + let a = i as f32 / (res_curve - 1) as f32; + path_p[i * 4] = origin[0]; + path_p[i * 4 + 1] = origin[1] + a * length; + path_p[i * 4 + 2] = origin[2]; + path_p[i * 4 + 3] = thickness * (1.0 - a); + } } - log!("res: {:?}", path); - path } diff --git a/nodes/max/plantarium/vec3/src/input.json b/nodes/max/plantarium/vec3/src/input.json index 2a33a14..1991792 100644 --- a/nodes/max/plantarium/vec3/src/input.json +++ b/nodes/max/plantarium/vec3/src/input.json @@ -6,15 +6,15 @@ "inputs": { "0": { "type": "float", - "label": false + "label": "" }, "1": { "type": "float", - "label": false + "label": "" }, "2": { "type": "float", - "label": false + "label": "" } } } diff --git a/packages/macros/src/lib.rs b/packages/macros/src/lib.rs index ac1d639..3de018b 100644 --- a/packages/macros/src/lib.rs +++ b/packages/macros/src/lib.rs @@ -32,6 +32,15 @@ pub fn node_definition(input: TokenStream) -> TokenStream { TokenStream::from(expanded) } +fn add_line_numbers(input: String) -> String { + return input + .split('\n') + .enumerate() + .map(|(i, line)| format!("{:2}: {}", i + 1, line)) + .collect::>() + .join("\n"); +} + #[proc_macro] pub fn include_definition_file(input: TokenStream) -> TokenStream { let file_path = syn::parse_macro_input!(input as syn::LitStr).value(); @@ -51,8 +60,9 @@ pub fn include_definition_file(input: TokenStream) -> TokenStream { // Optionally, validate that the content is valid JSON let _: NodeDefinition = serde_json::from_str(&json_content).unwrap_or_else(|err| { panic!( - "JSON file contains invalid JSON: \n {} \n {}", - json_content, err + "JSON file contains invalid JSON: \n{} \n{}", + err, + add_line_numbers(json_content.clone()) ) }); diff --git a/packages/types/src/lib.rs b/packages/types/src/lib.rs index 18a9fe1..46e1ca0 100644 --- a/packages/types/src/lib.rs +++ b/packages/types/src/lib.rs @@ -80,10 +80,10 @@ pub struct NodeInputSelect { pub default_options: DefaultOptions, #[serde(skip_serializing_if = "Option::is_none")] - pub value: Option, + pub value: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub options: Option>, + pub options: Option>, } #[derive(Serialize, Deserialize)] diff --git a/packages/utils/Cargo.toml b/packages/utils/Cargo.toml index 96eb7e4..08d1494 100644 --- a/packages/utils/Cargo.toml +++ b/packages/utils/Cargo.toml @@ -13,3 +13,4 @@ serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", default-features = false, features = ["alloc"] } console_error_panic_hook = { version = "0.1.7", optional = true } glam = "0.27.0" +noise = "0.9.0" diff --git a/packages/utils/src/lib.rs b/packages/utils/src/lib.rs index a12b170..90dca23 100644 --- a/packages/utils/src/lib.rs +++ b/packages/utils/src/lib.rs @@ -2,6 +2,7 @@ mod encoding; mod nodes; mod tree; pub use encoding::*; +pub use nodes::reset_call_count; pub use tree::*; pub mod geometry; diff --git a/packages/utils/src/nodes.rs b/packages/utils/src/nodes.rs index a624960..74f7dc6 100644 --- a/packages/utils/src/nodes.rs +++ b/packages/utils/src/nodes.rs @@ -1,4 +1,5 @@ use crate::{encoding, log}; +use noise::{core::open_simplex::open_simplex_2d, permutationtable::PermutationTable, Vector2}; pub fn math_node(args: &[i32]) -> i32 { let math_type = args[0]; @@ -19,16 +20,32 @@ pub fn math_node(args: &[i32]) -> i32 { static mut CALL_COUNT: i32 = 0; +pub fn reset_call_count() { + unsafe { + CALL_COUNT = 0; + } +} + pub fn random_node(args: &[i32]) -> i32 { let min = encoding::decode_float(args[0]); let max = encoding::decode_float(args[1]); - let seed = (args[2] + unsafe { CALL_COUNT } * 2312312) % 100_000; - let v = seed as f32 / 100_000.0; - log!("Random node: min: {}, max: {}, seed: {}", min, max, seed); - let result = min + v * (max - min); + + let seed = (args[2] + unsafe { CALL_COUNT }) % 100_000; + let hasher = PermutationTable::new(seed as u32); + + let value = open_simplex_2d(Vector2::new(seed as f64, 5.0), &hasher) as f32 + 0.5; + + log!( + "Random node: min: {}, max: {}, seed: {}, v: {}", + min, + max, + seed, + value + ); + let result = min + value * (max - min); unsafe { - CALL_COUNT += 1; + CALL_COUNT = (CALL_COUNT + 512) % i32::MAX; } encoding::encode_float(result)