Files
spatial-lab/docs/FORMAT.md
T

3.8 KiB
Raw Blame History

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.