I have the first building destruction tests running in Wallhammer Web, my browser engine written in TypeScript and plain WebGL2.
Click a wall and you can open a hole into the building. Remove enough support and the floors, walls and roof above it come down. The pieces keep the geometry of the building they came from, including windows and roof sections.
Here is the current result. This is a raw development recording, about 55 seconds long, without audio:
There are still rough edges. Some falling pieces pass through each other, and the interiors are basic. But there is enough working now to explain how the engine makes those decisions.
A browser engine with graphics generated from code
Wallhammer Web uses strict TypeScript and WebGL2 directly. The engine generates its graphics from code, including geometry and textures. It does not load image assets. Its only runtime dependency is earcut, used for roof triangulation.
The wider engine already has cameras, shadows, weather, world streaming and a fixed-step simulation. The destruction scene is a small example built on top of it. A separate application uses the engine for a model of Ústí nad Labem.
I keep the content generators separate from the engine's rendering and simulation infrastructure. The architecture module generates buildings; the renderer receives meshes and materials. Vegetation and actors have their own content modules.
The import rules are checked in the repository. WebGL calls belong in the GPU module, browser APIs belong in the platform module, and generators return plain data without touching the GPU. The simulation can run in Node without a canvas.
That last boundary is useful for destruction: deciding which parts remain standing does not require rendering a single frame.
A building is a collection of parts and connections
The generator produces a structure description alongside the visible mesh. It contains parts such as foundations, wall sections, floor slabs, partitions and stairs, plus connections between them.
Each part has a stable key derived from the recipe, a convex shape and a material. A connection records whether one part rests on another or is tied to it laterally. Foundations can be marked as anchors and indestructible.
Damage has four states: intact, cracked, breached and gone. A breach in a wall exposes the interior, with geometry around the opening. A part that is gone leaves cut faces and rubble.
When a destruction event arrives, the model finds parts within its radius and compares the damage against material thresholds. The damage falls off with distance. Seeded variation keeps the thresholds from being identical for every part while preserving repeatability.
Then it checks support. A part needs a supported path back to an anchor, subject to a limit on lateral support. Removing a wall can therefore take down parts outside the original hit area.
This is a structural heuristic. It does not calculate physical stresses through every piece of masonry. The distinction matters when deciding what kind of collapse to expect from it.
The result is final before the pieces finish falling
The destruction model works with integer centimetres and seeded hashes. Given the same structure, starting state and events, it produces the same damage state.
For an existing array of structure descriptions, the call looks like this:
import type { StructureDesc, StructureState } from 'wallhammer-web/base'; import { applyEventToAll, compileStructure, destructionEvent, } from 'wallhammer-web/sim/destruction'; declare const descriptions: StructureDesc[]; const compiled = descriptions.map(compileStructure); let states = new Map<number, StructureState>(); const event = destructionEvent({ position: [12, 4, 30], radius: 3, energy: 900, seed: 77, tick: 1, }); const result = applyEventToAll(compiled, states, event); states = result.states; The energy here is an abstract damage value, not a measurement in joules.
The model commits the new state immediately. It also returns a timeline describing when the removed parts should let go. Rendering uses that timeline to show the collapse over time.
That means a save taken halfway through a collapse contains the final damaged structure. A second hit during the animation acts on that final state too. Falling fragments do not feed back into the damage model.
For the visuals, the engine cuts pieces from the building as it stood before the hit. Those pieces follow calculated trajectories, with dust on landing and rubble appearing beneath them. This is why a falling wall section still carries its windows.
What still needs work
The current collision approximation checks a falling piece against standing parts at only two points along its flight. It can miss a corner between those points. Pieces also do not collide with one another, so a large roof section can pass through falling walls.
The interiors have slabs, partitions, doors and stairs, but the layouts repeat between storeys and the rooms are empty. Opening a building makes those shortcuts much easier to see.
There is also a practical rendering cost: after a hit, the engine needs the old geometry to extract falling pieces and new geometry for the damaged structure. The city application spreads that preparation across tasks and caches structure descriptions. The state changes immediately; the picture follows once the replacement meshes are ready.
For now, this video is a first look at the destruction system. The next useful improvements are clearer collisions between falling pieces and interiors that hold up when an entire side of a building disappears.


