Guide5 min read5 sections

Authored static model worlds

docs/AUTHORED_MODELS.mdSource updated 2026-10-24
Markdown
On this page 5 sections

World format 3 connects imported geometry to persistent authored entities, canonical ECS presentation, static collision and shared gameplay state. games/engine-zoo/model-world.ts is the independent two-place fixture. The default Darkwind player still uses its existing procedural content.

#Content contract

A world-3 document has a models dictionary of named glb-static.1 artifacts. Each placement uses mesh: 'model', model: '<catalog alias>', its existing persistent entityId, position/rotation/scale and material. A white material color [1,1,1] preserves the imported base colors; other colors tint them. Authored roughness and metalness override imported values when supplied. Imported RGB emission remains present, alongside any authored scalar emission. Procedural texture overrides are rejected.

asset-world.3 validates and owns the complete catalog before compilation. It deduplicates artifacts by SHA-256 and emits content-addressed asset keys, immutable identity/material/model tables and world-space collision triangles. Source aliases and placement belong to the world fingerprint; identical assets share geometry even under different aliases. Renaming or moving a placement retains its entity identity. Legacy worlds still use primitive-world.2, with unchanged content fingerprints.

The catalog admits at most 32 aliases and fits within the shared 16 MiB JSON envelope. Its conservative geometry budget is 16 MiB, counting both possible orientations of every unique primitive. Each place permits at most 4,096 expanded draw instances and 262,144 imported triangles. Traveler parts also consume the renderer's 4,096-instance runtime ceiling. Transformed model bounds and collision vertices must remain within +/-1,000,000. These limits are admission ceilings, not recommended scene sizes or demonstrated frame budgets.

#Authoring workflow

Use new output paths; the commands preserve existing files:

Terminal
mkdir -p authoring-output
npm run import:model -- games/engine-zoo/assets/lantern-plinth.glb authoring-output/plinth.model.json
npm run author -- import engine-zoo authoring-output/initial.json
npm run author -- attach-model authoring-output/initial.json plinth authoring-output/plinth.model.json authoring-output/with-model.json

attach-model submits a put-model transaction. It promotes a persisted world-2 document to world 3 without changing its object identities. Attachments alone do not create placements. Prepare an object with mesh: 'model', model: 'plinth', position, positive scale, material and optional collider: true using author prepare; then put that prepared object in a create transaction. Apply against the latest document's revision/hash and export or compile the resulting document through the existing authoring CLI.

The transaction API also supports remove-model and set with property model. Catalog changes, reference changes and placement edits validate together before publication. Removing a referenced alias fails; replacing every reference and removing the old alias in the same transaction succeeds. Invalid artifacts, stale revisions and oversized results leave the accepted document unchanged. Outputs can run through the bundled Node-only CLI outside the checkout.

#Collision and persistence

Imported colliders are native Rapier triangle meshes generated from selected node primitives, with composed placement transforms and reflected winding preserved. They follow the actual shape, rather than the artifact's conservative bounding boxes. Repeated placements have separate world-space collision meshes and shared render geometry.

These colliders are static. Motion, hinge and hide-with-item definitions are rejected on colliding imported objects. Runtime ECS edits cannot change their transform, parent or mesh asset: an authoring edit must compile and construct a new world so physics and presentation agree. Visibility and material changes remain separate rendering properties. Dynamic bodies and live collision replacement are still future work.

Simulation checkpoint profile 4 binds the asset-world.3 signature and retains the native mesh state. Restore reconstructs the matching content and validates the checkpoint before publication. Changing source content does not silently migrate an old checkpoint. Place travel constructs the destination's imported collision meshes.

#Presentation and graphics lifetime

PrimitiveAssets.create(compiled.assets) prepares both primitive and imported descriptions. Each imported entity expands into stable per-part draw IDs, sharing content-addressed oriented mesh handles. Incremental updates remove obsolete part IDs and preserve unrelated draws. Primitive-only envelopes remain presentation format 2; envelopes carrying imported handles or RGB emission use format 3. A stream can contain both, and a format-2 envelope cannot smuggle format-3 fields.

WebGPURenderer.replaceCatalog(world.models) prepares GPU geometry without adding independent overlay objects. Install it before accepting the ECS baseline. Baselines referencing unavailable handles and catalog replacements removing currently referenced geometry fail before publication. Replacement retains the existing 20-second deadline and 32 MiB accepted-plus-candidate buffer ceiling. Disposal and device loss release catalog ownership.

Player graphics creation and recovery both install the configured world's catalog before resuming presentation. The independent GPU probe verifies catalog reinstallation after actual device destruction. Default-player browser recovery continues to exercise its procedural catalog; the probe is the imported-catalog recovery evidence. Atomic live catalog-plus-world activation remains unimplemented.

#Shared worlds and verification scope

Trusted server callers can supply world to createRelay; omission retains Darkwind. The relay owns the world and pins the room's persisted content hash. There is no public world selector or remote asset fetch API.

tests/model-world.test.ts covers compiled catalogs, ownership, identity-preserving edits, exact native collision ray height, standing on the imported surface, full checkpoint restore, prototype-safe source names, invalid data and packaged authoring commands. tests/model-room.test.ts uses two real WebSocket clients and separate Simulations to verify shared material state, host handoff and rejection of a different content release against the same room storage.

The Engine Observatory worker exercises actual GPU geometry: authored moves, shared material changes, both place projections, exact checkpoint-frame restoration, missing-geometry rejection, referenced-catalog removal rejection, device loss/reinstallation and zero owned resources after disposal. The fixture projects seven draws in the gallery and four in the annex, sharing three oriented meshes and 2,592 geometry bytes. This is software-WebGPU evidence, not a physical-device performance claim or a two-browser imported-world player test.

Textures, skeletal animation, dynamic imported colliders, model-prefab composition, cached asset jobs, live release activation and the visual editor remain open. No full engine milestone is closed by this integration.

Source 12e8701 and its acceptance record retain 207 passing headless checks, the initial browser run (25 passed, one unexpected browser closure), and three passing follow-up repetitions of that interrupted case. The closure cause remains unproven. The worker report and desktop/narrow captures retain the rendered evidence.

End of Authored models