Skip to content

Aura3D 4.2.0

Pre-release
Pre-release

Choose a tag to compare

@gchahal1982 gchahal1982 released this 25 Oct 22:35
· 2526 commits to main since this release

Superseded. This version is deprecated. Upgrade to Aura3D 4.7.8.

  • Animation Studio no longer calls the retired asset-index worker. animation-scene cast add --query and prop add --query, and build-clip-library, now resolve from open licence-clear sources at build time through aura3d assets search (new scripts/open-source-search.ts; the template depends on @aura3d/cli). Accepted files keep the licence and author the provider reported (no more hard-coded CC-BY-4.0), the sha256, rig grading and weight-normalising loader. When nothing matches, the command says so and names the next steps: --file ./rigged.glb / aura3d assets add, or Meshy with --allow-meshy --budget N (opt-in, never a silent fallback to a network endpoint). Cast provenance is now open-source-resolved or meshy-generated; documents that say catalog-resolved still read the same.
  • Athletes and Links polish: round eyes with a pupil instead of dark bars, one clean waist line and 6 mm hems, smooth normals and matte cloth on the Hoops, Diamond, Links, FC and Red Zone athletes (fit to each shipped model); the Links camera frames the golfer on phones; matte golf cart. Known issue: Diamond bat leaves the hands mid-swing (attach reads the forearm before the procedural arm pose).
  • Group B last fixes (layout, material, palette). Gridlock Courier: a phone layout (minimap under the score at the top right, speed readout bottom right, nitro bottom left, so nothing overlaps) and a cleaner hero car: glass, light and underside regions only apply to outward-facing triangles of the double-shell mesh (inner-shell fragments take the body colour) and the paint carries a subtle vertical COLOR_0 gradient. Craterline GP: the phone title screen has a backdrop panel and an anchored tagline, and the track paint is world-space triplanar noise, so there is no directional streak stretch. Serpentine Sky Run: the default runner is a teal suit with silver trim (the orange gi and teal sash are gone), the surge shell is far less solid and the emissive wash is lower so the runner is no longer washed out, and the Slide, Fly and Surge touch buttons are 48 px, high contrast, with a shape icon. Chroma Roll: the start card fits a 390 px viewport. Ion Circuit: the countdown sits at the top centre and the objective card hides while it shows.
  • Links, FC and the repainted athletes: stroke counter, bag, cart, faces, hems, kits, referee, camera. The Links stroke counter climbed to about 19 per swing because the swing meter reports committed on every frame of the downswing; commitStroke now counts one stroke per shot. The golfer "bag" was a basketball ball rack (now a plain bag) and the golf cart's baked shard atlas is repainted flat. tools/hoops-athlete-retexture/retexture-face.mjs repaints the 15-joint athletes with clean hems and a flat face (Hoops, Diamond, Links, Red Zone, FC); FC keeps named materials so team tints work, and its skin weights are now smoothed over the whole mesh (triangles past 2x stretch: 750 and 869 down to 140 and 12; worst case 120x down to 5.2x). FC tints shorts, socks and skin per team, the referee is the player body in a yellow and black kit instead of a sci-fi guard model, and the broadcast camera is tighter (9.5 m up, 20 m back, 38 degrees). Verified by unit tests and CPU model renders; in-game frames are software GL where noted in evidence/<game>/rework/play-fix/.

A feature release: the games get real physics, animation and objectives, every game has its own name, render interpolation makes 120 and 144 Hz displays smooth, photographic and brand textures are gone from served assets, and the library gains the kits those fixes needed. It also carries the fixes that were planned as 4.1.4 (Hoops freeze, Cumulus Dash 2x crop, partial first frame, neutral-environment 404, canvas growth, onFrame errors). Everything here was verified on software WebGL2 unless a line says otherwise; none of it is real-GPU evidence.

