Skip to content

Add the Roblin demo, and give the provenance line real badges - #61

Open
hoainho wants to merge 10 commits into
mainfrom
feat/roblin-showcase
Open

hoainho wants to merge 10 commits into
mainfrom
feat/roblin-showcase

Conversation

@hoainho

@hoainho hoainho commented Aug 30, 2026

Copy link
Copy Markdown
Collaborator

Adds Roblin, a rigged goblin skirmisher, and gives the demo panel's provenance line real badges.

The demo

A character rebuilt as ONE measured skinned shell — 113,338 triangles, 41 real bones, 16 embedded clips, nothing fetched at runtime. The playground measured the surface and the rig; everything on top of that is authored here:

  • 10 sockets derived from the real bones. The export shipped no actionProfile at all, so each socket is (real bone) + (multiple of a measured body length, along a measured body axis). No literal world coordinate appears in the effect code.
  • A clip controller with cross-fades, one-shots that return, and cues read off the mixer's own clock rather than a wall-clock timer.
  • Three skills and a sprint, all aimed down the limb's own measured axis — verified at the call site as 0.0° from the hand's aim while sitting 9–16° off the torso.
  • A hand-written effect layer in plain three: instanced-quad particles with velocity-stretched streaks and an alpha-blended matter layer, ribbon trails, a procedural fracture, a bubbling caustic pool, a gnat swarm. No new dependency, no textures, no fetches.
  • A light rig whose every colour is measured — from the reference photo and from the model's own 62,956 vertex colours — then boosted, with each derivation recorded in code.

Gate R1

A clip that exists is not a clip that runs. Each of the 16 clips is seeked to 7 points and the skin is measured through applyBoneTransform against the true bind pose:

maxSampledBindingDelta = 2.832009 world units (188.5% of figure height)
16 pass, 0 fail, 0 unevaluated

Deltas over 100% are expected — the rig binds in a T-pose. The column that separates a running clip from a parked one is maxInterSampleDelta, reported per clip. Nothing is unevaluated, and there is no default-pass branch in the probe.

The write-up, including the defects that only measuring found, is in docs/showcases/roblin-stage-r.md.

The badge change (touches every demo)

src/pages/demo.ts has emitted .badge spans since the panel was written, but no CSS for that class ever existed — so every demo rendered its subject class, its provenance and its status as one run-on sentence of inline text.

  • generatedWith is authored as middot-separated steps and was rendered as a single badge; it is now split into one badge per step. No authored string changes.
  • .badge gets its first rules, built from the tokens already in styles.css: .btn's surface, border and 4px radius at a smaller size, in the mono face the site reserves for machine facts. The accent stays scarce as the palette note asks — amber fills a final status and nothing else; placeholder recedes behind a dashed rule.

One subtlety worth flagging for review: the chip is inline-block, not inline-flex. brand() wraps the product name in its own span, and inside a flex container the text following that span becomes a separate anonymous flex item whose leading whitespace is stripped — "img2threejs playground" rendered as one word.

Checks

  • tsc --noEmit clean, npm run build clean
  • npm run gate:r1 in the standalone package exits 0 (16/16)
  • Verified in the browser: Roblin renders and casts in the gallery; badges checked on both a character/placeholder demo and an object/final one

Known limits

Recorded in object-sculpt-spec.json under qualityContract.notDone, in short: no AI-vision fidelity review has been run; the single part label is still a bounds hypothesis (the bone names are not); the sprint's ground speed is authored because all 16 clips are in-place; and preset:biped:fire is a static aiming pose with no strike in it, which is why the casts sit on box_02/box_03.

hoainho added 10 commits August 30, 2026 12:25
…d a measured palette

Ten sockets derived from the 41 real bones the playground export ships without any, three ranged skills on real embedded clips, a hand-written three-only effect layer, and a light rig coloured from the reference photo and the model's own vertex colours. Gate R1 measures all 16 clips at boot.
A per-limb motion tracker gives every effect the hand or foot's own pointing axis and travel direction; cue times are now found by seeking the clip rather than guessed. Adds speed-driven limb trails and a directional muzzle flare, and stops the transparent floor from slicing the toes.
…oured bolt

Wake gradient, guttering embers, rising sparks and a scorch that outlives the blast; the three punches escalate and a cast tints the limb wakes. Also corrects the demo's camera pair, which was stale from an earlier framing and mirrored the composition.
…zardry

Projectiles are deformed rim-shaded globs and flat-shaded scrap, bile leaves a bubbling caustic pool, and a swarm of gnats replaces the rising motes. Fixes a NaN in the pool's hash that made it paint its own quad, and two inverted smoothsteps.
…e shape

THREE.Points draws one primitive, so every effect was the same soft circle. Quads give velocity-stretched spark streaks, per-particle rotation, and an alpha-blended matter layer that gives dust and mist weight.
…hits

box_02 is a boxing clip and it was throwing projectiles, so the animation struck something while the effect flew away from it. The impact now happens at the fist: a procedural fracture from the struck point, a ring of air in the plane of the blow, streak debris and a little dust.
The break belongs to the character, not his bracers. Everything around it dimmed by a third: green sits near the peak of the luminance curve, so weights that read as crisp in cool blue clip to a wash.
The .badge markup has been in the demo panel since it was written but never had any CSS, so every demo rendered its subject class, provenance and status as one run-on sentence. Splits generatedWith on its own middot separator into one badge per step and styles the class from the site's existing tokens.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant