Orbit Viewer
A metallic torus knot on a dark, fog-enveloped ground disc, lit by a colored three-point rig. It auto-rotates for a couple seconds after mount, then stops and goes idle — drag to orbit it yourself from there. The scene runs frameloop: "demand", so it only renders while the camera is actually moving: during that opening auto-rotate sweep, or while OrbitControls' damping is still settling a drag.
How it works
OrbitControlslives outside thethreecore namespace, so it's registered once viaextend()and used as theorbitControlstag.args: (l, root) => [root.camera, root.canvas]resolves lazily against the live root — the camera and canvas don't exist until the scene mounts, soargscan't be a plain array here. Seeargsreconstruction.onChangeisn't a property onOrbitControls, so it dispatches through the function-prop rules'addEventListenerfallback — it fires on every camera move, including the damped tail after a drag ends and every step of the opening auto-rotate sweep.onFrame: (root, delta, self) => self.update()is theuseFrame()analog — it drives the controls' damping and auto-rotate every rendered frame, and flipsautoRotateback off onceautoRotateElapsedpasses 2.5s. See Animation & Loop.frameloop: "demand"plusroot.invalidate()insideonChangeis what keeps the render loop asleep until there's actually camera motion to draw — seeinvalidate(). The brief startup auto-rotate rides that same path; once it turns itself off, the scene is idle again exactly like before.{ color: null, attach: "background", args: [...] }and the inferredfogattach (.isFog) set scene-level state through the sameattachmechanism used for geometry/material — see Attach inference.- The ground disc (
circleGeometry+meshStandardMaterial) sits below the knot atposition: [0, -1.5, 0]; the samefogalready on the scene dissolves its edge into the backdrop instead of a hard silhouette.