A gothic hall interior drenched in lantern light, latticework walls glowing amber and blue, a staircase climbing through the middle
Baseline / selfie-stick / part 2 · field notes

Standing where the builders stood

Part one taught arithmetic to fly a drone. This one brings the camera down to eye level — into the halls, onto the thrones, out to the gates — and then has to teach the judging what a wall is.

Gothic Ruin · 21,464 pieces · hall vantage · sunset 0.71 · aesthetic 6.23
What came out

The pictures first, again

Same rule as part one: everything below this is machinery. These frames were composed from a save file's furniture — a camera standing in a doorway, sitting in a chair, posted up on a courtyard flagstone. No human framed any of them.

Luminous Temple · gate_stor
Luminous Temple · gate_stor5.95
Floating Dock · court_sunse
Floating Dock · court_sunse5.91
Winter Cabin · 6,077 · seat_stor
Winter Cabin · 6,077 · seat_stor5.83
Pirate Haven · 5,928 · toproom_sunrise
Pirate Haven · 5,928 · toproom_sunrise5.51
court_nigh
court_nigh
Forest Hideaway · 1,986 · seat_nigh
Forest Hideaway · 1,986 · seat_nigh5.30
A storm over a gatehouse, a courtyard at dusk, a seat by the fire, a top room at dawn, battlements under stars, a barrel cellar at night. Five vantage kinds, four skies. The camera is at human eye height in every one.
The ask

Down from the drone

Part one ended with 1,411 photographs, all of them taken from the air: four bearings around each build, forty degrees up, far enough back to frame the whole box. Good photographs of buildings. But nobody who built these places ever saw them that way. They saw them from the hall floor, from the head of the table, from the gate coming home at night.

So the brief for this round was specific: the main room. The highest room with the biggest window. A chair, at a table. The main gate. The courtyard. And each of those through four skies — sunrise, sunset, a clear starry night, and a raging storm.

from the air · part one’s framing
from the air · part one’s framing5.88
from the hall floor · sunrise
from the hall floor · sunrise6.21
The same structure twice. Left: the drone's version from part one. Right: standing in its hall at sunrise. Readers of part one have met this build already — it is the 21,000-piece cluster whose record got printed as the sample. The record now has an inside.
Framing

The save file knows where every chair is

An orbit needs one fact per structure: its bounding box. An interior shot needs to know what a room is, and the box cannot say. But the save can. Every placed object in the world is a record with a position and a prefab id — every chair, every table, every gate hinge and every torch. The analytics cache had been storing them all along; nothing had ever asked.

One of part one's open items closed itself here. Prefab names used to be opaque hashes; a committed in-game dump of the prefab table now resolves 99.6% of 9.1 million objects to names at parse time. Once pieces have names, a vocabulary falls out: seats and tables, gates and doors, windows, fires, floors, roofs, walls. Group the floors into half-metre elevation bands and you have storeys. Grid the roof pieces and the cells with nothing overhead are courtyard candidates.

hall the floor band with the most floor under it, sweetened ×1.5 if a fire burns on it toproom the highest band 4 m above the hall with a window attached; aim into the light seat a chair with a table in reach; sit in it; look across the table, not at it gate the gate nearest the box edge at ground level; torch-lit gates win 6 m of slack court the largest open-sky patch walled on three sides; stand at its edge, look across Five recipes, all computed from furniture positions. A build that has no gates gets no gate shot — a skipped vantage with a reason beats a camera in a wall.
inside — one floor bandthe hall bandfirehallwindowtoproomaim into the lightseattableseatlook across the table, not at itno rotation in the save — a chair aims at what it is nearoutside — gate and courtthe build’s footprintgategate cam8 m out, aimed at the hallopen sky, walled on 3 sidescourtskips are loud: a build with no gates gets no gate shot
Where the five cameras stand, in plan. The save stores no rotation for furniture, so a chair's facing is unknowable — every seated shot aims at what the seat is near instead: the table, the fire, the hall. Which is the better photograph anyway.
Perspective

Eye level is a measured number

