# Architecture: runtime, objects and applications

## Dependency direction

The reusable runtime is `engine/`, with its own `index.js`, internal `src/` and bundled `vendor/`. Every folder directly under `objects/` is a separately portable package. The application imports an engine API namespace and passes it to object constructors. The engine imports no objects, application code, tests or documentation. Objects have no imports outside their own package; this allows them to be moved independently.

```mermaid
flowchart TD
  App[Shell or another application] --> Engine[engine/index.js]
  App --> Objects[Selected objects/package/index.js]
  App -- inject API --> Objects
  Engine --> Core[Lifecycle, motion, spatial queries]
  Engine --> Services[Environment, terrain, water, lighting, effects]
  Core --> Three[Bundled Three.js]
  Services --> Three
```

`THREE` is the runtime's matching Three.js namespace. Avoid another Three.js installation or mixing differently versioned copies. Application choreography, flight handling, human activity schedules and UI belong in the application. They do not become dependencies of a reusable object.

## Lifecycle and resources

Engine owns rendering, scheduling, sizing and its listeners. `mount(factory)` creates a stage with Scene, Camera, ResourceScope and AbortSignal. An obsolete asynchronous stage cannot replace a newer stage. The factory returns fixedUpdate, update, configure, onPause and dispose hooks as needed. Fixed updates use a 60 Hz clock with a six-step catch-up cap; display interpolation preserves position and quaternion orientation.

ResourceScope releases owned resources in reverse order once. Explicitly owned modules detach their roots before residual graph cleanup. `ObjectState` provides root, properties, transforms, bounds, serialization and disposal. Packages wrap it in a local PortableObject base and add their class-specific behavior. `sharedResources` excludes deliberately reference-counted materials/textures from an individual object's graph disposal. Buildings share generated surface libraries within an injected API instance and release the library after the last owner.

Object animation does not imply physics. Person is a skinned articulated model; cloth, foliage and water have procedural visual deformation. Application-level contact targets and character poses are separate from a general articulated-body dynamics solver.

## Motion and spatial queries

MotionBody integrates world acceleration and local angular velocity. SpatialWorld supports swept spheres and segments against boxes, spheres, transformed static triangles and heightfields. Triangle contact considers faces, edges and vertices. Mesh colliders snapshot their world transform; remove and re-add after changes. Initial box/sphere containment and terrain penetration are handled; arbitrary triangle meshes are surface colliders.

A conservative X/Z hash grid selects nearby static colliders; vertical bounds and exact 3D narrow-phase tests still determine contact. Large objects/queries fall back to the full set. Box triangles are created lazily. Terrain enumerates local grid cells. The system is a reusable finite-world contact service, not a full dynamic rigid-body solver or a BVH for arbitrary million-triangle imported models. Applications own friction, lift, crash behavior and other response policies. The flight shell uses an approximate 7 m sphere around a representative fighter and simple thrust/steering with wind drift.

## Generated world and terrain detail

The default region is 8 km square with 320 base cells per side. A deterministic generator creates a river/lake, mountains, meadow/forest/rock/alpine/farmland classifications, a beach and a flattened airfield. It is an Earth-like scene, not geographic Earth data.

Heightfield sampling and collision use the exact triangles rendered. Detail patches refine selected areas; newer patches replace overlapping triangles and blend their boundaries to the preceding surface. Water reads a GPU snapshot of the base and up to four detail patches, newest first. Build terrain patches before creating terrain meshes, colliders and water. The beach uses local detail at 2.5 m or finer. This is finite local refinement, not streaming or runtime adaptive tessellation.

Vegetation uses shared instanced species/variants with detailed leaves nearby, simpler middle geometry and textured distant cards. Complementary fades and animated depth materials keep transitions and shadows consistent. Static instance transforms/colors are uploaded only when membership or fade changes. Camera-following grass appears near ground and fades out at altitude. The shell places 24,000 trees in irregular terrain-weighted woodland, with terrain, shore, farmland and structure exclusions.

## Shared environmental state

Environment owns Daylight, WindField and RainField. Stable wind uniform references are injected into foliage, grass, fabric and water; cloud advection and rain streaks use the same direction/speed/strength. The flight controller samples that field for drift. Applications may register additional layers receiving the same state. Each Environment is independent; there is no global weather singleton.

Presets change time, cloud cover, storm darkness, rain, fog and wind. A rain-front transition advances clouds before precipitation. Night reduces ambient/environment illumination and displays a procedural moon, stars and faint galactic band. This is an artistic parameter model rather than a meteorological or astronomical simulation.

Three nested shadow regions use snapped light-space centres and overlapping transitions. Materials receive local shader patches; global Three.js shader chunks remain unchanged. Matching deformation is required in visible and depth passes. Coverage is finite and fades at the outer boundary.

## Water and effects

WaterSurface uses one horizontal planar reflection and world-space layered normals. A refined shore rectangle supports small geometric waves; its border amplitude fades into the surrounding surface. Terrain depth provides shoreline clipping and shallow coloring. River is a separate descending ribbon with local flow shading. These are visual approximations, not fluid simulation.

PostFX owns HDR targets, bloom, depth-based contact shading and final color conversion. Its water alpha mask and distant-contact suppression prevent the original terrain banding defect. Keep these contracts when changing materials or render targets. Direct rendering remains supported with no pipeline.

## Consumer separation

`templates/starter` demonstrates engine-only height-aware movement and collisions. `templates/object-demo` demonstrates an application with only people and beach packages. Release/relocation tools assemble independent copies and check import/asset closure. The development project and its documentation can move without Sunjack; after an actual move, startup and browser checks must be repeated at the new location.

## Camera and controller ownership

Orbit camera math and standard gamepad sampling are reusable engine modules. Studio transforms, package actions, flight mappings and the controller help/status UI belong to the shell. A shell-owned input loop stays responsive during simulation pause; it invalidates rendering only when camera/actions change. No object package depends on controller hardware. See CAMERA_AND_CONTROLLER.md.
