Stress Test — 1M Elements in a Single Federated Session¶
Status: RTree GPU path + Cockpit UI + Smart Overnight Bake — DONE S186.
Sandbox: scripts/sandbox_1M.db (1,061,736 elements, 29 real buildings)
Builder: scripts/build_sandbox_1M.py
Library: library/library.blend (120,471 meshes, 276 MB, shared all buildings)
S186 result: Background parallel Blender sessions (up to 4 instances) can resolve a full 1-million-element city in under 10 minutes at ~75MB total file size. Previously trended to 3.5 hours with save crashes. Terminal (48K elements) bakes in 36.6s. Hospital (63K) in 123s. Each building bakes in a fresh empty scene — no O(n) scene graph penalty. Linked mesh refs to library.blend keep files small. Smart Overnight auto-detects when offline bake is 5x faster and offers to switch — viewport stays fully interactive during the background bake. See
docs/RTree.mdfor full architecture, benchmarks, and proof.
Goal¶
Load 1,000,000 BIM elements into Blender with interactive viewport performance. All geometry is real — extracted from 29 IFC buildings, tiled into a city layout.
The Loading Problem¶
The Library button (S174) creates one Blender object per element. At 1M elements: - 1M objects in Outliner (unusable) - .blend save writes 1M objects (huge file, minutes to save) - No camera-distance LOD (every element rendered equally) - Instance creation: ~800 objects/s → 20+ minutes to load
The Solution: RTree GPU + Stingy Mesh Loader¶
Earlier Approach — GN Mode (S175–S184, halted)¶
Geometry Nodes (GN) were explored as the instancing layer: one point cloud per
discipline, Instance on Points picking meshes by hash_index. At small scale
(7K meshes) this loaded in under 2 seconds. At city scale (500+ modifier trees)
GN evaluation overhead reached 8 minutes — unviable. DLOD (distance-based
LOD swaps) and progressive make_local() were implemented to mitigate, but the
root cause — GN re-evaluating the full tree every frame — could not be fixed from
Python. GN Mode was halted at S184.
See internal/GN_LINK_INVESTIGATION.md and internal/DLOD_SPEC.md for the full
investigation archive.
Current Solution — RTree GPU Path (S184+)¶
The RTree Query Engine resolved the speed problem by eliminating mesh loading entirely from the default viewport:
DB (1M elements, SQLite R-tree index)
↓ O(log n) spatial query
RTree GPU — 1M wireframes, 13s load, instant orbit, zero mesh in RAM
↓ drill-down (click building → fly)
Stingy Loader — exact IFC geometry on demand, <1s per MESH press
↓ SHRED when done
Smart Bake — background Blender, 36s/48K, 4-core parallel, 1M city <10 min
- Zero Blender objects in the default view — GPU line batches drawn directly
- On-demand mesh via Stingy Loader: viewport-centre query, pre-warmed library
meshes linked from
library.blend, one named collection per MESH press - LOAD / SHRED is non-destructive — load geometry to inspect, shred to clean up
- Smart Overnight Bake (S186): background subprocess, fresh scene per building, no O(n) scene-graph penalty. Linked mesh refs keep files at ~2MB per building
See docs/RTree.md for the full architecture, benchmarks, and proof.
City Layout¶
Built by scripts/build_sandbox_1M.py from 29 real extracted buildings:
CBD strip (13 buildings): - Hospital ×2 (63,917 each), Terminal (48,428), LTU_AHouse (4,785) - HospitalGarage ×2, Clinic (16,480), 6 office buildings - Total: 221,386 elements
Suburb rows (51 rows × 18 house types): - Duplex, SampleHouse, BimWhale variants, Schependomlaan, etc. - 16,544 elements per row - Total: 843,744 elements
Grand total: 1,065,130 elements
Measured Performance¶
RTree GPU Path (current — S184+)¶
| Metric | Value |
|---|---|
| Wireframe load (1M elements) | 13s |
| Orbit / pan | Instant (60 FPS) |
| MESH press (viewport-centre) | <1s |
| Terminal bake (48K elements) | 36s |
| Hospital bake (63K elements) | 123s |
| Full city bake (1M, 4 cores) | <10 min |
| Blender objects in default view | 0 |
GN Mode (historical — S175–S184, halted)¶
| Metric | GN link=True | Per-element link=False |
|---|---|---|
| Mesh load | 1.74s | 37.05s |
| Instance/GN build | 0.05s | 57.47s |
| Total load | 2.19s | 64.08s |
| Outliner items | 6 | 48,428 |
| Viewport | Frozen (8-min GN eval overhead) | 60 FPS |
GN was fast to load but froze on evaluation at scale. RTree eliminated the problem by not loading meshes at all — wireframes from the spatial index, mesh on demand.
References¶
- RTree.md — primary viewer architecture, benchmarks, proof
- DLOD Spec — distance LOD handler design (GN era, archived)
- Full Loader 2 SRS — master loader spec
- GN Link Investigation — link=True vs link=False analysis (archived)
scripts/build_sandbox_1M.py— city builderscripts/pipeline_library.sh— extraction pipeline- MANIFESTO.md §The Backend — architecture philosophy: OS-level parallelism, compile-once, linked .blend
Copyright (c) 2025-2026 Redhuan D. Oon. MIT Licensed.