The plan file grew one column: mode=interior, a fourteenth field that older builds of the plugin simply never read. Inside the game it changes two things. The ground clamp — which keeps an orbit camera out of hillsides by forcing it two metres up — relaxes to twenty centimetres, because two metres of "safety" puts an indoor lens at the ceiling. And occlusion recovery turns off: outdoors it climbs the camera out of foliage, indoors every rescue is a teleport through the roof.

Then the receipts corrected the constants. The planner had assumed the lens rides 1.5 m above the player's feet; the receipts measured 1.8 m, frame after frame. Every standing camera in the pilot was composed three-tenths of a metre too high, which is the difference between a room and the underside of its ceiling joists. Assumed, then measured, then fixed — the same lesson part one learned about golden hour.

The throne that threw the camera

The first seated shots put the camera exactly at the chair's position. For plain chairs that worked. For thrones, the lens spawned inside the throne's own collider, and the engine's camera-collision resolved the disagreement by hurling the view seventeen metres into the air. The receipt is what caught it: the planner asked for a seat, the lens reported back from the sky.

shotplan-receipts.jsonl — the seated shot, first attempt. Three positions per frame is the whole audit trail.
{
  "shot": "seat_storm", "mode": "interior", "clearance": "planned",
  "planned": { x: ···, y: 41.99, z: ··· },  ← the seat of the throne
  "placed":  { x: ···, y: 41.99, z: ··· },  ← the engine agreed
  "lens":    { x: ···, y: 58.42, z: ··· },  ← the camera did not
  "lens_offset_m": 17.106              ← supposed to be ~1.8
}

The fix is thirty-five centimetres: spawn the camera just forward of the backrest, toward whatever the seat faces. The first attempt at that fix overshot to seventy — and produced a macro photograph of the far edge of the table. Composition at half-metre scale is a different sport than composition at a hundred metres.

thrown 17 m by the throne
thrown 17 m by the throne
slab · center_block 0.66
slab · center_block 0.66
walled into a grotto
walled into a grotto
Three ways a seated camera fails, left to right: thrown seventeen metres by a throne collider; jammed against a crystal slab (center_block 0.66); walled into a rock grotto. Every one was caught by a receipt or a depth map, not by a person scrolling.
A barrel-lined cellar at night, warm lamps on the right, a lit doorway glowing at the far end of the hall
Forest Hideaway · 1,986 · seat_night · aesthetic 5.30 — the seated shot, working: forward of the backrest, 1.4 m lens, aiming across the room instead of down at the furniture. Depth reads it as layered (center_block 0.17): barrels near, hall middle, lit doorway far.

Two more corrections rode along. The rig now runs in god and ghost mode, set by reflection at the start of every shot — courtyards have wolves, and a death mid-plan costs a respawn wait and puts a freshly visible corpse-run character in frame, because the hide-player toggle binds to the body that died. The operator spotted that one live, watching a run: a pink-armoured figure photobombing a courtyard at dawn.

Light

Four skies over one hall

Part one measured golden hour and clamped every exterior frame into the band 0.33–0.77 of the day, because outside that band facades go dark. That rule is an exterior rule, and this round deliberately breaks it. A starry night is the whole point of a night shot; an interior carries its own hearth light. The night value did move once — 0.97 came back black even outdoors, 0.90 keeps the stars and the last of the sky — and storm stayed on the value the old manual sweeps had already proven.

sunrise · 0.29
sunrise · 0.296.21
sunset · 0.71
sunset · 0.716.23
night · 0.90
night · 0.906.01
storm · 0.58
storm · 0.586.11
One hall, one camera position, yaw 135.79°, pitch 2.86°, fourteen metres across the room. Nothing moved but the sky: sunrise 0.29, sunset 0.71, night 0.90, thunderstorm 0.58.
Judgement sharpening

Teaching the judging what a wall is

The aesthetic model that ranks these frames was borrowed — a CLIP encoder and a small LAION head that were on the machine for an unrelated photo library. Indoors it faced new ways to fail, so the question was asked properly: is the borrowed scorer actually any good here?

Twelve pilot frames were labelled by hand — six keepers, six duds — and four scorers were benchmarked on all thirty-six keeper-versus-dud pairs.

