# Reusing the Brookside engine Units are metres, kilograms, and seconds; +Y is up. The engine is Three.js WebGL2 plus Cannon ES. It requires a modern browser with WebGL2. This release is a single-player local simulation; multiplayer authority, persistence, vehicle AI, interiors, and a level editor are extension work. ## Start a world ```js import { WorldEngine } from './src/engine/index.js'; import { brooksideScene } from './src/world/config.js'; const config = structuredClone(brooksideScene); config.id = 'my-game'; config.physics.maxDynamic = 80; const engine = new WorldEngine({ canvas, config, quality: 'balanced' }); await engine.load(); // geometry, collision, materials, sky, water, scenario, shader warmup engine.player.active = true; engine.start(); ``` The default scene is a reference implementation. Replace `buildScene(engine, config)` for another landscape; replace `scenario: {setup(engine), spawnProps(engine)}` for another game's objects. `materialFactory` and `waterRendererFactory` are injectable. `config.water` is passed to `WaterField`. The default water renderer's plane bounds and shoreline function are specific to Brookside: replace its renderer adapter when changing terrain. Do not change the CPU bed without matching the shader bed. To load another independent scene, dispose the current instance and instantiate/load a new one with its scene config and adapters. `engine.dispose()` stops animation, removes simulation listeners and bodies, and disposes owned scene textures, materials, geometry, reflection target and renderer. Share external GPU resources only through an adapter with an explicit ownership strategy. ## Spawn, hold, reset ```js import { C } from './src/engine/index.js'; const crate = engine.spawnBox({ position: [34, 2, -31], size: [1, .5, 1], material: 'wood', mass: 85, tag: 'delivery', }); crate.applyImpulse(new C.Vec3(0, 40, 0)); engine.reset(); // restores demo props and all original masonry engine.player.teleport(config.locations.brook); engine.setQuality('low'); // low | balanced | high ``` For physical vectors import `C` from the entry point and use `new C.Vec3(x, y, z)`; Three.js vectors and Cannon vectors are different types. `spawnBox()` pairs the body with a visible mesh. For custom shapes, create the Cannon body and call `engine.attach(body, material, geometry)`. `engine.physics.remove(body)` updates both simulation and render binding. `engine.held` uses a bounded damped spring, so held objects continue colliding with the scene. The default interface binds `engine.shoot()` to the current tool; a game can replace that input layer. `Explorer` handles keyboard, pointer lock, touch look, gravity-based movement, jumping, swimming and world-boundary recovery. The demo UI supplies the thumbstick. Direct position writes should be avoided; `teleport()` clears velocity and updates the collider. ## Fixed updates and game hooks ```js const uninstall = engine.use({ setup(e) { this.off = e.physics.on('demolition', event => console.log(event.broken)); }, update(dt, e) { /* render-frame game logic */ }, dispose() { this.off(); } }); const fixed = dt => { /* forces or authoritative local rules */ }; engine.physics.beforeStep.add(fixed); // Later: engine.physics.beforeStep.delete(fixed); uninstall(); ``` Physics hooks run once per fixed tick, before/after forces and contact resolution. Frame hooks run once per rendered frame. Do not apply a force from both hooks. Events include `spawn`, `remove`, `restore`, `fracture`, `demolition`, `splash`, and `reset`. See `examples/floating-delivery.js` for a complete tiny game extension with scoring, a physical delivery object, and cleanup. It runs on the same brook/physics without altering the engine. ## Independent simulation components `Physics`, `WaterField`, `Demolition`, physical material definitions, and terrain math are DOM-free and run in Node. Import their specific modules for headless use (the aggregate entry also exports the browser renderer). A renderer is not necessary for simulations or game rules. `Physics.box()` / `sphere()` creates reusable rigid bodies. Material definitions expose density, friction, restitution; mass can override density. `WaterField.sample(x,z,time)` returns surface height, normal, water velocity, local depth and wet status. `Demolition.add()` records chunks and foundation anchors; `connect()` builds the adjacency graph; `hit()` queues energy-based damage for the next fixed step. Call `reset()` to restore the original structure. ## Ownership map | Path | Responsibility | |---|---| | `src/engine/physics.js` | Fixed-step clock, rigid bodies, material definitions, buoyancy/drag, lifecycle budgets | | `src/engine/water.js` | Wave table, CPU sampling, generated GLSL wave terms, demo bed function | | `src/engine/water-renderer.js` | Shared-displacement water, Fresnel, reflection, surface detail | | `src/engine/demolition.js` | Collision damage, support graph, bounded dynamic fragments, restore | | `src/engine/player.js` | Physical explorer and desktop/touch look | | `src/engine/engine.js` | World lifecycle, rendering, bindings, plugins, quality and timing | | `src/world/config.js` | Scene description, spawns, houses, budgets and quality presets | | `src/world/neighborhood.js` | Original architecture, terrain, vegetation, collision proxies | | `src/world/scenario.js` | Replaceable demo props and destructible outbuilding | | `src/world/materials.js` | PBR materials and original procedural detail textures | | `src/world/batch.js` | Static geometry merging by material and spatial cell | | `src/main.js` | Demo UI, location shortcuts and user input binding |