Prepare Project
Place .json file exported from app.nodi3d.com
Install
nodi-modular is available via npm:Copy
npm install nodi-modular
"nodi-modular"
Copy
import init, { Modular } from "nodi-modular";
Usage
- JS
- React
Copy
import init, { Modular } from "nodi-modular";
// Initialize the WebAssembly module
await init();
// Create a new instance of the Modular
const modular = Modular.new();
// Load a node graph in JSON format as a string
modular.loadGraph(JSON.stringify({
nodes: { ... },
}));
// Evaluate the node graph to get the result
const result = modular.evaluate();
// Geometry identifiers are the keys of the geometries in the result
const { geometryIdentifiers } = result;
geometryIdentifiers.forEach((identifier) => {
// Get the geometry variant by identifier
// variants are curve, surface, mesh, and etc.
const geometry = modular.findGeometryById(identifier);
// Get the geometry interop by identifier
// geometry interop has the data that can be rendered as a polygonalized data (polyline or triangle mesh)
const interop = modular.findGeometryInteropById(identifier);
});
// Get the nodes of the node graph
const nodes = modular.getNodes();
// Find the node by the variant and label
const numberOfGrid = nodes.find((n) => n.variant === "Number" && n.label === 'number of grid');
// Each nodes have the properties that can be changed
// What properties can be changed depends on the node variant, so you need to check the node variant's properties (numberGrid["properties"])
modular.changeNodeProperty(numberOfGrid.id, {
name: "value",
value: {
type: "Number",
content: 30,
}
});
// re-evaluate the node graph to get the result after the property change
const resultAfterPropertyChange = await modular.evaluate();
Copy
import init, { Modular } from "nodi-modular";
.
.
.
const [modular, setModular] = useState<Modular | null>(null);
const [nodes, setNodes] = useState<NodeInterop[]>([]);
const [geometries, setGeometries] = useState<BufferGeometry[]>([]);
const evaluate = useCallback(
(m: Modular) => {
m.evaluate().then((e) => {
const { geometryIdentifiers } = e;
const gs = geometryIdentifiers
.map((id) => {
const interop = m.findGeometryInteropById(id);
const { transform } = id;
switch (interop?.variant) {
case "Mesh": {
const { data } = interop;
const geometry = new BufferGeometry();
const { vertices, normals, faces } = data;
geometry.setAttribute(
"position",
new BufferAttribute(new Float32Array(vertices.flat(1)), 3)
);
geometry.setAttribute(
"normal",
new BufferAttribute(new Float32Array(normals.flat(1)), 3)
);
if (faces !== undefined) {
geometry.setIndex(
new BufferAttribute(new Uint32Array(faces.flat(1)), 1)
);
}
geometry.applyMatrix4(new Matrix4().fromArray(transform));
return geometry;
}
default: {
return null;
}
}
})
.filter((g): g is BufferGeometry => g !== null);
setGeometries(gs);
});
},
[]
);
.
.
.
useEffect(() => {
(async () => {
await init();
setModular(Modular.new());
})();
}, []);
useEffect(() => {
if (modular !== null) {
modular.loadGraph(JSON.stringify(shell.graph));
// modular.loadGraph(JSON.stringify(brickWall.graph));
const nodes = modular.getNodes();
const numberNodes = nodes.filter((n) => n.variant === "Number" || n.variant === "NumberSlider");
setNodes(numberNodes);
evaluate(modular);
}
}, [modular, evaluate]);