3.8 KiB
Spatial Lab JSON contract, version 1
Editable project: spatial-lab.project/1
{
"schema": "spatial-lab.project/1",
"id": "corridor-study",
"name": "Corridor study",
"parameters": {"length": 10},
"nodes": [
{"id":"axis","op":"polyline","version":1,"visible":false,
"params":{"points":[[0,0,0],[0,"length",0]]}},
{"id":"basis","op":"frames","visible":false,"inputs":{"path":"axis"}},
{"id":"deck","op":"sweep","inputs":{"frames":"basis"},
"params":{"profile":[[-1,-0.15],[1,-0.15],[1,0.15],[-1,0.15]]},
"color":[0.4,0.56,0.68],"role":"gallery"}
]
}
id identifies a project for ownership in the Blender adapter. Use a different project ID for independently managed studies in the same scene. Node IDs identify graph operations, never rename them during ordinary parameter edits. Version defaults to 1; visibility defaults to true. name, color and role are optional semantic presentation metadata. Parameters may be numbers or bounded arithmetic expressions. Dependencies are explicitly listed in inputs, as a node ID or list of node IDs. Cycles and missing references fail validation.
Evaluated bundle: spatial-lab.bundle/1
| Field | Meaning |
|---|---|
project_id, name |
Source project identity |
units, handedness, up_axis |
Always meters, right, +Z |
matrix_convention |
Row arrays, column vectors, local-to-world matrices |
recipe |
Complete original project for further editing |
project_hash |
SHA-256 of canonical recipe JSON |
nodes |
Evaluated node summaries, input links and parameters |
geometries |
Dictionary keyed by geometry hash; each value has vertices and faces |
objects |
Stable ID, node ID, kind, transform, semantic metadata and geometry reference/data |
bounds |
World-space axis-aligned min/max |
validation |
Mesh reports, warnings, and explicit flags for checks not performed |
stats |
Node/object counts, unique vertex/mesh counts, triangles including instances |
bundle_hash |
SHA-256 of canonical bundle JSON excluding this field |
Every vertex is [x,y,z] in metres. Every face is exactly three zero-based vertex indices with outward winding for solid meshes. Geometry hash covers the complete {"vertices":...,"faces":...} object. Mesh instances reference it through geometry; they do not duplicate vertex arrays.
Every object has id, node_id, name, kind, role, color and a 4×4 matrix. Its bottom row is [0,0,0,1]; matrices are invertible and orientation-preserving. Translation is in the last column. A local position becomes matrix * [x,y,z,1]. Colour has three normalized RGB components.
Mesh object IDs combine node ID and part key, e.g. braided-galleries/0000/main. A curve object instead embeds points and closed and uses ID NODE/path. Its points are joined in order, with the final-to-first edge added only for closed curves. Frames are individual objects of kind frame, with local axes in matrix columns and their origin in its last column; ID NODE/frame-0000.
Canonical JSON is the Python kernel's json.dumps(value, sort_keys=True, separators=(',', ':'), allow_nan=False) encoded as UTF-8. These integrity hashes are for reproducibility and accidental-corruption detection, not authentication. validate_bundle checks the supported convention, hashes, references, finite coordinates, transforms and triangle/edge structure before import. Bundles should be generated by build rather than assembled manually. A consumer only needs the evaluated geometry and matrices to reproduce the shape; it does not need the expression evaluator or custom operators.
Blender natively uses the same axis convention. Unity/Godot/custom-engine adapters must explicitly convert basis/units and triangle winding if their chosen basis changes handedness. No such engine adapter is included yet.