engine v4.4.1
Engine v4.4.1
May 16, 2026
A patch in the Solid line.
what's new
- Savi places things on top of anything now — models, primitives, sprites, custom geometry, or text, she knows the size and lands the placement first try.
- Custom uploaded models that disappeared after the animation migration are back — your characters keep their model and animations switch correctly.
- Non-square images render on walls and floors again — photos, screenshots, and posters no longer come out as blank white spots.
›technical notes
Renderer
- White-floor fix on chat-attachment surfaces (#6511): new
OversizedPrimitiveConsumerroutes entities whose loaded textures don't fit the texture-array profile (512×512 desktop / 256×256 mobile) to a dedicatedInstancedMeshwith a stockMeshStandardNodeMaterial.mapRepeat/mapOffsetpacked into the pool key so seamless-tile walls tile correctly.scene.tssplit into per-consumer modules (water / effect / batch / oversized) behind aConsumerDispatcher; 575 → 423 lines,@ts-nocheckdropped. - Renderer unification (#6506): deleted legacy
engine/render/(~28k LOC of the @ts-nocheck WebGL main-thread renderer); renamedengine/render_v2/→engine/renderer/. Identifier sweep:RendererFeatureV2→RendererFeature,worker-renderer-v2.mjs→worker-renderer.mjs,[render_v2]→[render]. Zerorender_v2references anywhere. Removed the brokenplayground/dev harness. - New
TransformMiddleware(engine/renderer/transform/) owns pos/rot/scale smoothing in one place.ScaleSmootherparallels the pos/rot smoother (exp-damp, snaps on >2× axis-ratio change); scale interpolation is opt-in via the existingdraw/interpolationcomponent, and sticky-disable propagates so"disabled"keeps all three channels snapped.
Physics
- Auto-collider rebuilds when model bounds arrive (#6507). The
autoCollider: { kind: "model", modelId }marker was never acted on — clamped colliders stayed at the 0.5m placeholder forever. Now subscribes to the nextBoundsRegistry.setBoundson both planes; second-passapplyPhysicsSpecemits real half-extents. WeakMap dedup; teardown / despawn / model swap disposes the listener. Fixes resim spinning at 85-100/s on spawn into aphysics: "static"clamped-collider model.
Tome / ObjectAPI
setProperty('animated3DCharacter', false)no longer wipes DrawModel on entities whose model was authored independently (#6508) — tear-down now gated onDrawAnimated3DCharacteractually being present. Restores the 4.3.0 compat promise.model.animationupdates propagate on every write, not just the first (#6508).derive-appearance.syncAnimationForModelno longer bails when aDrawMixeris already present — upserts_default, preserves authored channels. Per-tickapplyClipwith unchanged clip/speed/loop skips the ECS write.api.getWorldBoundsBox()now returnsWorldBoundsBox({ min, max, size, center }) forDrawPrimitive(tube uses point-cloud min/max instead of bottom-center),BespokeGeometry/ DrawMesh-only models,DrawSprite(anchor-aware, billboard-mode-aware: full → sphere, yaw → cylinder in xz, none → flat quad), andDrawText(Geist Pixel metrics: charWidth ≈ 0.4 × size) (#6505). Internal OBB→AABB projection uses full local center so non-bottom-centered bespoke meshes project correctly.