Articulate.
Articulate Lab · Engineering log

Day 5 — fitting out the Glamper

Interior lining, night lighting, a rigged fridge, a swing-out prow unit and a kitchen full of appliances. Roughly forty separate changes, shipped live between each one. This is the honest version: the measurements that decided things, and the eleven faults that cost time — four of them the same two mistakes repeated.

What got built

Everything below is in viewer2 and re-exported to glTF after each change. Both files land at roughly 4.2 MB, 564 nodes. Frame 1 is closed, frame 2 open; every moving part is keyed on those two frames.

ItemWhat it isMeasured
Interior felt12 panels, 3 mm skin on top of the insulation, cabin side. Four colours in the configurator.3 mm
Night lightingNine lamps that were dark, three roof floods re-seated and aimed at the ground, new gullwing edge strip, four top-bay strips.900 W floods
Dometic CFX5 55Parametric, rigged lid, slide-out and 180° swivel.455 × 820 × 440
Prow unitSwing-out triangular shelf, 19 mm ply base + cladding face, cassette toilet on it.600 × 430 × 430
KitchenBasin, tap, drainer, pump, hot water heater, microwave, Nespresso, Bosch hob, three storage boxes, BBQ in the forward drawer.—

The fridge that didn't fit

The brief was a hinged Dometic with the hinge running along the trailer's long axis. The specification came off the Dometic manual rather than a product page: CFX5 55 — 720 × 455 × 480 mm including handles, 55 L, 23.6 kg, single zone, reversible lid.

Then the arithmetic killed it. Three numbers:

Measurementmm
Floor to worktop underside478
Existing slideout_shelf to worktop443
CFX5 55 height480

Two millimetres too tall standing on the bare floor; thirty-seven too tall on the shelf that was already in that bay. And the obvious answer — slide it out sideways through the kitchen face — is dead: wheel_R occupies x 776–1028 / y −589…189 and the jerry cage takes y −1008…−639. There is no 720 mm window between them.

Two things I said in that analysis were wrong, and the operator caught both. The jerry cans were eye-hidden, so they were never in the exported model — I quoted a hidden object as a blocker. And I was reasoning about a sideways slide that had never been asked for; the instruction was lengthwise. The rear extraction was right all along.

The resolution was to change the product, not the trailer: lid −10, box −30, length +100, giving 455 × 820 × 440. That clears the worktop by 37 mm. It extracts 950 mm out of the rear doors on a tray and swivels 180°, so the lid can actually open.

CFX5 55 closed
Shut. Hollow shell — base, four walls, rim frame.
CFX5 55 open
Lid at 105°, hinged on the long back edge. Liner, wire basket, divider, lid-mounted light strip.

The prow unit, three times

A swing-out triangular unit in the nose chamfer, holding a cassette toilet. It took three builds, and the first two were wrong in instructive ways.

First build. The requested unit was 600 × 600 × 400. The chamfer as built is a 415 × 477 triangle with a 632 mm rake, and the void behind that rake is 290 mm deep measured perpendicular. The unit was bigger than the hole.

Second build. Sized to the cut — and built into the corner. Wrong: the corner is outside the chamfer. That volume is fresh air, not a void. The shelf has to project inboard, into the footwell, with the rake as its face.

the inverted prow unit
The inverted version. Green and yellow are the two carcass walls, sitting outside the body envelope. The operator's note was three words: “Prow triangle is inverted.”

Third build. Mirrored inboard, and reduced to what was actually asked for: two parts only, an external cladding face and a 19 mm ply base. The base is an isoceles triangle — 600 mm face on the rake, two 430 mm sides, apex 308 mm inboard. Clear aperture between the jambs measures 620 mm, so the 600 face has 10 mm a side.

The hinge took two attempts as well. Pivoting on either end of the rake fouled a corner post at every angle from 70° to 110°. The answer was already in the file: the front door pivots at (301, 1405), which is 44 mm proud of the rake — an external butt hinge. Same pivot arrangement, same forward 100°, and the BVH sweep comes back clean.

prow unit open
Open. The cassette stands on the ply base and swings clear of the body.
prow aperture cut through
The aperture, cut through both the felt and the shell. Before this you could see daylight through the felt and a solid dark panel behind it.

Sourcing: three of six links were dead

Six model links, checked through the Sketchfab and 3D Warehouse APIs before download. Half of them could not be had at any effort:

ModelLicenceResult
Weber Q2200 (3D Warehouse)none declaredpublic GLB, downloaded
Microwave (carlcapu9)CC Attributiondownloaded
Nespresso (davidinlines)CC Attribution-ShareAlikedownloaded — share-alike, flag before commercial use
Weber Go-AnywhereStandard (Store)isDownloadable: false
Gas hob, 2 burner (HQ3DMOD)Standard (Store)isDownloadable: false
Amica PGA3610XBEnone declaredHTTP 403 on the download endpoint

The rule in our canon is “generic parametric or buy”, so the Go-Anywhere was built to spec instead — 512 × 395 × 285 in transport form, which fits the forward drawer where the Q2200 could not.

Two sourcing findings worth keeping. The 3D Warehouse Weber file contained three things: the BBQ, a second copy of it on a table, and a 1.82 m human scale figure whose materials were Marc_Shirt and Marc_Skin. The naïve unite grabbed the human. And Blender 5.1 has no COLLADA importer — bpy.ops.wm.collada_import is gone. Installing pycollada into Blender's own Python and parsing the file directly is the route; the Bosch hob arrived Z-up with unitmeter 0.0254, i.e. authored in inches.