Fixes

  • Bone attachments follow the final pose of the frame. Overlay poses, IK and procedural bone overrides written after the clip only dirtied local transforms, so handle.attach/attachToBone sockets and socket(bone) reads used the clip pose: a held item (the Diamond bat) left the hands as soon as a procedural swing diverged from the clip. The bone lookup now refreshes the actor's world transforms (dirty-tracked) before reading. Test: tests/unit/agent-api/actor-bone-attach-pose-order.test.ts.

  • Asset search keeps working when the hosted index is down, and returns relevant models. aura3d assets search and resolve now always run the open zero-auth sources (Khronos samples, Poly Haven, jsDelivr CC0 mirror of Kenney and Quaternius, OS3A) beside the hosted index, so a dead index no longer leaves only the built-in starter pack; texture sets, HDRIs and images are hidden from model queries unless the query asks for a surface or environment; and catalog popularity or screened-hero bonuses no longer rank an asset that matches no query term ("Garbage Truck" no longer appears for "sword"). On 20 realistic prompts, a clearly relevant first result went from 3 (published 4.1.3, which also logs asset-index fetch failed 404) to 13. Also fixes a "polyhaven" vs "poly-haven" adapter id mismatch. Audit and the asset resolution plan: docs/audit/asset-catalog-claim.md, docs/workflows/asset-resolution-plan.md. The hosted index Worker itself is not deployed (see the audit).

  • Gridlock Courier: the road no longer goes missing in the first frames. await app.ready() settles the mount, not the shader programs: programs compile asynchronously and a draw whose program is still compiling is skipped, so the first frame the player saw drew 47 of its 113 draw calls (no road). It is intermittent and not tied to canvas size (three 1440x900 loads were bit-identical; a cold 1280x720 load had no road). New warmPrograms(app) in @aura3d/engine/game settles the programs, steps a frame so the renderer kicks the exact feature records, settles again, then steps frames until the draw-call count is stable (diagnostics().drawCalls); the port awaits it before it marks itself ready and exposes settle() on its QA hook for captures after a teleport. ?warm=0 keeps the old behaviour for diagnostics. Regression spec: tests/browser/fixgrid.spec.ts. Every other game that renders right after ready() has the same exposure. Not fixed here: after a long jump the road can still flip in and out of consecutive frames on a loaded software-GL runner (cause not found), and the hypercar still reads as translucent (texture smoothing and a paint override had no measurable effect); both are written up in evidence/drift-and-deliver-port/rework/render-fix/README.md.

  • warmPrograms also waits for a pending environment HDRI (waitForEnvironment, environmentTimeoutMs; the result gains environmentFrames and environmentReady). When the HDRI lands every material switches to its image-based-lighting program variant (the diagnostics showed programs.reused jump from about 1,500 to 3,000), which dropped frames after a game believed it was settled.

  • Fix: with resize: false, a canvas backing size set after mount no longer leaves the picture in a corner of the buffer. The renderer's viewport and targets were sized from the backing store at mount, so a game that capped its own device pixel ratio after app.ready() (Cumulus Dash at 1.5 on a 2x display) drew into 720 of 1080 pixels: the 3D view filled the lower-left two thirds of the frame. The frame loop now forwards a changed backing size to the renderer (authoredBackingResize). Cumulus Dash itself now lets the engine size the canvas (pixelRatio capped at 1.5, no hand-written resize), so it also follows a window resize, which the pinned inline CSS size used to block. This class of bug is also present in code released as 4.1.3 (Cumulus Dash on any display with a pixel ratio above 1).

  • A renderer mount failure that is not strict now prints RENDERER_MOUNT_FAILED to the console. One model failing to load (a 404 on a GLB) rejects the whole mount, app.ready() still resolves in non-strict mode, and the page showed a black canvas with only the browser's "Failed to load resource". The text was already in app.diagnostics().errors; it is now also one console.error line that says nothing will draw and points at strict: true. Apex Overdrive, with its /aura-assets GLBs blocked, reproduces the black canvas; its GLBs are tracked and ship in a clean deploy, so the live site is not affected unless an asset request fails. This behaviour (one failed model blanks every node) is unchanged and is in code released as 4.1.3.

  • Fix: a throwing app.onFrame callback no longer stops the frame loop. The exception used to unwind the render loop, so nothing was drawn again and the page stayed blank (found by the cold-start agent trial: a cube whose onFrame called app.nodes.require("cube") on a node without .runtime({ id, mutable: true }) rendered black with 0 draw calls). The error is now caught per callback, reported once as onFrame callback threw: ... (console and diagnostics().errors), and the other callbacks and later frames keep running. Unit test tests/unit/agent-api/on-frame-errors.test.ts.

  • Fix: a canvas beside a HUD no longer grows until nothing draws. The app sizes its canvas to its parent. When the parent is an auto-height <body> or wrapper that also holds a HUD <div>, every resize grew the parent and so the canvas again, until the backing store passed GPU limits and the frame was black although draws were issued (the cold-start game-loop task, 2 of 3 runs). createParentFit now detects a write that moves the parent and keeps the mounted size on that axis; parents with a definite size are followed as before. Passing resize: false is no longer needed as a workaround. Tests: tests/unit/parent-fit.

  • Fix: published-package apps no longer request /aura-environments/neutral.* (a 404 and a console error in every app). The baked neutral environment is embedded in @aura3d/rendering as its own lazily loaded chunk (gzip + base64, decoded with DecompressionStream) and applied with no fetch; other presets still load from /aura-environments. The embedded copy keeps 5 significant mantissa bits on mip 0 (the sharp reflection) and 4 on the blurred mips, which is comparable to the bake's own Monte-Carlo noise (about 1.7% neighbour difference), so the chunk is 141 KB raw (about 100 KB gzip) and not the 703 KB of the first version: the stock cube app is 3,395 kB raw / 1,062 kB gzip against 3,258 / 963 on 4.1.3. Tolerance, enforced per texel in tests/unit/environment-embedded: at most half a quantization step against the smallest normalised max-channel mantissa (3.5% of the texel's peak on mip 0, 6.6% on the other mips; mean error under 1.5%). Frames on software GL (two scenes, same build otherwise): Silt & Signal rings differ by 0.074/255 mean absolute (0.04% of pixels by more than 8 levels, max 50, mean luma 76.441 to 76.442); Ninja Runner differs by 0.229/255, the same as two runs of the unchanged build against each other (0.226/255), so it is animation timing, not the environment. Regenerate with node tools/environments/embed-neutral.mjs.

  • Fix: a material.custom fragment that declares its own precision highp float; no longer fails to compile. The engine only injected a default precision when the author had none, but its own prelude (uniform float ...) sits before the author's line, so the shader failed with No precision specified for (float) and the object drew nothing (found by the cold-start water task). The default is now always declared first; a later author declaration still governs their code. Tests: tests/unit/custom-shader-precision.

  • Fix: fetchBytes tolerates a response without headers (two HDRI loader tests failed on stubbed fetches).

