Initial Spatial Lab release with verified Blender bridge

This commit is contained in:
emil28092005
2026-09-17 16:59:32 +03:00
commit 60d0018fa9
30 changed files with 58238 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
# Spatial Lab design
The author is an agent operating through Python and a CLI. The browser is an observation surface, not a manual modeller. The primary artifact is an editable construction graph; the derived bundle is the exact geometric handoff to Blender.
The viewer uses a cool drafting surface (#e9eef3), ink (#213348), quiet guides (#bccbd7), geometry blue (#668aa6), and a selection amber (#d18b42). System sans-serif carries navigation; fixed-width numerals and formulas use monospace. A narrow construction outline sits beside a large geometry viewport. A compact inspector shows the selected operation and its parameters. Controls only change observation: orbit, projections, visibility, section height, and wire/surface mode. Geometry never mutates through the viewer.
The visual emphasis is the construction itself. There is no marketing header, ornamental dashboard, animation, or material editor. Graph relationships, axes, and units are functional markings. Node colour is semantic and stable, not random decoration.
The kernel contains a versioned operator registry, bounded arithmetic evaluator, dependency-ordered graph execution, rotation-minimizing frames, triangulated geometry, structural validation, and deterministic content hashes. The project layer adds transactional edits and persistent undo/redo. No network service or third-party Python dependency is required to build geometry.
The JSON bundle uses metres, a right-handed Z-up basis, row-major matrix arrays, and column-vector multiplication. Objects reference shared geometric data by content hash. Stable object IDs derive from node IDs and instance keys. The Blender importer owns only tagged objects, updates them in place, preserves existing modifiers and material assignments, and verifies the imported base mesh against the bundle.
Version 0.1 does not claim collision-free architecture, walkability, a general constraint solver, solid booleans, or non-Euclidean runtime behaviour. Structural mesh checks and transfer parity are implemented; spatial design remains an iterative agent task.
+49
View File
@@ -0,0 +1,49 @@
# Spatial Lab JSON contract, version 1
## Editable project: `spatial-lab.project/1`
```json
{
"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.