ScorerPairs right
LAION aesthetic head (the incumbent)36 / 36kept — the borrowed scorer was never the problem
Same, HUD cropped out first35 / 36text in frame turns out not to matter at model resolution
CLIP zero-shot text probes35 / 36no better, and another thing to tune
7B vision model, 1–10 rubricsee below
The incumbent separated every keeper from every dud. Its real ceiling is subtler: the starry-night battlements — one of the best frames of the pilot — was its lowest-scoring keeper. It will keep a dark frame out of the reject pile, but it will never champion one.

Depth is a measurement, not an opinion

The sharpest question in this round came from the operator, watching frames come in: is this image mostly a tree branch — or is the subject behind the branch, so the branch adds a layer of depth? That is not a taste question. It is a geometry question, and geometry can be measured.

Every frame now runs through a monocular depth model, and the depth map is asked the questions a photographer would ask: is there a visible background? Is something near-depth sitting across the eye-line, or hugging the frame edges as a framing device? How many distinct depth layers hold real pixels?

one frame, as the depth map reads itoutside the dashes: edge_frame — near mass here frames the shotbottom band — exempt: a table edge or barrels here is compositioncenter_blocknear-depth pixels here =a wall across the eye-linemeasuredcrystal slabcenter_block 0.66 → vetoedbarrel cellarcenter_block 0.17 → keptveto: center_block > 0.45fired on 2 duds, 0 keepers
The blockage box is the upper centre on purpose. Foreground mass at the bottom of a frame — a table edge, barrels, the ground — is how layered photographs are built; the same mass across the eye-line is a wall the camera is stuck against.
center_block = share of near-depth pixels in the upper-centre box edge_frame = share of near mass hugging the border (framing, good) depth_score = far_mass × (1 − center_block) × span × framing_bonus veto: center_block > 0.45 → frame excluded, whatever its aesthetic On the labelled set the veto fired on exactly the two geometric duds and zero keepers. As a ranker on its own it is a coin flip — deep but unlit rooms score high on geometry and fail on light. The two signals are complementary, and neither replaces the other.

The judge that said 8.0 eighty times

The plan was a three-layer bench: aesthetic to filter, depth to veto, and a local 7B vision model as the final judge, reading each frame against a rubric — does this feel like standing in the scene? The model ran. It returned its verdict on all eighty frames it was shown: 8.0. Every single time. Same number, near-identical sentence. Small vision models compress absolute scales into a single polite answer, and an instrument with one reading is not an instrument.

The honest fix is already known and not yet built: ask the model to compare two frames rather than rate one — pairwise verdicts survive scale compression — and give the job to bigger eyes. The judging column ships in the data today, labelled for what it is: a reason-generator with a constant attached.

One more thing changed shape here. The thresholds above stopped being constants in a script and became sliders: the whole bench now lives in a reactive notebook where the frames ride inside the sortable dataframe — reorder by any instrument and the pictures reorder with it. That idea arrived as a tip from a reader of part one. Wheels were not rebuilt.

436 / 436frames planned / captured
25structures entered
109vantages derived
3pilot iterations first
36 / 36labelled pairs the filter got right
8.0 × 80what the judge said, every time
Forty-eight frames sampled evenly across the ranked interior corpus — best at top-left, weakest at bottom-right. The pile is real: plenty of duds. The point of the instruments is that nobody has to scroll past them.
Still open

What this does not do yet

  • The judge needs eyes and a sparring partner. Pairwise comparison instead of absolute scores, on a model big enough to have opinions. The hardware for that exists locally; the harness does not, yet.
  • Windows that are holes. Plenty of builds glaze nothing and leave openings instead. The top-room recipe falls back to an interior view when it finds no window prefabs, and the fallback is honest but rarely the best frame in the room.
  • Publishing is still a human act. Every frame in the index remains published: false until a person promotes it. The instruments shortlist; they do not consent on anyone's behalf. These are still other people's houses — now including their living rooms.
  • The plugin remains outside the repo. The interior changes — the mode column, the relaxed clamp, god mode for the rig — live in the same claimable BepInEx plugin as before, deliberately unabsorbed.