What broke

Eleven faults. Four of them are two mistakes, each made twice.

FAIL-HIDE-RESTORE-NOT-IN-FINALLY

838 objects · shipped models missing the body

A probe render hid everything except its subject, then errored on BLENDER_EEVEE_NEXT — an engine name that no longer exists in 5.1 — and never reached the restore line. Every subsequent script captured the broken state as its "previous" state and faithfully restored it. 838 objects were left hide_render=True, body_shell among them. The exporter drops hidden objects, so models published in that window were missing the trailer body.

Rule: any hide/restore pair goes in try/finally. A straight-line restore is not a restore.

FAIL-SOLID-BOX-WHERE-SHELL-NEEDED

Three separate builds · nothing rendered inside

cfx5_body was a solid cube, so the liner and wire basket were entombed inside it. cfx5_gasket was a solid slab across the aperture, sealing the tub shut. And body_shell is the same class of object — a 12-vertex solid already documented in the import gate. Cutting the felt for the prow aperture merely exposed the inside of that box, which reads as a flat dark panel.

Rule: anything with an interior is built as base + walls + rim frame. Never a cube.

FAIL-STALE-MATRIX-WORLD

Four occurrences in one day

The bridge's documented trap, hit four times. The rear-door MDF infills landed at rig-local coordinates in world space, hanging under the chassis. The fridge lid sat 400 mm high because the rig's matrix_world was still identity when the children captured it. The Weber re-import came in at 308 metres. And the prow parenting went the same way.

Rule: view_layer.update() before reading matrix_world, and set matrix_parent_inverse before matrix_world, never after.

FAIL-BOOLEAN-BEFORE-SOLIDIFY

Body collapsed to 8 vertices

The prow aperture cutter was added to body_shell and moved to the top of its modifier stack, ahead of the BEVEL and SOLIDIFY. The evaluated mesh fell to 8 vertices — the entire body reverted to a bare cube. The seven existing aperture cutters all sit after the solidify; that is not decoration, it is the order the shell is built in.

Rule: aperture booleans go at the end of the stack, after whatever generates the shell. Check the evaluated vertex count after adding any modifier.

FAIL-REGEX-KNEW-HALF-THE-CONVENTION

Nine lamps dark · twelve felt panels uncoloured · a BBQ invisible

Three separate versions of one mistake, all in the viewer rather than the model. The night regex matched led_* and lens_* but not the nine emis_* lamps. The felt regex was /^felt_\d/, which silently skipped felt_partition, felt_riser and felt_reardoor. And the BBQ option was defined but never added to the Glamper's shown list, so 23 parts sat in the file with no control to switch them on.

Rule: after adding a naming convention, enumerate what the pattern actually matches against the shipped file. Do not assume the convention is singular.

FAIL-ASSERTED-A-BLOCKER-FROM-HIDDEN-GEOMETRY

A design decision argued from a phantom

The sideways fridge extraction was declared impossible partly on the grounds that a jerry cage occupied y −1008…−639. Those objects were eye-hidden, therefore not in the exported model and not part of the design. A clash test that includes hidden geometry answers a question nobody asked.

Rule: filter clash tests by what actually ships — hide_get() and hide_render both — before quoting anything as a constraint.

FAIL-REASONED-PAST-THE-INSTRUCTION

Two rebuilds

Told the fridge was “lengthwise, not sideways”, I analysed a sideways slide anyway. Told the prow unit was “exactly the same as the prow door”, I moved its hinge to the opposite end and spent two rounds discovering that the door's own pivot was the answer. Both times the operator had already supplied the constraint.

Rule: when an existing part solves the same problem, read its transform before designing a new one.

FAIL-INSULATION-OUTSIDE-THE-WALL

Found by raycast in one pass

A six-direction ray sweep over a grid of interior points, flagging any first hit on body_shell, returned exactly one exposure. interior_insul_front was built at y 1399–1424 but the shell's inner face is at 1398 — the nose insulation was outside the wall, and the felt I had just added inherited the error. Moved inboard 30 mm; re-swept; zero exposures.

Rule: interior exposure is measured by raycast, not by eye. It found in one pass what four screenshots had not.

Rules out of Day 5

  1. try/finally around every hide/restore. The alternative is silently shipping a hollow model.
  2. Anything with an interior is a shell, never a cube.
  3. Tick the depsgraph before reading matrix_world. Set the parent inverse before the world matrix.
  4. Aperture booleans after the solidify. Verify by evaluated vertex count.
  5. Raycast for interior exposure. Grids and normals, not screenshots.
  6. Check isDownloadable and the licence before planning around a model. Half of them are shop windows.
  7. Read the existing part's transform before designing its sibling.

Still open

  1. Basin and forward drawer collide. The basin went into bay 4 (bowl bottom at 845) and the drawer runs to z 944 across y 533–954. One has to move.
  2. Two gas bottles at identical coordinates — gas_bottle_13kg_1 and _2, both at x ±109, y 1174–1394.
  3. Bosch hob textures shipped in the zip but the DAE material bindings did not survive the parse. On flat black glass for now.
  4. Nose step — the front wall moved back 30 mm, the prow rakes still run to y 1406.
  5. CFX5 branding — logo, badge, non-slip lid texture. The second half of the agreed hybrid route, not started.

Open the configurator →  ·  Full failure log →