Games

  • Gridlock Courier: the player car is a new solid hatchback. The old Meshy car was thin overlapping plates with gaps, so the interior showed through whatever material it wore. It is replaced by a freshly generated compact courier hatchback (text prompt only, no marks): one closed shell (0 open edges), 37.5k triangles, 1.8 MB, baked to the port's car convention by tools/gridlock-courier-bake/bake.mjs; the retexture tool for the old car is retired. Sim, collider and steering are unchanged.

  • Links, FC and the repainted athletes: stroke counter, bag, cart, faces, hems, kits, referee, camera. The Links stroke counter climbed to about 19 per swing because the swing meter reports committed on every frame of the downswing; commitStroke now counts one stroke per shot. The golfer "bag" was a basketball ball rack (now a plain bag) and the golf cart's baked shard atlas is repainted flat. tools/hoops-athlete-retexture/retexture-face.mjs repaints the 15-joint athletes with clean hems and a flat face (Hoops, Diamond, Links, Red Zone, FC); FC keeps named materials so team tints work, and its skin weights are now smoothed over the whole mesh (triangles past 2x stretch: 750 and 869 down to 140 and 12; worst case 120x down to 5.2x). FC tints shorts, socks and skin per team, the referee is the player body in a yellow and black kit instead of a sci-fi guard model, and the broadcast camera is tighter (9.5 m up, 20 m back, 38 degrees). Verified by unit tests and CPU model renders; in-game frames are software GL where noted in evidence/<game>/rework/play-fix/.

  • Teleoperator, Iron Crown and Cross Hop last fixes (game-rework). Teleoperator's fare card is a compact collapsible bottom sheet on phones (14.8% of the height, 4% collapsed) and its name tags move clear of panels and of each other with a leader line (0 overlaps measured, was up to 2,800 px^2). The robotaxi is repainted into flat region materials with recomputed smooth normals (33.5k triangles, no baked atlas). Iron Crown's fighters Kenji and Mara get flat stylised faces (tools/iron-crown-restyle/flatface.mjs), and phones show first names on the health plates. Cross Hop gets the shared quick bar with six world buttons. Software-WebGL2 checks only.

  • Dot Dash 3D is now Glint Courier, its own game. The arcade-derived maze layouts (Relay Grid, Smelter Rows, Overgrowth) were redrawn and the other boards renamed. The hero is a faceted drone with a spinning ring, the four sentries have distinct silhouettes (cone, cube, ring, saucer), pickups are datachips and surge cells, the bonus items are gems, the palette is a graphite board with amber and cyan traces, and the title, HUD, mode and message wording is new. The 11 unused Meshy models (6.4 MB) and their manifest are removed. The simulation and its rules are unchanged; sounds are still the shared library effects, not new cue-bank parameters.

  • Gridlock Courier: the hero car no longer reads as see-through, and the terrain no longer lies under the road. The hero car's Meshy GLB baked glass, interior and reflections into a shard atlas on a shell with a second layer of inward-facing triangles, so it looked translucent; tools/gridlock-car-retexture/ splits the same mesh by region (body, glass, tyres, rims, lights, underbody) into flat PBR materials: geometry unchanged, 2.46 MB to 1.73 MB, no textures, no credits (car region mean luma 144 against 92 to 94 before; software GL). The model's envMapIntensity override never reached it (it writes the legacy ambient uniform, not the image-based reflection term), so the paint override is gone. The terrain around the road is now a frame around the road square instead of a plane 3 cm under it (hardening against a depth tie; the intermittent road-less first frames were not reproduced with either layout, so their root cause is still open, see evidence/drift-and-deliver-port/rework/render-fix/README.md).

  • Group C visible names and mobile layouts. The Bellkeeper's Walk title card no longer shows the old name; Cumulus Dash drops the inspiration-derived title, chapter name ("Mount Paozu" is now "Cumulus Ridge") and "star orbs" (now "sky pearls"); Apex Overdrive loses a stale "AURA3D 4.0" pill. At 390x844, Duneglide, Saltwind Highway, Lamplight Line and The Bellkeeper's Walk no longer overlap their own HUD panels; Duneglide gets a real results card (time, lamps restored, field notes, impacts, rating). Apex Overdrive now fills the viewport (the canvas had no CSS size and stayed 1280x800), its quick-switcher is a single scrolling row at the top, and the Meshy box truck and carrier are width-fitted to the lane (the box truck was 1.72x wider than its sim width). The Cumulus Dash runner palette changed (teal tunic, gold sash, plum hair) with tools/kid-goku/recolor-hero.py. Evidence in evidence/<game>/rework/ui-fix/ (software WebGL2, not real-GPU).

  • Sports games: Diamond, Hoops, Links, Red Zone and FC use the shared quick bar; overlaps fixed. The bar is one sideways-scrolling row (never three or four rows over the scoreboard on a phone) and carries one "Built with Aura3D" credit link; each game's HUD now sits below it. Diamond's strike zone is an outline, not a grey slab over the batter. Red Zone's play-call cards are a compact strip with a collapse toggle, and the sheet is rebuilt only when it changes (it was rebuilt every frame, which could swallow clicks). Hoops' intro message also ends on wall-clock time so it cannot linger on slow frames. Slingshot Siege keeps its own bar but it no longer wraps, and the ammo tray sits above the hint footer.

  • Bunker Zero: the pistol is a pistol, and enemies and pickups keep their textures. The pistol viewmodel was the pulse-rifle model; a sidearm was generated through Meshy (30 credits, admitted with sha256 and provenance) and a single table (src/weapons-view.ts) now picks the model in hand per weapon, with a test that no two weapons share a model. Seven near-black models (gunner, guard, hound, warden, armor, crate, barrel) get Bunker Zero-local copies with the base-colour atlas lifted (tools/bunker-zero-lift/lift.mjs), and the pickups' full-material replacements are texture-preserving tints. Evidence: evidence/showcase-bunker-zero/rework/content-fix/.

  • Duneglide: QA hooks refresh the HUD. stepFrames, replay and render left the speed readout at its last live value (0 in manual runs while the rider flew at 41 m/s). Live play was already correct.

  • Five games: old names and "port" wording gone from the UI, HUD overlaps fixed, scenery stretch and track smear reduced. Chroma Roll's title card, Craterline GP's title screen, Serpentine Sky Run's title text and two taglines no longer name the games they were inspired by. Ion Circuit hides its HUD and countdown behind the title card and wraps its top row under 900 px; Craterline GP's standings list and banner sit below the top row; Chroma Roll's popups start under the HUD and scale to the viewport width; Serpentine Sky Run's distance bar moves to the bottom on phones and the touch buttons hide behind its cards; Shadowstep Gauntlet's forms, abilities and sound pill stack in rows on phones. Meshy houses, towers and gates keep their proportions within about 1.6x (they were stretched up to about 3x, which smeared their textures), and the Craterline GP track's brush streaks are 5:1 instead of 10:1. Software-GL frames only; evidence under evidence/<game>/rework/ui-fix/.

  • Cross Hop: log, lily-pad and stone platforms no longer render near-black, and vehicle textures are 1024 px. The instanced mover pools applied their colour twice (base material colour times per-instance colour, a #8b5a2b log came out #472c14); they now use a white base like the other pools. The ten vehicle GLBs (cars, tram, train) had three 2048 px textures each: 70 MB became 9.6 MB (tools/asset-optimize/texture-downscale.mjs), the app's assets went from 95 MB to 43 MB, and on software WebGL2 the game is ready in about 22 s instead of about 40 s and runs about 2.9 s per frame instead of about 3.7 s (the rest is software rasterisation; this is not real-GPU data). Evidence: evidence/cross-hop/rework/content-fix/.

  • Iron Crown: Kenji and Volt restyled, kit marker slabs removed, stage text made generic. Kenji's baked texture is recoloured by colour family (tools/iron-crown-restyle/recolor.mjs): white gi to deep teal, red headband to hair, so he no longer reads as a known fighting-game character; Volt goes burgundy and amber. The fighting kit's debug-style nodes (camera safe-zone posts, centre aura beam, start-lane slabs) are replaced by spawn rings. Bangkok Dock Market, Desert Airbase and Himalayan Monastery are now Lantern Dock Market, Dustline Airstrip and Cloudstep Monastery. Evidence: evidence/iron-crown/rework/content-fix/.

  • Teleoperator: every vehicle is now an original, generic Meshy-generated design. The Jaguar-style robotaxi with lettering, the Cybercab, Corvette, Cybertruck-style and roadster hero cars and the sedan, SUV, taxi, van, pickup and bus traffic models (photo-style atlases of real vehicles) are replaced by eight generated vehicles (robotaxi, compact hatch, sedan, sports coupe, delivery van, pickup truck, box truck, roadster; 14k to 38k triangles each, about 14.5 MB in total against about 59 MB before). Badges and door marks the generator invented were covered with plain discs, the traffic yaw now matches the new front-facing models, and the traffic sizes and collision footprints follow the new bodies (the box truck replaces the 11.8 m bus at 7.6 m, the hatch replaces the SUV at 3.9 m). tests/unit/likeness-audit/teleop-vehicles.test.ts locks the manifest hashes, the removal of the old files and a 42k-triangle budget; qaSetYaw is a new QA hook for framing a vehicle from every side. The Cable Car is not part of this swap. Evidence, prompts, task ids and credits are in evidence/teleoperator/rework/vehicles/README.md.

  • Kid Goku (Cloud Runner): the runner no longer reads as sliding. The Meshy run clip plants a foot at about 3.3 m/s while the sim moves the kid at about 14.5 m/s, and the old playback rate left the feet delivering about 4.7 m/s. Cadence and phase now come from createLocomotion, a leg-bone overlay widens the swing up to 1.8x, and footstep dust fires on foot touchdowns. Feet are planted up to 10.7 m/s of ground speed; at full sprint about 23% of the ground speed still slides (measured from the clip constants, not rendered bones). Evidence in evidence/kid-goku-beyond-the-clouds-port/rework/.

  • Aura Hoops 3D: the game no longer freezes after the first basket, athletes are clean, shots are decided by the physics. The juice hit-stop counted down on game time while frozen game time stands still, so the first made basket or dunk froze the simulation forever (found by a 10-minute remote run: 183 of 186 frames stuck in a dunk, 0-0); it now uses the library createHitStop on the frame clock. The athlete model's texture atlas tore single triangles across the whole map (shard artefacts, torn hems) and contained a photographic face, lettering and a brand mark; both athletes are re-skinned with a flat palette strip and boundary-subdivided region cuts (tools/hoops-athlete-retexture). Makes and misses come from the library impact kit: a 28-sphere rim ring and glass box resolve a ballistic shot launched with aim error from the release read (3000-shot Monte Carlo: 100% made at a perfect release, 99.3% green, 59% at 0.75, 27% at 0.55; rim rolls, rim misses, banks and airballs all occur); the ball integrates in fixed 1/240 s substeps with a compensated launch. The ball sits on the palm at contact at any speed (median palm-to-ball 0.209 m to 0.110 m), locomotion clips play at ground speed over measured clip speed, idle arms hang nearly straight instead of bowed. @aura3d/debug gains createFrameErrorBoundary. Evidence: evidence/aura-hoops-3d/rework/.

  • Teleoperator: cars are solid. The player used to drive straight through traffic. Contact now runs through the impact kit (createImpactWorld in each car's own frame, hit-stop, camera shake, a synthesized hit cue and a spark burst), the speed change comes from the collision (no scripted slow-down), and the ride takes a penalty: comfort rides lose comfort, street rides lose a multiplier step and bounty. Rear-end, head-on and side hits at 8, 16 and 30 m/s each raise exactly one impact with zero penetration (evidence/teleoperator/rework/). The game has no replay, so no reference was regenerated.

  • Drift & Deliver no longer stands still on every second frame on 120 and 144 Hz displays. The car, the traffic and the headlight beams are drawn between the last two 60 Hz simulation steps (createRenderInterpolator), and the chase camera follows that smoothed car. Measured with the real simulation and loop: at 120 Hz the old presentation drew an unchanged car on 479 of 960 frames, now on none. Teleports and wrapped traffic snap instead of smearing. Software-WebGL2 browser check pending; the refresh-rate harness is tools/motion-audit/refresh-audit.mts.

  • Every game has its own name. The eleven games previously titled as ports now carry unique names (Craterline GP, Chroma Roll, Serpentine Sky Run, Gridlock Courier, Ion Circuit, Shadowstep Gauntlet, Lamplight Line, Saltwind Highway, The Bellkeeper's Walk, Duneglide, Cumulus Dash). Titles, UI, metadata, the index cards and the sitemap no longer say "port", "reconstruction" or name another game; each game shows one neutral "Built with Aura3D" credit. New public URLs are /apps/<name>/; the old /apps/showcase-<slug>-port/ roots redirect (308). Mapping: tools/showcase-port-pages/names.json; record and name screen: docs/workflows/game-names.md.

  • Strange Orbit: solid scenery has consequences in zero-G flight. Gate pillars and lintels, rim boulders and spires, the lander and the observatories are now colliders (built from the same frames as the meshes via examples/strange-orbit-port/obstacles.ts), and a rider flying up under the track bounces instead of passing through. Impacts run through the library createImpactWorld, hit-stop, camera shake and cue; one impact event and one penalised hit per contact (energy -10, combo reset, 1 s cooldown). Measured: 18 surface-and-speed cases and 3 underside cases, one impact each, none passes through (evidence/strange-orbit-port/rework/). Replay references unchanged.

  • Serpentine Sky Run no longer shakes on 120 and 144 Hz displays. The 60 Hz simulation stepped the runner, its run cycle and the chase camera on some display frames and not on others, so the runner stood still on every second frame and the rigged runner flipped between its run and idle clips about 1,200 times in 10 seconds. The renderer now blends the last two simulation steps with the game kit's createRenderInterpolator, the run cycle follows the blended distance, and the procedural fallback runner's pelvis bob is nearly halved. Measured on the real simulation and fixed-step loop (evidence/saiyan-snake-way-port/rework/): per-frame speed variation 1.00 to 0.054 at 120 Hz, camera acceleration 0.48 to 0.0004 m per frame squared, clip flips 1,196 to 0 per 10 seconds. The simulation and its replay are unchanged.

  • HEATSINK has something to do: a strike layer on the Time Trial. 16 sentry and heavy drones per lap hover over the road, 12 barrels are now shootable, and the player's existing heat-limited gun fires bolts (F, J or click). Kills score with a chain multiplier (x1 to x5, 3 s window), style points for boost pads, checkpoints and pickups, a clean-lap bonus, bronze, silver and gold medals at 16, 30 and 42 kills of 48 (finishing required), a score, multiplier and targets HUD, a stated objective from the countdown, a results screen with medal, accuracy and best chain, bolt tracers, bursts, camera shake and synthesised cues. Additive: the movement replay still matches the original within 1e-6, and the strike replay (reference movement with the gun held down) is pinned by its own hash. examples/heatsink-port/{operation,audio}.ts, tests/unit/heatsink-port/strike.test.ts, tests/browser/heatsink-strike.spec.ts.

  • Where the Wind Wanders: the traveller's feet now move at the pace of the ground. The hero animator re-issued play with a fresh crossfade and a moving captureTime every frame, so the clip phase ran 2.4x to 3.8x too fast (planted-foot slide 5.5 u/s against 3.2 u/s of ground speed, ratio 1.72, derived from the recorded commands and the rig's forward kinematics). It now uses the library's createLocomotion, fed the real ground speed once per sim step with a pinned stride phase and a crossfade only on a gait change: phase rate exact, median slide 0.15 u/s (ratio 0.05). The authored walk clip still skates a little on its own (toe p95 about 0.5 to 0.65 u/s); stride warping or foot IK is the follow-up. Unit tests recompute the gait table from hero.glb and run the library foot-slide meter; evidence and frame strips in evidence/where-the-wind-wanders-port/rework/. Software GL only; real-GPU feel is the owner's to confirm.

  • Aura Links 3D: the golfer no longer reads as slanted, and the club head decides the strike. The legs were children of the hips, so the hip hinge rotated them too: at address the thighs leaned 17 degrees and both ankles sat 0.23 m behind the stance, on top of 36.7 degrees of trunk flex. Two-bone leg IK now keeps the ankles planted with the knees bent toward the ball (about 32 degrees of flex), and the spine reads about 28 degrees from the hips with the head over the ball. The ball now launches when the club head's swept path meets it (game/contact.ts), with a timed fallback so a missed contact can never soft-lock the hole, and the club is attached through the library attachToBone. Software-GL frames only; real-GPU look is unchecked.

  • Ninja Runner: crates and beams are solid. With the reworked contact rules (default in the game; ?rules=original keeps the original's pass-through), an unavoided hit stops the runner, knocks it back (bump 0.55 m, crash 0.95 m past 21.5 m/s) and breaks the obstacle into physical debris (planks bounce, slide and fade); a dash or attack still breaks it cleanly. Feedback runs through the library impact kit (createImpactFeedback, createHitStop, createCameraShake): hit-stop, trauma shake, a tier cue. The original-rules replay is unchanged (tests/unit/ninja-runner-port, 86 tests).

  • Aura Diamond 3D: the batter holds the bat, fielders wear gloves, the bat helps decide the hit. The game passed its hand-pose bones as arrays where the engine reads { x, y, z, w } objects, so the arms never moved while the bat floated beside him; fixed, with the bat and gloves attached through attachToBone (a failed attach is now loud, the route-side fallback that put the bat on the ground is deleted). The pitch now reflects about the swinging bat's face (batContact, bounded to 14 and 9 degrees from the timing model), and the swing accelerates into contact instead of stopping there. Software-GL measurements in evidence/aura-diamond-3d/rework/; not real-GPU.

  • Aura FC 3D: the players now actually kick, and the doubled legs are gone. Four causes, all measured. (1) The GLBs' Shoot clip is not a kick (the right foot travels 0.28 m at a peak 1 m/s), so the game drove procedural shorts and sock boxes through a real swing beside legs that barely moved: that was the double frame. The boxes and the procedural limb pose are removed; the athlete is one skinned body. (2) New KickTap / KickPass / KickShot clips are baked into both athlete GLBs with analytic two-bone leg IK (tools/aura-fc/bake-kick.mjs, no new Meshy credits): plant foot fixed (under 1.2 cm drift), boot back, accelerating through the ball, follow-through, boot tip inside the ball radius at the sim's launch fraction. The clip phase is the swing progress (kickT / kickDur), so the boot meets the ball on the exact frame the sim launches it (error under one frame across 95 simulated kicks) and a hit-stop freezes the swing. (3) The default animation path ignores AuraAnimationSpec.speed, so every clip speed the game set was a no-op and a planted foot slid 0.3 to 1.2 m/s; run cycles now advance with distance travelled (planted-foot slide RMS 0.05 to 0.11 m/s from jog to sprint, 0.14 to 0.35 m/s on the walk clip). (4) The pale slabs and flaps at the hips (the other half of the double-framed look) are bridging triangles the Meshy auto-rig left between body parts that move independently (left thigh to right thigh across the shorts seam, hand to hip); in a kick pose 328 triangles stretched past 3x and some past 100x. tools/aura-fc/skin.mjs softens the skin weights around them (no geometry removed): across the walk, run, sprint, kick, jump and tackle clips only 21 triangles of the striker (17 of the keeper) stretch past 2x and none past 5x. Sim fixes found on the way: the kicker now turns to face the kick line during the swing (up to 176 degrees off before) and is planted for it; a swing interrupted by a tackle, steal or stun no longer fires later as a phantom pass in a stale direction (seen 7 to 68 s after the swing in every simulated match); the AI no longer starts a swing during the kickoff countdown, where the ball launched a second after the animation ended. New unit tests tests/unit/aura-fc-3d/ (29), a QA hook (window.__AURA_AURA_FC_3D__: freezeAtKick, step, focusFastest) and a remote filmstrip spec tests/browser/rework-fc.spec.ts. Known limits: the shirt colour is a whole-mesh tint (the shorts and socks kit blocks are gone until runtime nodes expose bone sockets); the library createLocomotion is not used because its midpoint clip switching and 0.6 rate clamp slide 3 to 7 times more than the game's switch points on this rig (numbers in locomotion-sync.test.ts); crosses still use the pass swing.

Likeness and brand

  • Borrowed lore renamed at the source in Serpentine Sky Run, Shadowstep Gauntlet and Cumulus Dash; the runtime label masking is gone. The three games no longer hide another game's character, move, item and place names behind installNeutralLabels (deleted, with apps/showcase-port-shared/neutralLabels.ts and Serpentine's displayText layer): every identifier, string, QA hook and test now uses the games' own names (for example Surge, Vital Seed, Grapple Staff, the Serpent Hall, Spirit, Spiral Orb, Beast form, Lantern Village, Sky Pearls, Glider, Cumulus Ridge; QA globals __AURA_SERPENTINE_SKY_RUN__, __AURA_CUMULUS_DASH__, __lanternhold). Behaviour is unchanged: all 247 unit tests of the three games pass and the replays still match the captured original runs, which stay as captured; tests/unit/_support/legacy-names.ts maps the captured names in tests only, and courseDigest takes an optional type-name mapper so the Shadowstep test reproduces the captured digest exactly. Also: hand-typed engineVersion strings dropped (Hoops, Diamond, Links, Red Zone, Teleoperator), licensed font stacks in FC, Iron Crown and Aura Slam, the Red Zone cup asset key renamed rzChampionCupMeshy, .vercelignore patterns anchored (same ignore set) plus /evidence/ so a clean deploy stays under the file limit, and the game-checks lore list extended.
  • Likeness and brand cleanup of shared models. The trophy cabinet (framed photographs of people), the rooftop athlete face scans and the Bean Brawl Race yellow bean (a Pikachu-like face) no longer carry those textures: base-colour atlases are softened or the marks painted out, with new hash-named files, updated manifests and content-based tests (tests/unit/likeness-audit). A texture-by-texture audit of every served GLB is in docs/audit/likeness-brand-audit.md.
  • Iron Crown: the Crown Arena no longer shows framed photographic portraits. The shared trophy-cabinet model's baked atlas holds small framed photographs of people; the arena now builds its two cabinets from instanced primitives (wood frame, shelves, gold cups, flat crimson banners with gold borders; eight draws) and tests/unit/likeness-audit/iron-crown-stage-props.test.ts fails if the scanned cabinet, its hash or its bytes come back into the app. The other Iron Crown stage props were scanned for photographs and real marks: only generic signage ("RAMEN") and small panels, no faces or brands found. Evidence: evidence/iron-crown/rework/portraits/.
  • Athlete models repainted in Diamond, FC, Links and Red Zone (no photographic faces, lettering, crests or brand marks). diamondAthlete, fcSoccerStrikerMeshy, fcGoalkeeperMeshy, linksGolferAthleteMeshy, rzQuarterbackMeshy and rzDefenderLinemanMeshy now point at flat-colour models painted by body region (same rig and 23 clips, no textures), generated with tools/hoops-athlete-retexture/retexture.mjs (new per-sport config). The eight original athlete GLBs were removed. FC's team tint targets the kit material only. docs/audit/likeness-brand-audit.md lists what else still ships real marks (Teleoperator vehicles, rooftop face scans, race textures).
  • Fix: real brand marks and photographic likeness removed from served assets. The six athlete models (Hoops, Diamond, Links, FC, Red Zone) are repainted in flat region colours (no face, lettering, crest or swoosh); the Formula opponent livery and tyre lettering, the Tsukuba circuit logos and a Dunlop arch texture are cleaned; the unused rooftop face-scan GLBs are smeared and their unreferenced duplicates deleted. Geometry is unchanged, so body shapes that replicate real vehicles still need new art (docs/audit/likeness-brand-audit.md).

Library

  • clearCameraEye and createCameraClearance (@aura3d/engine/game): a chase camera that does not sit inside scenery. Pulls the eye back along the focus-to-eye line to just before the first solid sample, fast in and slow out. Duneglide uses it with its chapter colliders plus tree, rock and pier columns (trees and rocks have no sim collider, and a camera inside a crown fills the view with it): on the chapter-0 flight the unobstructed chase eye was inside scenery on 153 of 300 sampled steps; with clearance, 3 (all at the 2.5 m minimum distance behind a rider hugging a crown). The eye keeps 1.8 m from colliders, the most the rider's own 1.85 m wall clearance always allows. QA stepping (stepFrames, replay) now cuts the camera to the chase pose instead of easing from its previous pose, so QA frames show the real camera. docs/api/motion-camera-clear.md.
  • summarizeTextureUpgrade and texturedNodesReady (@aura3d/engine/game): wait for textures before capturing. Textured materials upgrade one at a time after mount, so an early frame, or any frame on a software-rendered runner where each new shader takes tens of seconds, shows plain white models. Saltwind Highway's QA hook now reports textures(), and its player car is added to the scene first so it is the first model textured (it used to be last: 12 of 15 textures were in by 480 s on SwiftShader and the car was not). No regression: the same pace was measured on the commits from the Meshy art pass through 4.1.3.
  • One shared quick-switcher bar (apps/showcase-port-shared/quickbar.css) replaces the per-game bars in Aura Slam, Iron Crown, Pips Big Leap, Dot Dash 3D, Thermal Drift and Bunker Zero. It is a single row that scrolls sideways instead of wrapping to four rows on a phone, reserves its height in --a3d-bar-space so HUDs sit below it, and has an opt-in centred pill layout for wide screens. Iron Crown moves its fighter and venue pickers into a toggled panel, Thermal Drift's command bar moves from the bottom of phones to the top and its HUD shrinks to fit, and Teleoperator's fleet dock collapses into one chip with stacked cards on phones. The "AURA3D ENGINE" chip and stale "Aura3D 4.0.x" text are gone from the game UIs, replaced by one "Built with Aura3D" link.
  • Smooth on 120 and 144 Hz displays: createFixedStepPresenter, createRecordBlend, runMotionGate and createFixedStepLoop().alpha. Additive. A 60 Hz sim drawn without interpolation stood still on every second frame at 120 Hz and flipped animation clips; the presenter draws between the last two steps (replays and stepFrames untouched), and runMotionGate fails a game that does not. Defaults of createFixedStepLoop are unchanged. Docs: docs/api/motion-presenter.md.
  • Motion kit in @aura3d/engine/game (additive). attachToBone (role-resolved bone sockets with a loud ATTACH_BONE_NOT_FOUND), createLocomotion and proceduralLegSwing (stride-synced gaits), createFootSlideMeter (planted-foot drift and legs-not-stepping check), createImpactWorld, createImpactFeedback, createHitStop and createCameraShake (swept collision with one event per contact plus hit-stop, shake, cue, particles and damage), smoothDamp, createSmoothFollow3, createRenderInterpolator and jitterReport, and checkDoubleFrame. attachToBone bone matching is case-, punctuation- and rig-prefix-insensitive with forearm, upper-arm, shoulder, thigh, shin, foot and hips roles for Mixamo, Meshy, Rigify, Unreal, glTF Avatar and Biped naming, and ATTACH_BONE_NOT_FOUND lists the tried names. Docs: docs/api/motion-*.md. These are pure TypeScript with no DOM, so they run in unit tests and QA hooks.
  • API: .position, .rotate and .lookAt on scene node builders (and instanced and batched handles) accept an array as well as separate numbers, like .scale already did (primitives.box().position([1, 2, 3])). The array form was the most common first-draft type error after app.camera and setUniform being optional; the signatures are overloads, so existing calls are unchanged.

Docs and tooling

  • Docs: docs/agents/recipes.md (complete compiled scenes for the five common tasks) and the .runtime({ id, mutable: true }) rule in the quickstart. In the cold-start trial, 8 of 15 runs spent all 40 turns reading dist/ without writing a scene; with the recipes the median dropped from 40 to 13 turns (see evidence/agent-eval/REPORT-after.md).

  • Docs: type traps table in docs/agents/recipes.md for the strict tsc errors agents hit on a first draft (app.camera and setUniform are optional, translate is on the runtime handle, geometry.define has no kind, material.custom option shapes).

  • Docs: black frame checklist in docs/agents/troubleshooting.md and the sized-wrapper advice in docs/agents/recipes.md.

  • Tests: three stale test doubles fixed (prd03-s18c-custom-passes, two cases in prd03-t0-16-statecache-invalidate). Their fake WebGL host lacked lifecycle.bindOutput, which runV2LdrTail has called since 4.0.4; they fail the same way on the commit before the frame-cost change, so they were never a regression of it.

  • Tooling: the cold-start scorer scores the forest task on a reduced canvas and frame plan so the 10,000-instance scene completes on software GL.

  • Lessons learned and automated game checks. docs/agents/lessons-learned.md catalogues every mistake from the 4.1.x and 4.2.0 programs (rendering, motion, game design, assets and likeness, naming and copy, build and deploy, verification, agent process) with the API or check that prevents it; docs/agents/new-game-checklist.md is the one-page pre-flight and acceptance list. node tools/game-checks/run.mjs <game-slug|--all> runs 13 per-game checks (old names and "port" wording, engine chip, own quick bar, canvas size after ready, fixed-step without presenter, hit-stop on frozen time, array bone poses, brand and lore terms, asset sha256, hand-rolled kits, three.js and vendored bundles, runtime text masking, fonts, tracked screenshots) and 3 repo-wide checks (unanchored .vercelignore, hand-typed game counts, Meshy caps). Baseline over the 26 games in docs/audit/game-checks-baseline.md (23 errors, all runtime label masking of borrowed lore in three games; 32 warnings).

Site

  • Site and docs: an honest three.js comparison. The homepage comparison and /docs/aura3d-vs-threejs.html are rewritten as a side-by-side with where Aura3D wins (scene source length in 4 of 5 bench scenes, game kit, safety, agent workflow), where three.js wins (7.7x to 8.7x smaller bundle, first frame, frame time, cold-start authoring speed 4 vs 10 median turns, breadth, maturity), ties, when to choose which, what the evidence does not prove, and how each number was measured; every row names its version and caveat (software GL, one author, n). The code panels are the real bench PBR viewer sources (49 vs 24 lines). Unsupported claims are removed from the comparison surfaces: ~120 lines vs 18, 83% less code, 15 / 15, zero-dependency (the engine depends on 15 sibling packages), 14 fragile packages. docs/aura3d-vs-threejs.md is v3 and the capability matrix is v3 (60 rows; row 16 corrected, since cube, array, stereo and chase cameras exist; new rows for the motion kit, render interpolation, warmPrograms, the judge CLI, cold-start authoring and frame cost).
  • Site claims corrected (marketing, docs, llms files). The unverified "800K+ catalog assets" / "~850K catalog" figure is removed everywhere (homepage stat, docs, llms-full, CLI index label, template comments) and replaced by the counted 652 admitted assets in the repo manifest; "zero-dependency", "MIT licensed" (the repo has no LICENSE file: copy now says MIT is declared in package.json), "WebGPU compute" and several per-game card claims (Aura Slam World Tour, Apex vehicle count, Thermal Drift cannons) are corrected or softened. marketing/scripts/check-site.mjs now fails if the homepage packages or admitted-assets stat disagrees with its counted source or the retracted figure returns. Audit: docs/audit/site-claims.md.
  • The site states the true game count, generated from one inventory. docs/workflows/game-inventory.json (built by tools/site/gen-game-inventory.mjs from the catalog and the routes the production build serves) lists 26 live games and counts the three V2 builds (Thermal Drift, Apex Overdrive, Grid Dispatch) as variants, not extra games. The homepage ("4 playable games", "Fifteen games"), the showcase index, README, llms.txt and the social-card generator read that number instead of hand-typing it, marketing/scripts/check-site.mjs fails when any user-facing file states a different count, and the showcase index is regenerated by tools/site/gen-showcase-index.mjs, grouped by genre with 1x and 2x card images built from the final screenshots (tools/site/build-card-images.mjs).

Known issues

  • Teleoperator: every vehicle is now an original generic design, but the hatch, the wagon-style sedan and the van still read as familiar real shapes, and some Meshy-added emblem-like marks are covered by thin plain discs (flat dots up close). docs/audit/likeness-brand-audit.md lists live games that still carry content for an owner's review (Aura Clash face textures, Courier vehicle atlases, a trophy name in Red Zone). Name clearance: the new game names have had a web screen only, not trademark clearance.
  • Gridlock Courier: after a long jump the road can appear in one screenshot and vanish in the next; the first frames that showed no road were not reproduced after the fixes above and the root cause is still open (4.2.0 work).
  • All evidence is software WebGL2; none is real-GPU evidence. The legacy post chain still darkens frames with bloom or vignette on (see 4.1.2).