Repository navigation
Castle
extensions/castle/ builds a moated brick castle from a plan. It draws the castle with brick, slate, water, lawn and woods under the sun of a date and an hour. The extension ships the plan of Wijnendale Castle at Torhout in West Flanders, Belgium. Each figure of a plan says how it was found. The page Castle analysis holds the engineering checks that read the same plan. The page Landscape stands the castle in mountains and woods, with a scanned church beside it.

The picture comes from examples/wijnendale.mojo. It takes about half a minute on 24 CPU threads. The sun is where it stands over Torhout at 15:00 local time on 19 October 2026. The moat is Clearwater's water, and the castle and the wood are reflected in it. The same castle is a scan of 3.65 million splats in Virtual scans. That scan draws in milliseconds and can be walked through.
.venv/bin/mojo run -I . examples/wijnendale.mojo out/wijnendale.png| Module | What it gives |
|---|---|
castle/kinds |
Material, RoofKind and Provenance, each a type with is_valid
|
castle/plan |
CastlePlan, Tower, Wing, Gate, QuayWall, Moat, Bridge and the point and band tools |
castle/wijnendale |
wijnendale_plan, the survey's footprint and the castle's place |
castle/masonry |
Masonry and historic_brick, the strength and stiffness of brickwork by EN 1996-1-1 |
castle/parts |
Walls with windows cut through them, plinths, crowns, dormers and spires, as triangles |
castle/render |
castle_meshes: the mesh view of a plan, one mesh for each material |
castle/textures |
Maps of brick, stone and slate from the real sizes of a unit |
castle/look |
castle_look: a physically based material for each surface |
castle/trees |
Trees grown from a branch skeleton, with cards of leaves, and shrubs |
castle/scene |
build_castle_scene, aim_sun and draw_castle
|
castle/sky, reflect
|
The sky and its clouds, and the mirror image in the water |
castle/sun, shadow
|
The sun over a site, and the shadows of the towers; see Castle analysis |
castle/landscape, landscape_mesh
|
The ground from the castle's meadow to the mountains, and its triangles; see Landscape |
castle/forest, crowns
|
The woods of a landscape by altitude and distance, and the crowns of far trees; see Landscape |
A plan is in a flat frame in meters, x east and y north of an origin that the plan names. Levels are meters above a datum. Every length is a Length64, every angle an Angle64, and every part carries a Provenance that says how its dimensions were found.
| Part | What it is |
|---|---|
Tower |
A round tower with a wall to a height and a roof over it: a spire or a crown |
Wing |
A band of constant width along an axis, with a gable roof whose ridge follows it. Its corners are mitered |
Gate |
A rectangular block with a flat top, at a heading |
QuayWall |
The wall that holds the island's earth at the edge of the moat |
Moat |
The water: an outline, a level and a depth |
Bridge |
A run of semicircular brick arches on piers |
CastlePlan.check refuses a plan whose parts do not stand together. footprint_overlap says how well the solids reproduce the outline that a survey gave: the area they share over the area they cover together.
Provenance is one of four kinds. A plan that relies on a figure can tell a survey from a guess.
| Provenance | Meaning |
|---|---|
SURVEYED |
From a survey: the outline of the building and of the moat |
MEASURED |
Fitted to survey data: a wing, the gate and a tower |
DOCUMENTED |
From a document |
ESTIMATED |
A guess from a photograph or from the style: the depth of the moat, the quay wall, the bridge's arches, the proportions of the roofs |
The Flemish heritage inventory (record 87491) and the history of the castle give the facts.
- About 1276 to 1278: Count Guy of Dampierre has a stone castle built. It is round and moated, with eleven half-round towers and a heavy gate tower.
- From 1833: the Matthieu family rebuilds the castle.
- 1877 to 1878: the Brussels architect Felix Laureys builds the pseudo-medieval gate tower with its crenellations. He extends the right wing with a round donjon.
- 1982: the castle becomes a protected monument.
The inventory gives no dimensions. The plan comes from open data of Digitaal Vlaanderen. See THIRD-PARTY-NOTICES.md.
- The outline of the building and the outline of the moat are from the Flemish large scale reference map, GRB. The building has 99 corners. The coordinates are Belgian Lambert 72. The moat outline is simplified by 0.25 m.
- The heights are from the Digital Height Model of Flanders II. It is a 1 m raster of the surface and the terrain from an airborne laser scan. The water surface is the flat 34.31 m that the scan returns over the moat.
- The towers are circles fitted to the arcs of the surveyed outline. The wings and the gate are the bands and the rectangle that best cover it. They reproduce 96 percent of the surveyed area.
The plan holds these parts: the donjon and seven turrets, the north and the south wing, the gate tower, the moat and the bridge. It also holds the low wall of the courtyard with its four quay towers.
castle_meshes(plan, default_view()) gives one geometry for each material: brick, stone, slate, water, lawn, gravel, foliage, glass, wood, metal and bark. A wall is a plate with the openings cut through it, so a window has a reveal as deep as the wall is thick. A window has a stone surround, a sill, a frame, a mullion and a pane set back in the opening. A round wall is a ring of plates, and a crown is a ring of corbels under a parapet of merlons. A wing has dormers, chimneys and a leaded ridge. The ground is a grid of heights: the bed of the moat, its banks, the island and the meadow.
The textures are procedural, and use the real sizes of a unit:
- A brick is 210 by 65 mm with a 10 mm joint, in running bond.
- A block of stone is 600 by 300 mm.
- A slate is 300 by 400 mm, laid with a 120 mm exposure.
The normals come from a height field that the same pattern makes. So a joint is a groove, and a slate has an edge that throws a shadow. castle_look gives each surface a metallic-roughness material.
var plan = wijnendale_plan()
var renderer = castle_renderer(800, 1000)
var castle = build_castle_scene(plan, default_settings(), eye_east, eye_north, 45.0)
aim_sun(castle, renderer, toward_the_sun) # a unit vector, y up and z south
var image = draw_castle(castle, renderer, camera, 0.55, 5)A picture is made in four steps.
- The renderer draws the scene with the sky as a prefiltered environment, and soft shadows from a lamp that stands where the sun does.
- The sky and its cumulus are painted where the renderer drew only the clear ground.
- The water of the moat is Clearwater's, composed into the picture where it is nearest.
- The castle and the wood are reflected in the water, in the share that Fresnel's law gives.
aim_sun redirects the lamp and prefilters the sky again. A low sun is dimmer and redder, because its light crosses more of the air. The woods are an illustration: the survey does not say where the trees are. They follow the photograph, a meadow open to the north, broadleaf trees close to the moat and dark conifers behind. No tree stands within a radius that the caller gives of a place, such as the camera.
SceneSettings trades quality for time. It sets the size of a tile of material, of the sky's cube and of the shadow map. It also sets whether the woods are grown, and the spacing of the ground grid. default_settings() gives 512 texel tiles, a 128 texel sky, a 4096 texel shadow map, woods and a 1 m grid.
- The plan has no interiors. A wall is a plate and the inside is not modeled.
- The openings are a regular pattern of the style, not a survey of the windows.
- A figure that is
ESTIMATEDis a guess. The roofs' proportions, the plinth, the depth of the moat, the quay wall and the bridge's arches come from a photograph. - The renderer draws in software, with supersampling and a shadow map. A picture takes about half a minute. To walk through the castle, draw its scan instead.
Tutorials
How-to
- Install
- Run the checks
- GPU backend
- Coverage
- Measure examples
- Add a feature
- Add a scanned building
- Write documentation
Reference
- Scene graph
- Rotations
- Cameras
- Geometry
- Geometry addons
- Lofts and clipping groups
- Sculptor
- Procedural generators
- Meshes and assets
- Lines
- Points and sprites
- Helpers
- Scene objects
- Animated objects
- Raycasting
- Curves and paths
- Animation
- Skinning
- Materials
- Node materials
- TSL functions
- Lights
- Lighting addons
- Fog
- Textures
- Renderer
- Renderer hooks and material flags
- Rasterization
- GPU backend
- Render target
- Post-processing
- GPU computation
- Compute nodes
- Progressive light map
- Gaussian splats
- Voxel global illumination
- SVG renderer
- Image files
- Image decode queue
- Model files
- More model files
- Exporters
- Scene JSON
- Windowing and controls
- C ABI and hosts
- Math
- Norm consumers
- Math addons
- Units
- Coverage tool
- Commands
- Examples
- Benchmarks
- Extensions
- Shared physics
- Physics query snapshots
- Continuous collision
- Tick force restoration
- Water
- Warp drives
- Vegetation
- Village
- Streamline
- Animals
-
Buildings
- Numerics
- Building topology
- Building model
- IFC exchange
- Procedural towers
- Floor plans and interiors
- Frame analysis
- Shell analysis
- Building energy
- Construction kits
- Bearing walls
- Scanned buildings
- SOG files
- Compressed PLY files
- Scan parts
- Cleaning and orienting scans
- Walking through a scan
- Virtual scans
- Castle
- CARLA
- Femur
- Tibia
- Fibula
- Patella
- Knee
- Muscles
- Vessels
- Lymph
- Nerves
- Integument
- Leg
- Foot
- Pelvis
- Torso
- Arm
- Hand
- Head
- Genome
- Game humanoid
- Humanoid fidelity
- Mixamo animations
- Audio-aligned game faces
- Converted assets
- Mesh quality
- Garments
- Outfits and armor
- Cloth and spring bones
- Attire estimates
- Segment inertia
- Process chemistry
- Thermochemical data
- Chemical equilibrium
- Process maps
- Rates and transport
- Electrolysis and film color
- Binary solutions
- Flowsheets and routes
- Materials and coatings
- Crystals and figures
Explanation
- Software rasterizer
- Scene graph as an array
- Linear color
- Normals are not colors
- Perspective correction
- Fixed-point coverage
- Per-fragment shading
- Mipmaps
- Sorted transparency
- Types and checks
- Render hooks as a trait
- Shared CPU and GPU code
- Bands and threads
- PNG structure
- Extensions beside the port
- Process temperatures
- Scans as building models
- CUDA teardown hang
- Mojo compiler hang