feat: add vec3 to stem

This commit is contained in:
max_richter 2024-04-18 13:16:33 +02:00
parent 815152d23c
commit 32426ac045
31 changed files with 563 additions and 327 deletions

137
Cargo.lock generated
View File

@ -65,26 +65,6 @@ dependencies = [
"wasm-bindgen-test", "wasm-bindgen-test",
] ]
[[package]]
name = "getrandom"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gl_matrix"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df64d0245c589931a0b5a385a63e7db2aeff209bdd471df0417e0f230a4c33ae"
dependencies = [
"rand",
]
[[package]] [[package]]
name = "glam" name = "glam"
version = "0.27.0" version = "0.27.0"
@ -106,12 +86,6 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.21" version = "0.4.21"
@ -141,6 +115,48 @@ dependencies = [
"web-sys", "web-sys",
] ]
[[package]]
name = "max-plantarium-sum"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"macros",
"serde",
"serde-wasm-bindgen",
"utils",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]]
name = "max-plantarium-triangle"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"macros",
"serde",
"serde-wasm-bindgen",
"utils",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]]
name = "max-plantarium-vec3"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"macros",
"serde",
"serde-wasm-bindgen",
"utils",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.19.0" version = "1.19.0"
@ -152,6 +168,7 @@ name = "output"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook", "console_error_panic_hook",
"glam",
"macros", "macros",
"serde", "serde",
"serde-wasm-bindgen", "serde-wasm-bindgen",
@ -162,12 +179,6 @@ dependencies = [
"web-sys", "web-sys",
] ]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.80" version = "1.0.80"
@ -186,47 +197,6 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "rand"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom",
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core",
]
[[package]] [[package]]
name = "random" name = "random"
version = "0.1.0" version = "0.1.0"
@ -308,20 +278,6 @@ dependencies = [
"web-sys", "web-sys",
] ]
[[package]]
name = "sum"
version = "0.1.0"
dependencies = [
"console_error_panic_hook",
"macros",
"serde",
"serde-wasm-bindgen",
"utils",
"wasm-bindgen",
"wasm-bindgen-test",
"web-sys",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.109"
@ -369,7 +325,6 @@ name = "utils"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"console_error_panic_hook", "console_error_panic_hook",
"gl_matrix",
"glam", "glam",
"serde", "serde",
"serde_json", "serde_json",
@ -377,12 +332,6 @@ dependencies = [
"web-sys", "web-sys",
] ]
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.92" version = "0.2.92"

View File

@ -6,13 +6,12 @@
export let node: Node; export let node: Node;
export let input: NodeInput; export let input: NodeInput;
export let id: string; export let id: string;
export let label: string | undefined;
const graph = getGraphManager(); const graph = getGraphManager();
let value = node?.props?.[id] ?? input.value; let value = node?.props?.[id] ?? input.value;
let elementId = Math.random().toString(36).substring(7); export let elementId: string = `input-${Math.random().toString(36).substring(7)}`;
$: if (node?.props?.[id] !== value) { $: if (node?.props?.[id] !== value) {
node.props = { ...node.props, [id]: value }; node.props = { ...node.props, [id]: value };
@ -21,5 +20,4 @@
} }
</script> </script>
<label for="input-{elementId}">{label || id}</label>
<Input id="input-{elementId}" {input} bind:value /> <Input id="input-{elementId}" {input} bind:value />

View File

