feat: add some documentation
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 2m9s

This commit is contained in:
max_richter 2024-05-05 13:47:08 +02:00
parent 94f39bac8e
commit f4853821d4
6 changed files with 194 additions and 6 deletions

View File

@ -1 +0,0 @@
# Developing Nodes

View File

@ -14,7 +14,7 @@ Nodarium
# Table of contents
- [Architecture](./ARCHITECTURE.md)
- [Architecture](./docs/ARCHITECTURE.md)
- [Developing](#developing)
- [Roadmap](#roadmap)
@ -45,6 +45,6 @@ cd app
pnpm dev
```
### [Now you can create your first node 🤓](./DEVELOPING_NODES.md)
### [Now you can create your first node 🤓](./docs/DEVELOPING_NODES.md)
# Roadmap

View File

@ -16,6 +16,30 @@ type Node = {
}
```
## How are the arguments defined?
To define which arguments a nodes accepts we use JSON. This json is embeded into the `.wasm` file of our node. An example `definition.json` file could look like this:
```json
{
"id": "my-name/my-namespace/zylinder-node",
"outputs": [
"geometry"
],
"inputs": {
"height": {
"type": "float",
"value": 2
},
"radius": {
"type": "float",
"value": 0.5
}
}
}
```
For a more in-depth explanation have a look at [./NODE_DEFINITION.md](NODE_DEFINITION.md).
## How are the nodes executed?
## How are the nodes stored?

128
docs/DEVELOPING_NODES.md Normal file
View File

@ -0,0 +1,128 @@
# Developing Nodes
This guide will help you developing your first Nodarium Node written in Rust. As an example we will implement a `cylinder` node, which generates a 3D model of a cylinder.
## Prerequesites
You need to have [Rust](https://www.rust-lang.org/tools/install) and [wasm-pack](https://rustwasm.github.io/wasm-pack/book/) installed. Rust is the language we are going to develop our node in and wasm-pack helps us compile our rust code into a webassembly file.
```bash
# install rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# install wasm-pack
cargo install wasm-pack
```
## Clone Template
```bash
wasm-pack new my-new-node --template https://github.com/jim-fx/nodarium_template
cd my-new-node
```
## Setup Definition
Now we create the definition file of the node.
Here we define what kind of inputs our node will expect and what kind of output it produces. If you want to dive deeper into this topic, have a look at [NODE_DEFINITION.md](./NODE_DEFINITION.md).
`src/definition.json`
```json
{
"id": "my-name/my-namespace/zylinder-node",
"outputs": [
"geometry"
],
"inputs": {
"height": {
"type": "float",
"value": 2,
},
"radius": {
"type": "float",
"value": 0.4
}
}
}
```
If we take a look at the `src/lib.rs` file we see that `src/definition.json` is included with the following line:
```rust
include_definition_file!("src/definition.json");
```
This procedural rust macro loads the definition.json, validates its content and embeds it in our output file.
## Implement Node
This is the hardest part when developing a node, for now you can copy the following content into the `src/lib.rs` file:
```rust
use glam::Vec2;
use wasm_bindgen::prelude::*;
nodarium_macros::include_definition_file!("src/definition.json");
#[wasm_bindgen]
pub fn execute(input: &[i32]) -> Vec<i32> {
let arguments = nodarium_utils::split_args(input);
let height = nodarium_utils::evaluate_float(arguments[0]);
let radius = nodarium_utils::evaluate_float(arguments[1]);
let mut geometry_data = nodarium_utils::geometry::create_geometry_data(16, 16);
let geometry = nodarium_utils::geometry::wrap_geometry_data(&mut geometry_data);
// bottom circle
for i in 0..8 {
let x = radius * (2.0 * std::f32::consts::PI * i as f32 / 8.0).cos();
let y = radius * (2.0 * std::f32::consts::PI * i as f32 / 8.0).sin();
let vec = Vec2::new(x, y).normalize();
// bottom circle
geometry.positions[i * 3 + 0] = x;
geometry.positions[i * 3 + 1] = 0.0;
geometry.positions[i * 3 + 2] = y;
geometry.normals[i * 3 + 0] = vec[0];
geometry.normals[i * 3 + 1] = 0.0;
geometry.normals[i * 3 + 2] = vec[1];
// top circle
geometry.positions[24 + i * 3 + 0] = x;
geometry.positions[24 + i * 3 + 1] = height;
geometry.positions[24 + i * 3 + 2] = y;
geometry.normals[24 + i * 3 + 0] = vec[0];
geometry.normals[24 + i * 3 + 1] = 0.0;
geometry.normals[24 + i * 3 + 2] = vec[1];
geometry.faces[i * 6 + 0] = (i + 8) as i32;
geometry.faces[i * 6 + 1] = (i as i32 + 1) % 8;
geometry.faces[i * 6 + 2] = (i) as i32;
geometry.faces[i * 6 + 3] = 8 + (i % 8) as i32;
geometry.faces[i * 6 + 4] = 8 + (i as i32 + 1) % 8;
geometry.faces[i * 6 + 5] = (i as i32 + 1) % 8;
}
nodarium_utils::concat_arg_vecs(vec![geometry_data])
}
```
As you can see we import `glam` on the first line. Glam is a fantastic math library. Install it with the following command:
```bash
cargo add glam
```
## Build time
We compile our node by running the following command:
```bash
wasm-pack build --release
```
This will produce a `.wasm` file in the `pkg/` directory of our node. To check if the node works, we can drag it onto the node-graph on https://nodes.max-richter.dev and see if it loads.

38
docs/NODE_DEFINITION.md Normal file
View File

@ -0,0 +1,38 @@
# Node Definition
Which arguments a node expects is defined in a single `.json` file that is embedded into our node. It consists of three main fields:
## id
`user-name/namespace/node-id`
## outputs
```json
"outputs": [
"geometry"
]
```
## inputs
```json
"inputs": {
"height": {
"type": "float",
"value": 2
},
"radius": {
"type": "float",
"value": 0.5
}
}
```
## meta (optional)
The meta object is optional and can contain two other fields:
`title`
`description`

View File

@ -30,12 +30,11 @@
},
"offsetSingle": {
"type": "float",
"hidden": true,
"description": "Used to offset every second branch",
"min": 0,
"hidden": true,
"max": 1,
"step": 0.01,
"value": 0.5
"value": 0
},
"lowestBranch": {
"type": "float",