Repository navigation
67js 0.19.0
67js is now Crucible. This release shipped as
@codepawlhq/67js, which is deprecated and gets no more updates. Install@codepawlhq/crucibleinstead and see crucible.codepawl.com and the v0.20.0 notes for the move (binscrucible-mcp, classCrucibleRenderer, skillsbuild-crucible-sceneandrender-crucible-media).
scene_review,scene_render_statusandscene_render_resultreturn only what an agent acts on by default;response_format: "detailed"keeps the full diagnostics, digests and metrics, andscene_capabilitiestakesconciseto drop the field notes of a topic (#656).scene_capabilitiestopicexamples(andexamples.<tool>) serves one valid call each forscene_create,scene_apply,scene_create_assetandscene_render_submit, with no growth of any tool schema (#657)- MCP: one server holds up to 4 open scenes under a 96 MiB geometry cap; the least recently used scene is evicted with a clear error.
sessionId(returned byscene_create) picks the scene on every tool, and a call without it uses the last used scene. Each scene keeps 16 checkpoints, oldest evicted first (evictedCheckpointIds), and a render job stays tied to its scene (#658). - Motion drivers read custom properties on nodes and bones (
motion.properties), distance and rotation difference variables, and can drive lights and shape keys (#694) - Mesh particle emitters take
from: "edges", with an optionalgroupandsharpAngle, so sparks spread along a rim by edge length (#695) - Mesh particle emitters take a vertex group (
emitter.group) that weights surface and vertex emission, so sparks come off a painted rim (#695) - A cloth sheet with
selfCollision: truenow reads its ownthicknessas the contact radius (never past half the shortest edge), so a flag dropped to the floor lies as a thin crumpled layer. Behaviour change: a sheet that sets bothselfCollision: trueandthicknessused to ignore the thickness (radius 0.9 of half the shortest edge) and now keeps layers2 x thicknessapart, so its baked frames differ; passselfCollision: { radius }to keep a fixed radius. Sheets that set no thickness keep the old radius (#696) - A cloth sheet takes
softBody(shape matching and pressure on a closed mesh),selfCollisionand astiffnessGroupvertex group, all baked and seekable (#696) - Field expressions read face area, edge angle, island index and neighbour counts, and accumulate, statistic, blur, sample index and rank over a whole mesh domain (#699)
- A recipe curve takes
grow, morph targets of the curve grown step by step, so a motion morph track grows a vine and seeking equals playing (#701) mesh_editgainsunsubdivideandcircularize, and poke, dual, tris to quads and symmetrize now have Blender golden cases (#703).effects.compositekeys a green screen (chroma) or a luma range out of the frame and draws it over a colour or gradient background, with the samemaskas the other post steps (part of #707)- Post steps take a
maskby part names or a depth range, andeffects.stylizeadds sharpen, kuwahara, posterize and pixelate filters (part of #707) - Mesh edits gain geometry masks: vertex_group measure curvature, edge or occlusion, and vertex_color gradients along a group, so a mesh with no UVs can carry edge wear and dirt (#708)
- Materials gain
wear: a vertex group blends the material from paint to bare metal per pixel and a second group adds dirt, so a mesh with no UVs shows metal on its edges and dirt in its cavities (#708) - Material graphs get
brick,whiteNoise,coordandmappingnodes, so a procedural material works on a mesh without UVs (#708) - Blended and transmissive parts cast sun shadows weighted by opacity and tinted by colour, so stained glass, curtains and leaf canopies throw coloured and partial shadows;
castShadow: falseturns it off (#709) environment.localVolumesadds up to 8 box or sphere volumes that absorb and emit light, in the rasterizer and the CPU path tracer (#710)- A mesh boolean
cuttercan be{ "geometry": "<id>" }, another recipe geometry, so cuts form a bounded DAG with cycle and missing-ID errors (#730) - Render jobs take a
wireframepass that draws polygon edges over the shaded surface and colours boundary, non-manifold, flipped and degenerate edges for visual review (#732) exportObj(OBJ with MTL text) andexportStl(binary STL) in the newaddons/export-meshentry write the same parts asexportGlb, in world space, with deterministic bytes (#747)- The jolt adapter builds convexHull colliders from the flat xyz point array and frees its world when setup throws.
67js/addons/physics-joltaddsjoltAdapter, a second engine for the live physics runtime built on the optionaljolt-physicspackage: the same contact and sensor events as Rapier on the same scene, queries, kinematic control and force fields, with recorded 500-box step times for both engines (part of #771)67js/addons/physics-runtimeaddscreatePhysicsSystem, live physics as a runtime system over an engine adapter (Rapier first): stepped infixedUpdate, contact and sensor events, kinematic control, ray, shape-cast and overlap queries, and interpolated part matrices (part of #771)createCameraCliptreats a ground function that returns a non-finite height as ground height 0, so the camera still stays above the floor instead of clipping being switched off (#772).67js/addons/playeradds vehicle and free-flight controllers, orbit, chase and side-scroller camera rigs,createCameraClip(camera pull-in against walls and ground), and a registry (registerController,registerCameraRig,replaceController,replaceCameraRig) for custom kinds and runtime swaps (#772)- Fix: the vehicle and flight controllers ignore a zero-length step, so the runtime's first variable-mode tick no longer turns their speed and velocity into NaN.
67js/addons/playeradds a character controller (walk, run, jump, kinematic collide-and-slide on a ground plane, heightfield or boxes, with amoverseam for physics) and swappable follow, first-person and top-down camera rigs as runtime systems (#772)67js/addons/inputaddstouchSource(virtual sticks, tap, swipe, pinch),deviceMotionSource, axissmoothing, andrecordInputwithreplaySourceso one demo runs from keyboard, gamepad, touch or a replay (#773)67js/addons/inputaddscreateInput, an open input layer: sources register, named actions and axes with rebinding and dead zones, keyboard, mouse and gamepad sources, and per-fixed-step sampling as a runtime system (#773)- Animation graph: blended clips now end with their own shares in
poseLayers()(the chain of lerp factors ran in the wrong order, so a walk to run blend played as full run); planted feet no longer slide in a blend space (#774) - Breaking for tuned graphs: a layer with two or more active slots (blend space or crossfade) now gives a different pose than before, because the old mix was wrong. Graphs tuned around the old output need a fresh look (#774)
createPathFollowerwalks an NPC along a navmesh route through the animation graph, blending idle, walk and run by speed and moving by root motion (#774)67js/addons/animation-graphaddscreateAnimationGraph, a live animation state graph: states with clips or 1D and 2D blend spaces, parameter transitions with crossfades, masked layers, deterministic fixed steps, a runtime system and pose layers forcreateSkeletonPose(#774)67js/addons/animation-graphadds root motion (rootMotionoption,graph.rootMotion,extractRootMotion; the player controller takes it through a newrootMotionoption andstate.intentSpeed), interruptible transitions (interrupt: true) and the IK hookscreateFootPlacementandcreateLookAt(#774)67js/addons/audioaddscreateAudio, spatial audio for live games on Web Audio: sounds on nodes with a listener on the camera, distance falloff and optional occlusion, triggers from input actions, physics contacts and animation markers, buses with a limiter, and a swappable backend (#775)67js/addons/streamingevicts lowest assetpriorityfirst (newevictionOrder: "distance"opts in to farthest-first within a priority; the default stays least recently used) and addscreateWorkerLoaderto decode assets in a worker (part of #776)67js/addons/streamingaddscreateStreaming, a runtime system that loads assets on demand by distance from a focus point or by game request, with a loader plugin registry (GLB first), a byte budget with least-recently-used eviction, level of detail switching with hysteresis and a loading state game code can read (part of #776)- MCP can attach a playable game to a scene (
set-game, topicgameinscene_capabilities) andscene_export_webwrites it as a static web build;67js/addons/gameplays it in a page (#777) 67js/addons/game-rulesaddscreateGameRules, a runtime system that plays a bounded JSON rule document of variables, zone, contact, input, timer and variable triggers and actions, with a deterministic event log (#777)- Make the reference netcode relay survive an oversize frame or a socket error instead of crashing, so one bad client cannot drop every player (#778)
- Add
createBroadcastChannelTransportto67js/addons/netcode, so tabs of one browser play together with no server, with a two-player sample page, a reference WebSocket relay (scripts/netcode-relay.mjs) and a headless Chrome test that plays two pages over both transports with 50 ms injected latency (#778) - Cut the netcode sample's lag with 50 ms of injected latency to about 95 ms each way (a snapshot every tick, a 40 ms interpolation delay), keep
withInjectedLatencystats live, close the transport onpagehide, and makecreateBroadcastChannelTransportforget peers silent forpeerTimeoutMilliseconds(#778) 67js/addons/netcodeaddscreateNetcode, a runtime system for multiplayer state sync: server or host authority, a transport plugin interface with an in-memory loopback (seeded latency, jitter and loss) and a WebSocket wrapper, bounded delta snapshots with quantisation, client prediction with reconciliation and remote interpolation (first slice of #778)replaceParts(parts, { retainedUnchanged: true })groups only the parts appended since the last call when a world grows by whole geometries, so loading a large world in slices no longer regroups the whole prefix on every call; a floor that shares a geometry with a world part still groups with it (#779)- A renderer built with
deferProgramLink: truelinks its shaders without freezing the page: awaitrenderer.programsReady();shaderFeatureRepresentatives(parts)picks the few parts that compile the program a whole scene needs, andgroupPartsbuilds each material key once;await renderer.prepareFrame(frame)then draws the first frame while the canvas is hidden without blocking on the post, liquid, occlusion and reversed-depth programs a first draw links (#779) loadGltfcopies accessors and converts geometry in slices of about 8 ms, andloadHdridecodes a Radiance map a row at a time with a yield between slices, so a large model or sky no longer blocks the page in one piece; the syncreadAccessorandparseRadianceHdrstay, and the output is byte for byte the same (#779)- The home page opens on the five-world loop (container port, data center, chip fab, warehouse, dark store) instead of the airport ramp: scene tabs, the credits of the playing world, a poster for reduced motion and for the first paint, and the first world downloads after the poster; the airport hero code and its styles are gone, and
hero-loop.htmlstays as the standalone page (#780) - Fix the MCP recipe schema refusing the curve fields from #701:
scene_createandscene_applyadd-geometrynow takekind,weights,splines(up to 64),shape,trimandgrowon acurve, andpointsis optional whenshapeorsplinesis given (#801) environment.localVolumeswithshape: "mesh"andfit: "mesh"now draws in the rasterizer: a mesh pass sums the length of each pixel's ray inside the closed part, exact for any number of shells, and the CPU path tracer and the rasterizer agree within 0.03 on the L-room test (#807)environment.localVolumestakesshape: "mesh"with apart: the part's oriented bounds in the rasterizer and the CPU path tracer, or its closed mesh (fit: "mesh") in the CPU path tracer (#807)- Local volumes with
noiseAmountnow draw the same noise field in the CPU path tracer as in the rasterizer, whose noise moved to a hash that rounds the same on every GPU; the WebGL, WebGPU and progressive tracers still refuse local volumes, with a test each (#808) - The bake report names the
environment.localVolumesthe lightmap bake leaves out (skippedLocalVolumesand awarningsline), and the volumes guide states that a volume emission does not light baked surfaces (#809). - Path tracer: a texture with no wrap mode now repeats, as the rasteriser and glTF draw it, so box-projected pattern walls such as the brick room keep their bricks instead of stretching the edge row (#813)
- Path tracer:
lightSelection: "tree"(andautopast 8 lights) now draws only the lights a linked part can see, uniformly among them, instead of walking a tree that counts every light, on the CPU, WebGL2 and WebGPU tracers (#814) - A motion track
{ "kind": "geometry", "id": "sea", "property": "oceanTime" }drives thetimeof the ocean nodes in a mesh stack, so one video job or timeline renders moving waves (#817) - Fix mesh edits such as
mesh_stackfailing with "render vertices exceed maxVertices across the scene" after a few re-evaluations of a large mesh: the oldest undo revisions are released one at a time before the budget refuses and the answer carries anundoNotewith the count, and a scene that is really over the limit is still rejected (#818) - The
watertag reads the sea's foam as lace (a bright core that breaks into veins, soft and antialiased edges), mirrors the sky with a fresnel term over a deep blue-green body, breaks the sun glint into facets with eight wind ripple bands with warped phases, and anoceanmesh smooths over 180 degrees by default; the physical sky draws its sun as a round disc on a 1024 by 512 map and fades the ground into haze over the first 7 degrees below the horizon, so a finite sea ends in haze, not a tan band (#819) - The coplanar search no longer throws "reading 'push'" for a touching pair whose shared box overflows to Infinity (a second route to a NaN priority bin, after non-finite bounds).
- The coplanar diagnostics no longer throw "Cannot read properties of undefined (reading 'push')" mid-render when parts with non-finite bounds (a NaN vertex, an overflowed pose) share a plane; such parts are left out of the search (#839).
- NURBS splines take
order,knotsandknotMode, andmeshEdgesToSplinesturns mesh edge loops and chains into curve splines (#841) - Motion drivers can now set the camera eye, target, fov and roll after the camera tracks, and a constraint
influenceexpression can read custom properties, so one property can dolly the camera or fade a constraint in and out (#842) - A jelly
softBodytakesbounce(0 to 1, default 0): the share of its landing speed the body keeps when it turns around, so a jelly cube rebounds 0.07 m at 0, 0.15 m at 0.5 and 0.47 m at 1 from a 1.95 m drop; softness comes from the existingshapeandstiffness(#852) - A material graph has an
imagenode that reads a catalog image with the graph's coordinates and mapping (#860) - The first path traced draw of a page on the WebGL2 backend builds its kernel faster, because the emitter loop now holds one copy of the shadow ray, with the same pixels (53 of 54 test renders byte-identical, one sun-and-sky scene off by 1/255 in one pixel):
lit-interiorwent from 108 s (one run) to 27 to 47 s over three runs on a loaded RTX 3060, and the old and new kernels compiled side by side took 36 and 7.8 s, 23 and 6.5 s (#861) mesh_editgainssplit_edges,delete_looseandflatten;unsubdivide,circularizeandextrude_vertices(not representable: a mesh has no loose edge) stay open on #703 (#703).
Install: npm install @codepawlhq/67js@0.19.0