feat: add some documentation
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 2m9s
All checks were successful
Deploy to GitHub Pages / build_site (push) Successful in 2m9s
This commit is contained in:
parent
94f39bac8e
commit
f4853821d4
@ -1 +0,0 @@
|
||||
# Developing Nodes
|
@ -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
|
||||
|
@ -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
128
docs/DEVELOPING_NODES.md
Normal 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
38
docs/NODE_DEFINITION.md
Normal 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`
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user