@ -1,10 +1,14 @@
<script lang="ts"> <script lang="ts">
import type { NodeInput as NodeInputType, Socket, Node as NodeType } from '@nodes/types'; import type {
import { getContext } from 'svelte'; NodeInput as NodeInputType,
import { createNodePath } from '../helpers/index.js'; Socket,
import { possibleSocketIds } from '../graph/stores.js'; Node as NodeType,
import { getGraphManager } from '../graph/context.js'; } from "@nodes/types";
import NodeInput from './NodeInput.svelte'; import { getContext } from "svelte";
import { createNodePath } from "../helpers/index.js";
import { possibleSocketIds } from "../graph/stores.js";
import { getGraphManager } from "../graph/context.js";
import NodeInput from "./NodeInput.svelte";
export let node: NodeType; export let node: NodeType;
export let input: NodeInputType; export let input: NodeInputType;
@ -17,9 +21,13 @@
const graphId = graph.id; const graphId = graph.id;
const inputSockets = graph.inputSockets; const inputSockets = graph.inputSockets;
const setDownSocket = getContext<(socket: Socket) => void>('setDownSocket'); const elementId = `input-${Math.random().toString(36).substring(7)}`;
const setDownSocket = getContext<(socket: Socket) => void>("setDownSocket");
const getSocketPosition = const getSocketPosition =
getContext<(node: NodeType, index: string) => [number, number]>('getSocketPosition'); getContext<(node: NodeType, index: string) => [number, number]>(
"getSocketPosition",
);
function handleMouseDown(ev: MouseEvent) { function handleMouseDown(ev: MouseEvent) {
ev.preventDefault(); ev.preventDefault();
@ -27,7 +35,7 @@
setDownSocket({ setDownSocket({
node, node,
index: id, index: id,
position: getSocketPosition(node, id) position: getSocketPosition(node, id),
}); });
} }
@ -41,7 +49,7 @@
y: 51, y: 51,
cornerBottom, cornerBottom,
leftBump, leftBump,
aspectRatio aspectRatio,
}); });
const pathDisabled = createNodePath({ const pathDisabled = createNodePath({
depth: 0, depth: 0,
@ -49,7 +57,7 @@
y: 50, y: 50,
cornerBottom, cornerBottom,
leftBump, leftBump,
aspectRatio aspectRatio,
}); });
const pathHover = createNodePath({ const pathHover = createNodePath({
depth: 6, depth: 6,
@ -57,21 +65,35 @@
y: 50.5, y: 50.5,
cornerBottom, cornerBottom,
leftBump, leftBump,
aspectRatio aspectRatio,
}); });
</script> </script>
<div class="wrapper" class:disabled={$possibleSocketIds && !$possibleSocketIds.has(socketId)}> <div
class="wrapper"
class:disabled={$possibleSocketIds && !$possibleSocketIds.has(socketId)}
>
{#key id && graphId} {#key id && graphId}
{#if node?.tmp?.type?.inputs?.[id]?.external !== true}
<div class="content" class:disabled={$inputSockets.has(socketId)}> <div class="content" class:disabled={$inputSockets.has(socketId)}>
<NodeInput {node} {input} {id} label={input.label} /> <label for={elementId}>{input.label || id}</label>
</div> {#if node?.tmp?.type?.inputs?.[id]?.external !== true}
<NodeInput {elementId} {node} {input} {id} />
{/if} {/if}
</div>
{#if node?.tmp?.type?.inputs?.[id]?.internal !== true} {#if node?.tmp?.type?.inputs?.[id]?.internal !== true}
<div class="large target" on:mousedown={handleMouseDown} role="button" tabindex="0" /> <div
<div class="small target" on:mousedown={handleMouseDown} role="button" tabindex="0" /> class="large target"
on:mousedown={handleMouseDown}
role="button"
tabindex="0"
/>
<div
class="small target"
on:mousedown={handleMouseDown}
role="button"
tabindex="0"
/>
{/if} {/if}
{/key} {/key}

View File

@ -73,6 +73,7 @@ export class RemoteNodeRegistry implements NodeRegistry {
nodeIds.push("max/plantarium/random"); nodeIds.push("max/plantarium/random");
nodeIds.push("max/plantarium/float"); nodeIds.push("max/plantarium/float");
nodeIds.push("max/plantarium/triangle"); nodeIds.push("max/plantarium/triangle");
nodeIds.push("max/plantarium/vec3");
nodeIds.push("max/plantarium/output"); nodeIds.push("max/plantarium/output");
nodeIds.push("max/plantarium/array"); nodeIds.push("max/plantarium/array");
nodeIds.push("max/plantarium/sum"); nodeIds.push("max/plantarium/sum");

View File

@ -1,5 +1,5 @@
import type { Graph, NodeRegistry, NodeType, RuntimeExecutor } from "@nodes/types"; import type { Graph, NodeRegistry, NodeType, RuntimeExecutor } from "@nodes/types";
import { fastHash, concat_encoded, encodeFloat } from "@nodes/utils" import { fastHash, concat_encoded, encodeFloat, encode } from "@nodes/utils"
export class MemoryRuntimeExecutor implements RuntimeExecutor { export class MemoryRuntimeExecutor implements RuntimeExecutor {
@ -176,15 +176,22 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
return encodeFloat(value as number); return encodeFloat(value as number);
} }
if (Array.isArray(value)) {
return encode(value);
}
return value; return value;
}); });
console.log(transformed_inputs);
const a2 = performance.now(); const a2 = performance.now();
// console.log(`${a2 - a1}ms TRANSFORMED_INPUTS`); // console.log(`${a2 - a1}ms TRANSFORMED_INPUTS`);
const _inputs = concat_encoded(transformed_inputs); const _inputs = concat_encoded(transformed_inputs);
const a3 = performance.now(); const a3 = performance.now();
console.log(`executing ${node_type.id || node.id}`, _inputs);
results[node.id] = node_type.execute(_inputs) as number; results[node.id] = node_type.execute(_inputs) as number;
const duration = performance.now() - a3; const duration = performance.now() - a3;
if (duration > 5) { if (duration > 5) {

View File

@ -0,0 +1,6 @@
/target
**/*.rs.bk
Cargo.lock
bin/
pkg/
wasm-pack.log

View File

@ -0,0 +1,28 @@
[package]
name = "triangle"
version = "0.1.0"
authors = ["Max Richter <jim-x@web.de>"]
edition = "2018"
[lib]
crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
utils = { version = "0.1.0", path = "../../../../packages/utils" }
macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@ -0,0 +1,6 @@
{
"scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features",
"dev": "cargo watch -s 'pnpm build'"
}
}

View File

@ -0,0 +1,4 @@
{
"outputs": [],
"inputs": {}
}

View File

@ -0,0 +1,12 @@
use macros::include_definition_file;
use utils::{decode_float, encode_float, wrap_arg};
use wasm_bindgen::prelude::*;
use web_sys::console;
include_definition_file!("src/input.json");
#[rustfmt::skip]
#[wasm_bindgen]
pub fn execute(input: &[i32]) -> Vec<i32> {
vec![]
}

View File

@ -0,0 +1,13 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@ -1,5 +1,5 @@
use macros::include_definition_file; use macros::include_definition_file;
use utils::{evaluate_args, get_args}; use utils::{evaluate_arg, get_args};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use web_sys::console; use web_sys::console;
@ -11,9 +11,8 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
let args = get_args(input); let args = get_args(input);
let value_encoded = evaluate_args(args[0]); let value_encoded = evaluate_arg(args[0]);
// let value = decode_float(value_encoded[0], value_encoded[1]); let length = evaluate_arg(args[1]) as usize;
let length = (args[1][0]) as usize;
console::log_1(&format!("WASM(array): input: {:?} -> {:?}", args, value_encoded).into()); console::log_1(&format!("WASM(array): input: {:?} -> {:?}", args, value_encoded).into());
@ -22,7 +21,7 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
res.push(0); res.push(0);
res.push(length as i32 + 4); res.push(length as i32 + 4);
for _ in 0..length { for _ in 0..length {
res.push(value_encoded[0]); res.push(value_encoded);
} }
res.push(1); res.push(1);
res.push(1); res.push(1);

View File

@ -1,7 +1,6 @@
use crate::geometry::calculate_normals;
use macros::include_definition_file; use macros::include_definition_file;
use utils::{ use utils::{
decode_float, encode_float, evaluate_args, geometry, get_args, set_panic_hook, wrap_arg, encode_float, evaluate_float, geometry::calculate_normals, get_args, set_panic_hook, wrap_arg,
}; };
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use web_sys::console; use web_sys::console;
@ -18,12 +17,10 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
console::log_1(&format!("WASM(cube): input: {:?} -> {:?}", input, args ).into()); console::log_1(&format!("WASM(cube): input: {:?} -> {:?}", input, args ).into());
let arg1 = evaluate_args(args[0]); let size = evaluate_float(args[0]);
let decoded = decode_float(arg1[0]); let p = encode_float(size);
let n = encode_float(-size);
let p = encode_float(decoded);
let n = encode_float(-decoded);
// [[1,3, x, y, z, x, y,z,x,y,z]]; // [[1,3, x, y, z, x, y,z,x,y,z]];

View File

@ -25,6 +25,7 @@ macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde-wasm-bindgen = "0.4" serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true } console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] } web-sys = { version = "0.3.69", features = ["console"] }
glam = "0.27.0"
[dev-dependencies] [dev-dependencies]
wasm-bindgen-test = "0.3.34" wasm-bindgen-test = "0.3.34"

View File

@ -1,10 +1,14 @@
use glam::{Mat4, Vec3};
use macros::include_definition_file; use macros::include_definition_file;
use utils::{concat_args, geometry::extrude_path, get_args}; use utils::{
concat_args,
geometry::{extrude_path, transform_geometry},
get_args,
};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
include_definition_file!("src/inputs.json"); include_definition_file!("src/inputs.json");
#[rustfmt::skip]
#[wasm_bindgen] #[wasm_bindgen]
pub fn execute(input: Vec<i32>) -> Vec<i32> { pub fn execute(input: Vec<i32>) -> Vec<i32> {
utils::set_panic_hook(); utils::set_panic_hook();
@ -13,19 +17,20 @@ pub fn execute(input: Vec<i32>) -> Vec<i32> {
let mut output: Vec<Vec<i32>> = Vec::new(); let mut output: Vec<Vec<i32>> = Vec::new();
for arg in args { for arg in args {
if arg.len() < 3 {
if arg.len() < 3 { continue; } continue;
}
if arg[2] == 0 { if arg[2] == 0 {
let _arg = &arg[3..]; let _arg = &arg[3..];
let geometry = extrude_path(_arg, 16); let mut geometry = extrude_path(_arg, 4);
let matrix = Mat4::from_translation(Vec3::new(0.0, 0.0, 0.0));
geometry = transform_geometry(geometry, matrix);
output.push(geometry); output.push(geometry);
} else if arg[2] == 1 { } else if arg[2] == 1 {
output.push(arg.to_vec()); output.push(arg.to_vec());
} }
} }
concat_args(output) concat_args(output)
} }

View File

@ -3,6 +3,15 @@
"plant" "plant"
], ],
"inputs": { "inputs": {
"origin": {
"type": "vec3",
"value": [
0,
0,
0
],
"external": true
},
"length": { "length": {
"type": "float", "type": "float",
"value": 2 "value": 2

View File

@ -1,5 +1,5 @@
use macros::include_definition_file; use macros::include_definition_file;
use utils::{decode_float, evaluate_args, get_args, set_panic_hook, wrap_arg}; use utils::{evaluate_float, evaluate_vec3, get_args, log, set_panic_hook, wrap_arg};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json"); include_definition_file!("src/input.json");
@ -10,9 +10,13 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
let args = get_args(input); let args = get_args(input);
let length = decode_float(evaluate_args(args[0])[0]); log!("Args: {:?}", args);
let thickness = decode_float(evaluate_args(args[1])[0]);
let resolution = 512; //evaluate_args(args[2]); let origin = evaluate_vec3(args[0]);
log!("Origin: {:?}", origin);
let length = evaluate_float(args[1]);
let thickness = evaluate_float(args[2]);
let resolution = 16;
let mut path: Vec<i32> = vec![0; resolution * 4 + 1]; let mut path: Vec<i32> = vec![0; resolution * 4 + 1];
path.resize(resolution * 4 + 1, 0); path.resize(resolution * 4 + 1, 0);
@ -32,9 +36,9 @@ pub fn execute(input: &[i32]) -> Vec<i32> {
for i in 0..resolution { for i in 0..resolution {
let a = i as f32 / resolution as f32; let a = i as f32 / resolution as f32;
path_p[i * 4] = (a * 8.0).sin() * 0.2; path_p[i * 4] = origin[0] + (a * 8.0).sin() * 0.2;
path_p[i * 4 + 1] = a * length; path_p[i * 4 + 1] = origin[1] + a * length;
path_p[i * 4 + 2] = 0.0; path_p[i * 4 + 2] = origin[2] + 0.0;
path_p[i * 4 + 3] = thickness * (1.0 - a); path_p[i * 4 + 3] = thickness * (1.0 - a);
} }

View File

@ -1,5 +1,5 @@
[package] [package]
name = "sum" name = "max-plantarium-sum"
version = "0.1.0" version = "0.1.0"
authors = ["Max Richter <jim-x@web.de>"] authors = ["Max Richter <jim-x@web.de>"]
edition = "2018" edition = "2018"

View File

@ -1,5 +1,5 @@
[package] [package]
name = "triangle" name = "max-plantarium-triangle"
version = "0.1.0" version = "0.1.0"
authors = ["Max Richter <jim-x@web.de>"] authors = ["Max Richter <jim-x@web.de>"]
edition = "2018" edition = "2018"

6
nodes/max/plantarium/vec3/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/target
**/*.rs.bk
Cargo.lock
bin/
pkg/
wasm-pack.log

View File

@ -0,0 +1,28 @@
[package]
name = "max-plantarium-vec3"
version = "0.1.0"
authors = ["Max Richter <jim-x@web.de>"]
edition = "2018"
[lib]
crate-type = ["cdylib", "rlib"]
[features]
default = ["console_error_panic_hook"]
[dependencies]
wasm-bindgen = "0.2.84"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
utils = { version = "0.1.0", path = "../../../../packages/utils" }
macros = { version = "0.1.0", path = "../../../../packages/macros" }
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4"
console_error_panic_hook = { version = "0.1.7", optional = true }
web-sys = { version = "0.3.69", features = ["console"] }
[dev-dependencies]
wasm-bindgen-test = "0.3.34"

View File

@ -0,0 +1,6 @@
{
"scripts": {
"build": "wasm-pack build --release --out-name index --no-default-features",
"dev": "cargo watch -s 'pnpm build'"
}
}

View File

@ -0,0 +1,16 @@
{
"outputs": [
"vec3"
],
"inputs": {
"0": {
"type": "float"
},
"1": {
"type": "float"
},
"2": {
"type": "float"
}
}
}

View File

@ -0,0 +1,20 @@
use macros::include_definition_file;
use utils::log;
use wasm_bindgen::prelude::*;
include_definition_file!("src/input.json");
#[wasm_bindgen]
pub fn execute(args: &[i32]) -> Vec<i32> {
let mut result = Vec::with_capacity(args.len() + 2);
result.push(0); // encoding the [ bracket
result.push(args[1]);
result.extend_from_slice(&args[2..]);
result.push(1);
result.push(1); // closing bracket
log!("WASM(vec3): res {:?}", result);
result
}

View File

@ -0,0 +1,13 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
}

View File

@ -12,5 +12,4 @@ web-sys = { version = "0.3.69", features = ["console"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", default-features = false, features = ["alloc"] } serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
console_error_panic_hook = { version = "0.1.7", optional = true } console_error_panic_hook = { version = "0.1.7", optional = true }
gl_matrix = "0.0.2"
glam = "0.27.0" glam = "0.27.0"

View File

@ -1,4 +1,4 @@
use super::create_empty_geometry; use super::{create_geometry_data, wrap_geometry_data};
use glam::{Mat4, Quat, Vec3}; use glam::{Mat4, Quat, Vec3};
fn create_circle(res: usize) -> Vec<f32> { fn create_circle(res: usize) -> Vec<f32> {
@ -19,22 +19,19 @@ pub fn extrude_path(input_path: &[i32], res_x: usize) -> Vec<i32> {
let circle = create_circle(res_x); let circle = create_circle(res_x);
let mut geometry = create_empty_geometry(vertices_amount, face_amount); let mut geometry_data = create_geometry_data(vertices_amount, face_amount);
let geometry = wrap_geometry_data(&mut geometry_data);
let normals = geometry.normals;
let positions = geometry.positions;
let indices = geometry.faces;
let (_header,rest) = geometry.split_at_mut(5);
let (indices, rest) = rest.split_at_mut(face_amount*3);
let (_positions, _normals) = rest.split_at_mut(vertices_amount*3);
let positions: &mut [f32];
let normals: &mut [f32];
let path: &[f32]; let path: &[f32];
unsafe { unsafe {
path = std::slice::from_raw_parts(input_path.as_ptr() as *const f32, input_path.len()); path = std::slice::from_raw_parts(input_path.as_ptr() as *const f32, input_path.len());
positions = std::slice::from_raw_parts_mut(_positions.as_mut_ptr() as *mut f32, _positions.len());
normals = std::slice::from_raw_parts_mut(_normals.as_mut_ptr() as *mut f32, _normals.len());
} }
normals[0] = 0.0;
for i in 0..point_amount { for i in 0..point_amount {
let index_offset = i * res_x * 6; let index_offset = i * res_x * 6;
@ -109,5 +106,5 @@ pub fn extrude_path(input_path: &[i32], res_x: usize) -> Vec<i32> {
} }
} }
geometry geometry_data
} }

View File

@ -0,0 +1,74 @@
use crate::log;
pub struct GeometryData<'a> {
pub positions: &'a mut [f32], // View into `data`
pub normals: &'a mut [f32], // View into `data`
pub faces: &'a mut [i32], // View into `data`
}
pub fn create_geometry_data(vertex_amount: usize, face_amount: usize) -> Vec<i32> {
let amount = 3 // definition (type, vertex_amount, face_amount)
+ 4 // opening and closing brackets
+ vertex_amount * 3 // positions
+ vertex_amount * 3 // normals
+ face_amount * 3; // faces
let mut geo = vec![0; amount];
geo[0] = 0; // opening bracket
geo[1] = amount as i32 - 2; // opening bracket
geo[2] = 1; // type: geometry
geo[3] = vertex_amount as i32;
geo[4] = face_amount as i32;
geo[amount - 2] = 1; // closing bracket
geo[amount - 1] = 1; // closing bracket
geo
}
pub fn wrap_geometry_data(geometry: &mut [i32]) -> GeometryData {
// Basic validity checks
assert!(
geometry.len() > 5,
"Geometry vector does not contain enough data for a header."
);
// Split at after header
let (header, rest) = geometry.split_at_mut(5);
let vertices_amount = header[3] as usize;
let face_amount = header[4] as usize;
let total_floats = vertices_amount * 3 * 2;
let (faces, rest) = rest.split_at_mut(face_amount * 3);
let (positions_slice, rest) = rest.split_at_mut(vertices_amount * 3);
let (normals_slice, _) = rest.split_at_mut(vertices_amount * 3);
log!(
"Vertices: {}, normals: {}, Total floats: {}",
positions_slice.len(),
normals_slice.len(),
total_floats
);
assert!(
positions_slice.len() + normals_slice.len() == total_floats,
"Slices do not match the expected sizes."
);
let positions: &mut [f32] = unsafe {
std::slice::from_raw_parts_mut(
positions_slice.as_mut_ptr() as *mut f32,
positions_slice.len(),
)
};
let normals: &mut [f32] = unsafe {
std::slice::from_raw_parts_mut(normals_slice.as_mut_ptr() as *mut f32, normals_slice.len())
};
GeometryData {
positions,
normals,
faces,
}
}

View File

@ -1,33 +1,9 @@
mod calculate_normals; mod calculate_normals;
mod extrude_path; mod extrude_path;
mod geometry;
mod transform;
pub use calculate_normals::*; pub use calculate_normals::*;
pub use extrude_path::*; pub use extrude_path::*;
pub use geometry::*;
use crate::log; pub use transform::*;
#[rustfmt::skip]
pub fn create_empty_geometry(vertex_amount: usize, face_amount: usize) -> Vec<i32> {
log!(
"create_empty_geometry: vertex_amount: {}, face_amount: {}",
vertex_amount,
face_amount
);
let amount =
3 // definition (type, vertex_amount, face_amount)
+ 4 // opening and closing brackets
+ vertex_amount * 3 // positions
+ vertex_amount * 3 // normals
+ face_amount * 3; // faces
let mut vec: Vec<i32> = vec![0; amount];
vec[0] = 0; // opening bracket
vec[1] = amount as i32 - 2; // opening bracket
vec[2] = 1; // type: geometry
vec[3] = vertex_amount as i32;
vec[4] = face_amount as i32;
vec[amount - 2] = 1; // closing bracket
vec[amount - 1] = 1; // closing bracket
vec
}

View File

@ -0,0 +1,25 @@
use glam::{Mat4, Vec3};
pub fn transform_geometry(mut geometry: Vec<i32>, matrix: Mat4) -> Vec<i32> {
let (_header, rest) = geometry.split_at_mut(5);
let vertices_amount = _header[3] as usize;
let face_amount = _header[4] as usize;
let (_indices, rest) = rest.split_at_mut(face_amount * 3);
let (_positions, _normals) = rest.split_at_mut(vertices_amount * 3);
let positions: &mut [f32];
unsafe {
positions =
std::slice::from_raw_parts_mut(_positions.as_mut_ptr() as *mut f32, _positions.len());
}
for i in 0..vertices_amount {
let pos = Mat4::transform_point3(&matrix, Vec3::from_slice(&positions[i * 3..i * 3 + 3]));
positions[i * 3] = pos.x;
positions[i * 3 + 1] = pos.y;
positions[i * 3 + 2] = pos.z;
}
geometry
}

View File

@ -1,3 +1,5 @@
use crate::decode_float;
pub fn get_args(args: &[i32]) -> Vec<&[i32]> { pub fn get_args(args: &[i32]) -> Vec<&[i32]> {
let mut idx: usize = 0; let mut idx: usize = 0;
let mut depth = -1; let mut depth = -1;
@ -105,13 +107,29 @@ pub fn evaluate_node(input_args: &[i32]) -> i32 {
} }
} }
pub fn evaluate_args(input_args: &[i32]) -> Vec<i32> { pub fn evaluate_vec3(input_args: &[i32]) -> Vec<f32> {
if input_args.len() == 1 { let args = get_args(input_args);
return input_args.to_vec();
assert!(
args.len() == 3,
"Failed to evaluate Vec3 - Expected 3 arguments, got {}",
args.len()
);
let x = evaluate_float(args[0]);
let y = evaluate_float(args[1]);
let z = evaluate_float(args[2]);
vec![x, y, z]
} }
if input_args.len() == 4 && input_args[0] == 0 && input_args[1] == 3 { pub fn evaluate_float(arg: &[i32]) -> f32 {
return vec![input_args[2], input_args[3]]; decode_float(evaluate_arg(arg))
}
pub fn evaluate_arg(input_args: &[i32]) -> i32 {
if input_args.len() == 1 {
return input_args.to_vec()[0];
} }
let args = get_args(input_args); let args = get_args(input_args);
@ -125,22 +143,20 @@ pub fn evaluate_args(input_args: &[i32]) -> Vec<i32> {
resolved.push(arg[2]); resolved.push(arg[2]);
resolved.push(arg[3]); resolved.push(arg[3]);
} else { } else {
resolved.push(evaluate_args(arg)[0]); resolved.push(evaluate_arg(arg));
} }
} }
if resolved.len() > 1 { if resolved.len() > 1 {
let res = evaluate_node(&resolved); evaluate_node(&resolved)
vec![res]
} else { } else {
resolved resolved[0]
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::encoding::decode_float;
use super::*; use super::*;
#[test] #[test]
@ -152,10 +168,9 @@ mod tests {
// and another math node that adds 2 to that result // and another math node that adds 2 to that result
// the numbers are f32 floats encoded as two i32's // the numbers are f32 floats encoded as two i32's
let result = evaluate_args(&input); let result = evaluate_float(&input);
let decoded = decode_float(result[0]);
assert_eq!(decoded, 6.0); assert_eq!(result, 6.0);
} }
#[test] #[test]