Implement, populate, edit, compose, or validate SimpleGL XML scenes and prefab XML files from an approved visual room design or direct scene request. Use for room layout, walls and openings, window or door inserts, furniture placement, set dressing, materials, lights, cameras, groups, primitive selection, transforms, prefab authoring, design-coverage audits, and diagnosing sparse, misplaced, floating, intersecting, incorrectly oriented, or incorrectly scaled scene objects.
Implement, populate, edit, compose, or validate SimpleGL XML scenes and prefab XML files from an approved visual room design or direct scene request. Use for room layout, walls and openings, window or door inserts, furniture placement, set dressing, materials, lights, cameras, groups, primitive selection, transforms, prefab authoring, design-coverage audits, and diagnosing sparse, misplaced, floating, intersecting, incorrectly oriented, or incorrectly scaled scene objects.
Populate SimpleGL XML Scenes
Build scenes in stable local coordinate frames and verify them with CLI checks and tests.
Read the relevant references
Read references/scene-format.md for supported XML tags, attributes, defaults, rotations, modifiers, and prefabs.
Read references/shot-composition-guide.md whenever placing or revising cameras, and use it to define each shot's story purpose, framing, continuity, negative space, and field of view.
Read references/alone-in-the-dark-layout-study.md whenever planning a multi-room floor, fixed-camera coverage regions and handoffs, corridors, column rhythms, or stair traversal shots.
Workflow
Locate the approved visual room design and its canonical source brief for story-driven or reference-driven work. If either is missing, use the appropriate source adapter and $art-direct-room before implementation. Do not derive the full environment directly from raw story objects when a design brief is required.
Inspect the target scene, referenced prefabs, existing materials, brief inventory, state variants, priorities, and camera coverage matrix before editing. When explicitly rebuilding from scratch, retain the approved briefs and reusable generic assets only; do not copy the discarded scene's transforms, clusters, or composition.
Establish the room coordinate system, floor height, wall centers, local axes, spatial zones, circulation and story-action clearances.
Create the structural shell first: floor, walls, ceiling or roof, openings, architectural articulation, cameras, and lights. An interior room is enclosed unless the design explicitly calls for an open or roofless space.
Build hero furniture and large silhouettes before storage systems, prop clusters and accents. Give every hero a distinctive outer silhouette, secondary construction hierarchy, and story-specific detail; a generic box with an emblem is not a finished hero asset. Reuse a prefab when an object appears more than once or has a natural front direction.
Place related geometry in a shared <group> coordinate frame. Never duplicate a rotated parent's world-space transform by hand when a group can express it.
Keep all naturally grounded objects at the documented prefab baseline. Calculate primitive centers from half-height; do not guess vertical positions.
Populate every density pass named by the visual design while preserving its intentional rest areas and text zones. Fill visible drawers, cubbies, shelves, bins, racks, and under-furniture storage with plausible contents unless emptiness is deliberate and narratively legible. Do not use raw object count as proof that a room is sufficiently authored.
Audit every visible contact: joined assembly parts terminate cleanly against their supports, while unrelated objects retain deliberate negative space without accidental overlap or tangency.
Audit coverage: every CANON element and required initial state is represented, every hero/secondary design element reads in at least one intended camera, and any deliberate omission is documented. For story cameras, audit the actor/action/target as well as the environment: place one camera-scoped character dummy for each character who must appear, choose a readable pose aimed toward the interaction target, and never rely on a camera merely pointing at an empty object to imply the action.
Validate XML, build the project, and run the tests.
Load the scene with ./build/bin/scener --list-cameras PATH.blks and check its declared cameras.
When composition, lighting, or references are part of the request, render the affected cameras with ./build/bin/scener --render PATH.blks --camera CameraName --output-dir render/review, then inspect the PNG before accepting the edit. Review the result as an art-direction problem: identify generic hero silhouettes, empty functional volumes, weak upper-space occupation, flat front-on staging, repetitive prop rhythm, implausible scale, missing reference motifs, blocked actions, tangencies, and false grouping. Correct the scene and render again. Use -d 24 to hide lamp and character editor overlays. For every camera requiring a character, also render a blocking review with -d 8, which hides camera/lamp helpers but keeps character gizmos visible; confirm the correct actor appears once, at the correct support height, with a readable pose and gesture toward the focal target. Rendered review complements, but does not replace, CLI validation.
For every interior room, place at least one motivated practical or window light that casts readable shadows. Match visible lamp geometry to its light position, establish a clear key direction, and use weaker fill only where needed to keep important actions legible.
Correct every invariant violation found through brief coverage, coordinate calculations, XML validation, scene loading, screenshot review, or tests.
Render critique gates
Judge hero assets in close view and at thumbnail scale. Replace generic inherited assets when their silhouette, construction, or ornament does not express the room's identity.
Check practical-light reach against the floor, hero furniture, storage interiors, ceiling/rafters, and story props. A technically lit room still fails when upper space becomes a black void or lower storage collapses into silhouette.
Check open storage in its intended camera, not only in XML. Contents need readable color/value separation, depth layering, and enough scale to register.
Check low cameras for foreground takeover. Foreground framing should lead toward the hero; move or reduce anything that becomes the dominant mass by accident.
Calibrate camera height against the declared character height. A supposed tiny-character viewpoint placed at twice the character's height weakens furniture monumentality even when the geometry is correctly scaled.
Check traversal shots for both endpoints. Showing a ladder or mechanism is insufficient unless the takeoff, complete route, and recognizable destination read together.
Check actor/action/target completeness. A shot of an interactive object without the acting character is object coverage, not action coverage. Keep alternate poses camera-scoped so a shared scene never shows duplicate copies of one actor.
Check small canonical props for discoverability. First improve placement, opening, silhouette, and camera angle; then add a restrained motivated bounce/glint only when the physical staging still needs contrast.
Compare the render against the reference decomposition after every major pass and name what remains absent. Add missing architectural or occupational motifs selectively rather than accepting a valid but generic room.
Brief handoff
Treat the canonical source brief as factual authority for names, relationships, interactions, scale language and required states.
Treat the visual room design as authority for architecture, noncanonical furnishings, density, hierarchy, lighting, zones and camera intent.
Preserve the design classification of CANON, REFERENCE, INFERRED and ATMOSPHERE; noninteractive visual dressing does not need a game-parser object.
Implement the approved initial state unless the request names another state. Keep future state geometry feasible and document what remains unimplemented.
When a later explicit user direction supersedes an approved design decision, update the design brief before implementation and record the change in coverage. Never let a later coverage document silently override the design.
When a current scene conflicts with the briefs, correct the scene or record a deliberate renderer limitation. Do not silently weaken the brief to match existing assets.
Prefab architecture
Organize authored families with semantic subfolders: use prefabs/workshop/clock.blk or prefabs/workshop/desks/main.blk, never category or room prefixes joined into filenames such as workshop_clock.blk or desk_with_items.blk.
Keep generic undecorated construction in category folders such as furniture/, fixtures/, and items/. Put room-specific dressing and combinations under the room family.
Author furniture-with-contents, stocked shelves, dressed desks, and other meaningful object clusters as composite .blk prefabs that reference smaller prefabs. The scene should place the complete authored object, not rebuild its contents item by item.
Use scene-level groups only for relationships unique to room geography or story staging. If a cluster could move as one object or recur coherently, make it a prefab.
Preserve useful attach points on both base and composite prefabs so later state variants can relocate story props without dismantling the asset.
Declare scene-wide ambient light and background only as attributes on the root
element: <scene ambient="r g b" background="preset-or-rgb">. Never emit
<ambient> or <background> child elements. The XML parser accepts those
unknown nodes but ignores them, silently falling back to its defaults.
Color-space contract
Author every XML value that represents a visible RGB color in sRGB space,
using the same 0..1 values a color picker displays. This includes scene
ambient and background, material and shape color, light and sun
color, unlit emitters, and colored dummy/overlay geometry.
Do not pre-linearize, gamma-correct, square, or otherwise transform authored
color values. The renderer converts sRGB colors to linear values exactly
once at its input boundary, performs lighting in linear space, and relies on
the sRGB framebuffer to encode the final output for display.
Treat light intensity as a linear scalar, not a color. Never apply an sRGB
conversion to intensity or fold intensity into the XML color value.
intensity="2" supplies twice the linear light energy of intensity="1",
although the displayed pixel value is not necessarily twice as large after
lighting, clipping, and sRGB output encoding.
Treat positions, directions, radius, shininess, transforms, and every other
non-color number as linear data with no color-space conversion.
Keep light color channels normally within 0..1; use intensity for HDR
brightness above white. Use color="1 0.75 0.4" intensity="2", not
color="2 1.5 0.8" intensity="1".
Align the smallest dimension of a thin insert with the wall's local Z thickness axis.
Prefer a window or door prefab containing its own <bool-negative-box> so the opening and insert cannot drift apart. Match the outer frame extents to the cutter extents; inset only the pane or explicitly recessed pieces.
Keep inserts smaller than their opening only when visible construction clearance is intentional.
Treat a gap or penetration larger than 0.001 scene units as an error unless the design explicitly requires it.
Make structural and decorative members terminate deliberately. Bars, mullions, rails, legs, cords, and similar joined parts must meet their intended frame or support within 0.001; never leave endpoints floating visibly inside open space. For a member ending at a curved boundary, calculate the curve intersection at the member's full width instead of extending or shortening it by eye.
Distinguish physical assemblies from unrelated neighbors. Parts meant to function together may touch or visually overlap where construction requires it; separate unrelated fixtures, furniture, and decorations with readable negative space. Avoid silhouette tangencies, near-tangencies, and shadow mergers that make separate objects look accidentally grouped.
Evaluate spacing in both world space and the affected camera views. As a starting point, give unrelated neighboring silhouettes a visible gap at least as wide as the smaller object's nearby trim or structural member, then increase it when perspective or cast shadows close the gap.
Never overlap coplanar visible faces. OpenGL depth settings cannot reliably order surfaces at the same depth; resize or reposition the parts so their exterior faces occupy distinct regions. Adjacent parts may meet at a shared edge.
Prefer swapping box dimensions over adding a rotation when both describe the same axis-aligned shape in the current local frame.
Document the default front direction in every directional prefab's leading XML comment.
Orient prefab instances toward their intended target using the documented front direction; never infer it only from the prefab name.
Use for placing objects on prefab surfaces rather than manual vertical position calculations. The attached element inherits the instance's full world transform — its , , and are applied in the instance's local frame at the attach point. Objects placed on a rotated workbench automatically stay flat on the surface without the author needing to match rotations.
Required CLI validation
xmllint --noout scenes/scene.blks
xmllint --xpath 'count(/scene/ambient | /scene/background)' scenes/scene.blks
make
make test
./build/bin/scener --list-cameras scenes/scene.blks
./build/bin/scener --render scenes/scene.blks --size 320x240 --output-dir render/validation
Run xmllint on every edited scene and prefab. Use the actual target path in place of scenes/scene.blks. Treat parser errors, unsupported XML element warnings on stderr, unresolved materials or prefabs, build warnings, test failures, and invalid camera declarations as failures. Keep this technical gate distinct from the mandatory rendered-camera review; neither substitutes for the other.
The XPath count must print 0; any other value means scene-wide settings were
written as ignored child elements instead of root attributes.
Prefab rules
Keep prefab geometry centered around a useful placement origin, normally floor center.
Use semantic directory hierarchy instead of filename prefixes: workshop/clock, workshop/desks/main, and workshop/shelves/jars, not workshop_clock, workshop_main_desk, or workshop_jars_shelf.
Keep prefab materials externally resolvable by the containing scene.
State footprint, baseline, and front direction in the leading comment.
Declare <attach> elements on prefabs that have meaningful surface reference points (tabletop center, seat surface, shelf height). Name the primary work surface top_surface; use under_center, shelf_lower, shelf_upper, or edge_n/edge_s for secondary slots.
Define a shelf attach at the center of each usable shelf surface. Name them by tier (shelf_lower, shelf_upper). Treat edge anchors as separate, explicitly named slots rather than using an edge as the default surface anchor.
Keep a practical light, its unlit emitter, and its shadow-casting shade in one prefab. Verify transformed and scaled instances keep the point light inside the emitter and on the emitting side of the shade lip.
Put a wall insert's <bool-negative-box> and all visible frame geometry in the same prefab. Center the prefab on the desired opening, align its local Z with wall thickness, and make the cutter deep enough to cross the complete wall.
Use source= on <prefab> to specify the file; name= only when something references this instance via attach.
Use sanityIgnore="1" only for a documented intentional overlap that the proxy checker cannot model, such as a wall insert owning its cutter. Never exempt a hero, furniture assembly, traversal mechanism, or practical light merely to obtain a passing scene test; correct its placement or explain the exact checker limitation.
Verify a directional prefab's 0, 90, -90, and 180 orientation mappings numerically before using it repeatedly.
Prefer a prefab over copied groups so later corrections propagate to every instance.
Make visible storage believable. An open commode, cubby, shelf, drawer, bin, rack, or under-desk bay should contain grouped objects with varied scale, yaw, depth, and silhouette unless its emptiness is a deliberate focal statement.
Completion standard
Do not report a scene as complete until its source/design coverage is audited, its XML validates, the project builds, relevant tests pass, and the scene loads through the CLI. For an interior, also verify that every density pass in the approved design is represented, the shell includes its intended ceiling or roof, visible practicals own aligned prefab-local lights, emitter geometry is unlit and shadow-free, and every story camera has a readable focal subject with deliberate cast shadows. Report unimplemented state variants and any limitation that CLI validation cannot establish.
attach="name:slot"
pos
rot
scale
Put surface attach points at the usable surface center, not its front or side edge. Apply deliberate offsets in a shared local group, and keep each object's complete rotated footprint inside the support boundary with visible margin.
Make lived-in prop clusters irregular but authored: vary yaw, spacing, depth, and scale slightly instead of aligning every center on one axis. Keep the variation deterministic, preserve contact, prevent intersections, and do not tilt an object away from its support unless it pivots plausibly from a contact edge.
Use pivotOffset for hinged rotations (book covers, open drawers) instead of group nesting workarounds.
Use the <array> modifier for repeating geometry (books, shelves, stairs) rather than copy-pasting shapes.
Prefer built-in preset materials (wall, floor, wood, metal, glass) and backgrounds (midnight, dusk, neutral, black). Define <material> tags only for custom materials.
Close interior shells with a ceiling or roof at the wall-top elevation unless an opening is intentional. Keep overhead cameras below a visible ceiling or provide a deliberate non-production plan view.
Motivate every light with visible or implied scene geometry such as a lamp, window, fire, or doorway. Put a reusable practical's <light> inside its prefab so geometry and illumination share one transform.
Mark visible bulbs, flames, and other self-luminous source geometry unlit="1" castShadow="0". Place the point light inside that source volume and below any opaque shade or lamp body so the fixture does not block its own useful light.
Every scene object and architectural element must cast shadows (castShadow="1") unless it is self-luminous emitter geometry. Ceilings, floors, walls, furniture, and props all contribute to the stencil shadow volumes. The only legitimate castShadow="0" exceptions are: unlit light bulbs/flames, glass panes (which are opaque in fixed-function but conceptually transparent), shadow-catcher placeholder planes, and deliberately composited scene boundaries.
Give each room a dominant shadow-casting key light. Keep ambient light low enough for shape, but never leave the hero subject or interaction in featureless darkness; add a weaker motivated fill or rim when required for readability.
Aim directional exterior light through an actual opening. Use a 45–60 degree downward angle and offset it 15–45 degrees from the wall axis so cast shadows fall diagonally rather than parallel to walls. dir="-0.6 -1 1" gives ~45° down and ~30° horizontal offset; dir="0 -1.7 1" gives ~60° down. Never set the horizontal component to zero — that produces shadows aligned to walls, which reads as flat and uninteresting. Check that the ceiling and wall shell do not accidentally block the intended window-light path.
Treat a window as both a compositional subject and a lighting instrument, not background decoration. In at least one establishing or action camera, frame the window itself or its bright spill so the source of the key is legible. Place the window on the side of the hero work surface that the camera can plausibly see; a distant window behind the action often lights only an empty floor and contributes neither story nor depth.
Solve daylight placement against the hero surface before committing to the room layout. For a window-center ray p + t * dir (where dir.y < 0) and a tabletop at height h, use t = (h - p.y) / dir.y, then check the resulting X/Z point lands inside the tabletop footprint. Move the opening or adjust the sun direction until it crosses a prop cluster rather than bare floor. Window frames and mullions must cast shadows so this spill creates readable, crisp patterned shapes across the table and its objects.
When the camera must view a closed room from the outside, mark the camera-facing wall renderable="0" castShadow="1". It remains invisible while preserving correct interior shadow and light-blocking behavior.
Verify that traversal mechanisms (lifts, stairs, ladders) are positioned adjacent to their destination platform. The base should sit near the lower platform and the top should reach near the upper platform so a single shot can capture both ends of the traversal.
Make composite prefabs reference their component prefabs. A dressed desk owns its work clusters; a stocked commode owns its shelf contents; a lamp owns its emitter and light. Keep room XML focused on spatial relationships between these authored objects.