UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.

641 lines (561 loc) 272 kB
# Changelog All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [5.1.0-alpha.6] - 2026-05-12 - `WebXRImageTracking.imageTracked` event — invoked every frame an image is tracked, with typed access to the tracked object instance: ```ts imageTracking.imageTracked.addEventListener(evt => { console.log(evt.object, evt.image); }); ``` - `?stats` URL parameter now also logs renderer info (DPR, window DPR, antialias, MSAA samples, drawing buffer resolution) ## [5.1.0-alpha.5] - 2026-05-08 **Added** - `Context.events` — typed event bus for decoupled component communication. Known events get autocomplete; custom events can be typed at the call site: ```ts context.events.on("scene-content-changed", e => console.log(e.object)); context.events.emit<{ pts: number }>("scored", { pts: 10 }); ``` - `ContactShadows` auto-refit — when `autoFit` is enabled, shadows automatically refit when scene content changes (e.g. SceneSwitcher load, DropListener asset loading) - `Input.addEventListener` now returns an unsubscribe function (works with `autoCleanup`): ```ts this.autoCleanup(this.context.input.addEventListener("pointerdown", (evt) => { ... })); ``` - `AnimationBuilder` — low-level API for defining animation tracks with typed keyframes and tween shorthands. Used by `AnimatorControllerBuilder` and `TimelineBuilder` for inline `.track()` calls - `TimelineBuilder` typed track builder interfaces per track type (`AnimationTrackBuilder`, `AudioTrackBuilder`, etc.) with inline `.track()` support for keyframe animation - `AnimatorControllerBuilder`: inline `.track()` for defining animation directly on states, support for `TrackDescriptor` arrays as clip sources, simplified `exitTime` (replaces separate `hasExitTime` flag) - Physics raycast `includeTriggers` option — opt-in to hitting trigger/sensor colliders (skipped by default) **Changed** - Timeline track classes renamed for consistency: `AnimationTrackHandler` → `TimelineAnimationTrack`, `AudioTrackHandler` → `TimelineAudioTrack`, `ActivationTrackHandler` → `TimelineActivationTrack`, `ControlTrackHandler` → `TimelineControlTrack`, `MarkerTrackHandler` → `TimelineMarkerTrack`, `TrackHandler` → `TimelineTrackHandler` - `OrbitControls.fitCamera` deprecated overload removed from type declarations (runtime still accepts `Object3D` for backwards compat — use `fitCamera({ objects: [...] })` instead) **Fixed** - `OrbitControls`: programmatic camera transitions (e.g. `fitCamera`) no longer interrupted continuously during an ongoing drag — only at interaction start - `fitCamera` with `centerCamera: "y"` producing incorrect camera elevation when camera was above the scene center - `Animator`: switching `runtimeAnimatorController` now properly disposes the previous controller - `AnimatorController.dispose()` guard against missing mixer - `CursorFollow.snapToSurface` incorrect property description removed - Vite 8 compatibility fixes ## [5.1.0-alpha.4] - 2026-05-06 #### Added - `autoCleanup` on `Behaviour` — register disposables or cleanup functions tied to the component lifecycle. Automatically cleaned up on disable or destroy depending on when registered: ```ts onEnable() { this.autoCleanup(on(window, "resize", () => { ... })); this.autoCleanup(this.context.connection.beginListen("my-event", () => { ... })); } ``` - `TimelineBuilder` API for building timeline assets from code: ```ts const timeline = TimelineBuilder.create("MyTimeline") .animationTrack("Walk", animator).clip(walkClip, { duration: 2 }) .activationTrack("FX", vfxObject).activate({ start: 1, duration: 0.5 }) .build(); director.playableAsset = timeline; ``` - `PlayableDirector`: expose `tracks` and `activationTracks` getters, support runtime `playableAsset` assignment with automatic graph rebuild - `PhysicsCollider`: expose `density` property, add `@validate` decorator for automatic property updates at runtime - Timeline `AudioTrack` volume getter/setter - `Networking`: `beginListen` now returns an unsubscribe function (backwards compatible — `stopListen` still works): ```ts const unsub = this.context.connection.beginListen("my-event", (data) => { ... }); unsub(); // or use this.autoCleanup(unsub) ``` #### Changed - Serialization: consolidated instantiate reference resolution into a unified system — fixes cloned timelines, EventLists, SignalReceivers, and deep component references not resolving correctly after `instantiate()` - Removed legacy `AvatarLoader`, `AvatarBlink_Simple`, `AvatarEyeLook_Rotation`, `Avatar_Brain_LookAt`, `Avatar_MouthShapes`, `Avatar_MustacheShake` components #### Fixed - `@validate` decorator wrapping `__internalAwake` multiple times when components were re-activated - Instantiated scenes with timeline `SignalReceiver` not resolving EventList object references - `instantiate()` not including cloned Object3D GUIDs in the guids map - `Light` component throwing on unsupported light types (now logs error without breaking deserialization) - Worker URLs producing incorrect paths for SPA deployments - Vite license and project identifier error handling for non-500 status codes - Rapier physics `dispose()` not clearing internal state (freed world could cause crashes) ## [5.1.0-alpha.3] - 2026-04-29 #### Added - `AudioClip` type with standalone playback control — use with `@serializable(AudioClip)` for direct audio clip references - `AudioSource` spatial blend support via dual-path audio graph for smooth 2D/3D crossfade - UI Text default static font from Needle CDN with absolute font URL support - `DragControls` EventList support #### Fixed - UI Text font URL resolution when loading GLBs from external hosts (e.g. CDN) - `AudioSource` spatial rolloff factor and `play()` reliability - `Animation` `play()` with `{ exclusive: false }` not stopping already-running clips - XR lifecycle — spurious `onLeaveXR` calls for scripts that never entered XR - `OrbitControls` lookBounds lerp and distance-relative gizmo sizes - `CursorFollow` self-intersection and snapToSurface raycast direction - Vite `makeFilesLocal` and alias plugins now respect `vite.config` `base` - `three-mesh-bvh` worker failing to load in local dev server - `VideoPlayer` URL serializer tree-shaken out in code-only projects - `ReflectionProbe` not cleaning up overrides when removed ## [5.1.0-alpha.2] - 2026-04-13 - **NEW**: Scene Bindings (experimental) — auto-generated TypeScript types from your glTF scenes, providing typed access to nodes, components, and properties via `ctx.sceneData` or `needle.sceneData`. Types are generated automatically by a Vite plugin whenever your scene files change — no configuration needed. Works with any glTF/GLB assigned as `src` on `<needle-engine>`, including remote URLs and Needle Cloud assets. The API shape (particularly `$components` and `$object` accessors) may evolve based on feedback. Can be disabled with `dts: { enabled: false }` in your Vite plugin config. ```ts // fully typed, with autocomplete for every node and component const cam = ctx.sceneData.MyScene.MainCamera.$object; // THREE.PerspectiveCamera const orbit = ctx.sceneData.MyScene.MainCamera.$components.OrbitControls; // typed! ``` - **NEW**: SSR support (experimental) — import Needle Engine in Node.js/SSR frameworks (SvelteKit, Next.js, Nuxt) without `ReferenceError` crashes. The engine now provides SSR-safe base classes and skips browser-dependent initialization on the server. Core rendering still happens client-side — SSR support means your app can import and reference engine code server-side without errors. - **NEW**: JSX type declarations for `<needle-engine>` and other web components — first-class support for React, Preact, SolidJS, and other JSX-based frameworks with full autocomplete and type checking - **NEW**: `needle` shorthand (experimental) — quick access to the current engine context from anywhere without passing `ctx` around. Works in React/Svelte/Vue components, button handlers, or plain JavaScript. SSR-safe. ```ts import { needle } from "@needle-tools/engine"; needle.scene.traverse(obj => { ... }); // access the three.js scene needle.renderer; // access the WebGLRenderer needle.sceneData.MyScene.Camera.$components.OrbitControls.autoRotate = true; ``` - **NEW**: `context.lights` array and `context.mainLight` getter for easy access to all scene lights and the primary directional light - Add: `needlePlugins()` can now be called without arguments — the Vite command is resolved automatically. This simplifies setup in frameworks like SvelteKit where `defineConfig` doesn't expose the command: ```js export default defineConfig({ plugins: [sveltekit(), needlePlugins()] }); ``` - Fix: BloomEffect and Sharpening were pulling in the entire `postprocessing` library even in projects that don't use postprocessing, increasing bundle size unnecessarily - Fix: SceneSwitcher now shows the object name in the URL when referencing scene objects (instead of just an index) - Improved: Vite plugin reliability (fewer unnecessary reloads, cleaner log output) ## [5.1.0-alpha.1] - 2026-04-10 - Add: `AnimatorControllerBuilder` for building animator controllers from code (experimental) - Add: XR global events now return an unsubscribe function + `onBeforeXRSessionRequest` event - Add: `getComponent` by string name (experimental) - Add: FastHDR (PMREM) support for `GroundProjection` - Fix: `setParamWithoutReload` losing URL hash - Fix: Physics treeshaking when used in code-only projects - Improved: Vite logger with "latest" symlink, mobile fix, and more readable timestamps (at `node_modules/.needle/logs`). This is useful for local AI to help debug ## [5.1.0-alpha] - 2026-04-07 #### Networking - Add: VOIP `volume` property and `speaking` event - Add: `onSyncInstantiate` and `onSyncDestroy` callbacks - Change: `requestOwnership` now returns a `Promise` - Change: `addComponent` generates deterministic component GUIDs for reliable networking of runtime-added components - Change: `syncInstantiate` automatically adds to prefabProvider and assigns GUID #### Rendering - Add: MaterialX Voronoi node "cell" output - Add: Postprocessing tests - Change: Postprocessing moved to core — accessible via `context.postprocessing` and exported from `@needle-tools/engine` - Improved: Tonemapping without other postprocessing effects is now applied directly to the renderer, avoiding an unnecessary postprocessing pass - Fix: MaterialPropertyBlock multimaterial change from opaque to transparent #### XR - Improved: iOS AppClip AR session now opens reliably on first visit and first tap - Fix: XR light intensity in scaled sessions #### UI - Fix: HTML mobile icon not rendering - Fix: UI `Text` component absolute font URL handling ## [5.0.4] - 2026-04-20 - Fix: VideoPlayer not working when tree-shaking is enabled due to URL serializer being removed - Fix: ReflectionProbe not cleaning up `envMapRotation` and `envMapIntensity` overrides when removing envMap ## [5.0.3] - 2026-04-08 - Add: PMREM / FastHDR support for GroundProjection with shader-based blurriness, blending, and alpha controls - Fix: MaterialPropertyBlock multi-material change from opaque to transparent - Improved: OrbitControls JSDoc for `targetBounds` ## [5.0.2] - 2026-04-03 - Updated `@needle-tools/materialx` to 1.6.0: - UV coordinate convention handling (glTF ↔ OpenGL) — fixes UV-dependent effects like displacement and procedural noise in the browser - Material-level ambient occlusion for `gltf_pbr` materials per the glTF specification - Visual graph editor for interactive MaterialX authoring - Fix: Light intensity in scaled AR session ## [5.0.0] - 2026-03-27 - **NEW**: Compression support for EXR skybox and environment textures (powered by Needle's [FastHDR](<https://engine.needle.tools/docs/explanation/fasthdr.html>)): - 10x faster than EXR - 95% less GPU memory - Zero framedrops - **NEW**: Support for Vite 8, now powered by Rolldown (Rust) for extremely fast bundling - **NEW**: MaterialX *Lights and Magic* update: - Lights and shadow suppport: point lights, spot lights, directional lights - Displacement: full support for offset and vector displacement - Transparency Modes: auto-detection and support for opaque, transparent, and masked material rendering modes - See - Change: OrbitControls now uses `lookAtTarget` and `lockLookAtTarget` instead of a LookAtConstraint component. The LookAtConstraint component has been deprecated. - Change: EventList `addEventListener` now returns a method that can be called to remove the callback function again: `const remove = myEventList.addEventListener(() => { ... })` - Change: Rapier Physics colliders will now just be disabled instead of removed from the physics world when a Collider component becomes inactive. - Change: Postprocessing now has an `adaptiveResolution` option (default true) which can automatically scale down resolution slightly for Retina or high pixel density screens if performance drops (See the `Volume` component for more information) - Improved: Networking types (Typescript) - Improved: Dependencies chunking for faster loading and improved LCP score(Largest Contentful Paint) - Fix: NextJS support ## [4.16.4] - 2026-03-18 - Fix: Splines catmullrom tension - Fix: `focus-rect` attribute for e.g. `<needle-engine focus-rect=".mydiv" src="..."></needle-engine>` - Fix: Vite plugins process exit on `SIGINT` - Improved `activeInHierarchy` performance - Improved `Graphics.blit` performance - Improved Postprocessing performance ## [4.16.3] - 2026-03-15 - VideoPlayer default `renderMode` set to `MaterialOverride` ## [4.16.2] - 2026-03-11 - Improve: ReflectionProbe now uses integrated box intersection and gizmo - Improve: ReflectionProbe `center` and `size` now have default values and improved JSDoc documentation - Improve: Comprehensive TypeScript declarations for Vite and Next.js plugins with full JSDoc, `@param`, `@returns`, and `@example` tags for API documentation (NE-6952) - Improve: Plugin type declarations are now auto-generated from source - Remove: `loadMaterialX` vite plugin setting (no longer needed) ## [4.16.1] - 2026-03-09 - Fix: Regression causing error in react ## [4.16.0] - 2026-03-05 - **NEW**: `makeFilesLocal` build option overhauled — builds can now be fully self-contained and work offline. The plugin downloads external CDN assets at build time and bundles them locally. This is essential for playable ads, app stores that require single-origin or self-contained bundles, offline-capable PWAs, and restricted hosting environments. Supports auto-detection of used features, per-feature opt-in/opt-out, and platform presets. Covers Draco decoders, KTX2 transcoders, MaterialX, WebXR input profiles, skybox/environment textures, Google Fonts, third-party scripts, and more. Example in `vite.config.js`: ```js needlePlugin({ makeFilesLocal: "auto" // auto-detect and download only what your project uses }) // or with fine-grained control: needlePlugin({ makeFilesLocal: { enabled: true, features: ["draco", "ktx2", "fonts"], excludeFeatures: ["xr"] } }) ``` - Add: `showBalloonMessage` now supports `duration`, `once`, and `key` options for controlling message display duration and updating existing messages - Add: `needleAI` vite plugin — when using Claude Code in a Needle Engine project, the engine automatically provides a project-aware AI skill with Needle Engine context - Add: DragControls now warns when used on static objects that won't update their transforms - Add: AR overlay support for AppClip sessions - Improve: Stable three.js chunk names in production builds, enabling CDN import maps with predictable URLs - Improve: USDZ export now uses `"string"` type for input variable names for better spec compatibility - Improve: Gizmo rendering uses consistent font from CDN - Improve: needle-menu layout with correct padding and minimum width for icon-only elements - Improve: Vite project template aligned with online template - Improve: Updated MaterialX dependency - Improve: JSDoc documentation - Fix: ReflectionProbe support for Blender workflows - Fix: Mac build error ("-50" error) - Fix: PWA defaults when package name is missing - Fix: Improved error handling in MaterialX importer ## [4.15.0] - 2026-02-27 - **NEW**: Accessibility support with screen reader overlay. The engine now maintains a visually-hidden DOM tree mirroring 3D scene objects with ARIA roles and labels. Components like Button, Text, DragControls, and USDZ behavior components automatically register accessible elements. - Add: `AccessibilityManager` accessible via `context.accessibility` for managing accessible elements, focus, and hover announcements - Add: ReflectionProbe now supports assigning a URL string as texture (for Blender workflows) - Update: Networking backend migrated to Cloudflare Durable Objects for improved scalability, per-room isolation, and reduced latency - Improved MaterialPropertyBlock documentation with examples for material swapping behavior and override management - Improved documentation for Networking, OneEuroFilter, and needle-button web component ## [4.14.0] - 2026-02-19 - Add: MaterialPropertyBlock support. This allows you to change material properties of objects without breaking batching and instancing. It can be used by calling `const block = MaterialPropertyBlock.get(myObject);` and then set or remove overrides on the block. This even supports the same material being rendered as transparent for one object and opaque for another. - Add: Support of ReflectionProbe + Lightmap rendering on the same object - Add: CustomShader (Unlit) support with VideoPlayer component - Improved `?stats` console logs with info about shaders and used memory - Improved documentation ## [4.13.1] - 2026-02-13 - Improved code documentation across the engine - Improved ContactShadows to allow updating darkness and opacity dynamically at runtime - Fix: Support for Lightmaps and ReflectionProbes on the same object - Fix: Eventlist bug with instantiation ([Forum post](<https://forum.needle.tools/t/camera-orbit-controls-nan-in-new-scene/2779/6>)) ## [4.13.0] - 2026-02-10 - **NEW**: Needle Engine MaterialX loader added to core. No extra dependency to @needle-tools/materialx is required anymore - Fix: ContactShadows rendering - Fix: Memory issue caused by ReflectionProbes component ## [4.12.5] - 2026-02-09 - Update three.js dependency - Minor log improvements in development mode ## [4.12.4] - 2026-02-05 - Fix: WebXR image tracking support for multiple images (iOS + Android) - Change: Animation and Animator components now checks in local dev if the root object to be animated is marked as static and won't automatically update matrices - Improved iOS WebXR balloon message rendering to not overlap with camera or menu button ## [4.12.3] - 2026-02-04 - Add: `getComponentInChildren` and `getComponentInParent` now expose the `includeInactive` parameter to include inactive objects in the search - Change: Improved XR `sessiongranted` temporary scene design (removing temporary objects in AR and adding support for custom logo display while the AR session is initializing) - Fix: iOS WebXR canvas size for screenspace UI rendering - Fix: iOS WebXR UI InputField support - Fix: Invalid input event causing issue in OrbitControls when pressing multiple mouse buttons at the same time ## [4.12.2] - 2026-02-03 - Add: `showBalloonMessage` now also render in AR sessions - Fix: iOS WebXR DOM-Overlay fixed - Fix: iOS WebXR custom Quit AR button fixed ## [4.12.2] - 2026-02-03 - **NEW:** WebXR support for iOS - Your AR experiences now launch instantly on iPhone and iPad without app installation. Just tap "Enter AR" and you're in. Powered by Needle Go AppClip, combining Apple's excellent AR tracking with standards-compliant WebXR. Try it at [appclip.needle.tools](https://appclip.needle.tools) - **NEW:** Intellisense support for the `<needle-engine>` web component and its attributes, both in HTML and in code. The `custom-elements.json` allows for VSCode intellisense support, while `HTMLElementTagNameMap` and `get/setAttribute` overloads bring code completion and documentation. - Add: exposed `createCollider` API for the Rapier physics engine - Add: `beforeLODExport` callback for USDZ export. This allows overriding which LOD level gets exported per object. - Add: `?spector=#frame` URL parameter to enable a Spector.js capture on the specified frame number after page load. Make sure to install the [Spector.js browser extension](<https://chromewebstore.google.com/detail/spectorjs/denbgaamihkadbghdceggmchnflmhpmk?pli=1>). You can optionally specify a frame number for capturing: `?spector=15`. - Add: auto-registration of custom elements for easier discovery of available web components in Needle Engine. You can disable this feature by setting `noCustomElementData` to false in vite config. To manually register custom elements data, add it to your workspace or `.vscode/settings.json` via the `html.customData` setting. - Add: Support for rotation and scaling in DropListener component - Improve: VisionOS and iPad detection for better WebXR compatibility - Improve: WebXR session flow and error handling - Improve: QuickLook integration - disabled by default in WebXR component, shows "Open in Quicklook" button - Improve: SceneSwitcher now supports multiple scene switchers referencing the same asset reference - Improve: DragControls smoothed velocity calculations and region support - Improve: Detection of user interactions to enable media playback - Improve: JSDoc documentation for Everywhere Actions and other components - Fix: issue with callbacks on freshly destroyed components when leaving XR sessions - Fix: Instancing issue with growing vertex/index buffers when not necessary - Fix: Issue with `<needle-engine>` element being moved in the DOM - Fix: Better type declarations in package.json ## [4.11.5] - 2025-10-31 - Fix: Timeline cloning with `instantiate` ([forum 2733](<https://forum.needle.tools/t/2733>)) - Fix: Renderer `sharedMaterials` being null in awake - Fix: Issue where lightmapped materials were cloned - Fix: Apply lighting intensity multiplier in root scene - Fix: GLTF extensions when loading scene with Blob URL - Improve JSDoc documentation ## [4.11.4] - 2025-10-24 - Add: `qrcode-logo-src` attribute to `<needle-engine>` web component to override the logo displayed in the QR code button. Requires PRO license. - Improve JSDoc documentation ## [4.11.3] - 2025-10-21 - Fix: See-Through with MeshPhysicalMaterial ## [4.11.2] - 2025-10-20 - Change: Animation component disable `randomStartTime` - Change: Vite build build pipeline plugin increased default max wait time to 60 seconds. This time is now exposed via `needlePlugins` user config, e.g. to increase it to 5 minutes write `needlePlugins(command, needleConfig, { buildPipeline: { maxWaitDuration: 300_000 } })` in your `vite.config.js`. ## [4.11.1] - 2025-10-16 - Fix: WebXR / VR issue where trying to access missing geometry during raycasting caused errors - Change: ScrollFollow now only applies when scroll has changed. It also immediately jumps to the target position on the first update instead of interpolating (avoiding interpolation through long timeline animations). - Change: SplineWalker now has an option to disable LookAt. It also received a `pullStrength` property which controls how tightly the object moves along the spline. - Improved: OrbitControls and ViewBox interaction ## [4.11.0] - 2025-10-15 - **NEW**: SeeThrough component. With this component you can easily fade-out objects between the camera and a reference point in the scene. See the [See-Through sample](<https://see-through-walls-z23hmxbz1kjfjn.needle.run/>) to see it in action - **NEW**: [Droplistener sample](<https://engine.needle.tools/samples/droplistener/>) - Add: CursorFollow option to follow cursor on the full page, even when a user moves their mouse outside of the `<needle-engine>` element. - Add: CursorFollow `snapToSurface` option to automatically snap the object to the surface below the cursor. - Add: Object3D `raycastAllowed` property to disable raycasting on specific objects (e.g. for performance reasons or to ignore invisible helper objects) - Add: OrbitControls `targetBounds` property which can be used to constrain the OrbitControls target within a defined area in the scene. A Object3D can be assigned to the property. The position and scale of this object will be used. - Add: *Experimental* - Vite plugin to generate `needle-app.js` which encapsulates the whole website into a single web component. The `needle-app.js` file will be emitted next to index.html and can be used to directly embed the website and 3D assets into another website by importing `<url>/needle-app.js` and then using the `<needle-app></needle-app>` web component. - Add: Object3D `contains(otherObject: Object3D)` method to check if an object is a child of another object in the scene graph - Fix: three nodes update camera for TSL - Fix: Renderer lightmaps are now updating `sharedMaterials` - Fix: `Gizmos.DrawWireMesh` matrix - Fix: Image UI color was sometimes not correctly calculated for Button color states when used with the CanvasGroup component - Fix: ScrollMarker issue - Improved JSDoc documentation ## [4.10.4] - 2025-10-08 - Update: three-animation-pointer dependency to 1.0.4 to support KHR_node_visibility extension - Documentation improvements ## [4.10.3] - 2025-10-06 ### Needle Engine - Add: [`ScrollFollow`](<https://engine.needle.tools/docs/api/ScrollFollow>) timeline markers can now be defined in HTML only and don't require markers to be present in the Timeline anymore. This means any timeline animation can now be mapped to HTML content by annotating the HTML elements. For example `<div data-timeline-marker="2.5">` will define that the timeline should reach the time 2.5 seconds when this element becomes visible in the viewport. The [bike-scroll-follow example on Github](<https://github.com/needle-engine/needle-engine-bike-scrollytelling/tree/main>) will be updated to use this new feature soon ([example index.html](<https://github.com/needle-engine/needle-engine-bike-scrollytelling/blob/main/Scroll%20Bike%20Website/index.html>)). ## [4.10.1] - 2025-09-30 - Change: ViewBox `referenceFieldOfView` can now set to `-1` to automatically take the camera's field of view at runtime - Fix: ViewBox evaluation order is now hierarchy-independent (Previously OrbitControls panning might be applied after ViewBox calculations if the ViewBox component was on a parent object) ## [4.10.0] - 2025-09-29 - **NEW**: [**Scrollytelling Bike Example**](https://scrollytelling-bike-z23hmxb2gnu5a.needle.run/) – This example uses ViewBox, FocusRect and ScrollFollow to create a scrollytelling experience. All project files are [available on Github](<https://github.com/needle-engine/needle-engine-bike-scrollytelling>). - **NEW**: HoverAnimation component. Use this component to get a scale hover animation of an object when the cursor is hovering over the object or one of it's children. - **NEW**: ViewBox component. Use this component to automatically perfectly fit your 3D scene into the camera view. Try the Scrollytelling Example to see it in action, test the [example on Stackblitz](<https://stackblitz.com/edit/needle-engine-view-box-example?file=src%2Fmain.ts>) or see the [ViewBox documentation](<https://engine.needle.tools/docs/api/ViewBox>) for details. - Add: `fitCamera` function - Add: `<needle-engine poster>` attribute. It works with an URL to an image that should be shown as a poster image. If no URL is assigned then the poster that is automatically generated during the first frame will be used. - Add: `<needle-engine focus-rect="<html_selector">` attribute. Assign a HTML selector to the attribute to use a specific HTML element on screen offset the 3D camera center to the center of the HTML element. (The same can be done programmatically using `ctx.setCameraFocusRect(<html_element|DOMRect>)`) - Add: Timeline [ScrollMarker](<https://engine.needle.tools/docs/api/ScrollMarkerModel>) for Unity and Blender timeline animations to control timing based on HTML visibility. - Fix: Renderer `material` accessing error when component was not yet initialized - Fix: Poster screenshot glitch during the first frame (development only) - Fix: HTC Vive Focus 3 controller movement ([forum post](<https://forum.needle.tools/t/movement-via-controller-in-vr-with-htc-vive-focus-3/2718>)) - Change: Loading display does not show Needle logo anymore by default - Change: Use fallback raycast method for lowpoly meshes while the faster mesh BVH is being generated ## [4.9.3] - 2025-09-15 - Fix: SpriteRenderer index issue when animated where animation precision issue was causing the wrong sprite to be selected ([issue](<https://forum.needle.tools/t/switching-sprite-images-via-timeline-causes-ghosting-glitches-when-exported/2709>)) - Fix: Scaling scene in AR with multitouch causing camera projection issue for a frame ([issue](<https://forum.needle.tools/t/3d-assets-warping-on-rotation-in-ar>)) ## [4.9.1] - 2025-09-11 - Update [ScrollFollow component](<https://engine.needle.tools/docs/api/ScrollFollow>) documentation - Update Renderer `sharedMaterial` typescript type ## [4.9.0] - 2025-09-08 - **NEW**: [**Scrollytelling Example**](<https://scrollytelling-2-z23hmxby7c6x.needle.run/>) - **NEW**: Spline support with SplineContainer and SplineWalker components - SplineContainer: Holds the spline data. Use `addKnot` and `removeKnot` to modify the spline and `getPointAt(t01:number)` to get a point on the spline curve. Splines currently only support cubic interpolation. - SplineWalker: Component for moving objects along a spline. It can automatically move along the spline or be controlled by animations or other components by setting the `position01` property. - **NEW**: [Attractor component](<https://engine.needle.tools/docs/api/Attractor>) – Add Rigidbodies to the list to attract physical objects towards a point in space (or apply repulsion). - **NEW**: [CursorFollow component](<https://engine.needle.tools/docs/api/CursorFollow>) – Does what it says! Add the component to an object to make it follow your cursor (or touch) on screen. - **NEW**: [ScrollFollow component](<https://engine.needle.tools/docs/api/ScrollFollow>) – Use browser scroll to influence animation, audio, light... in your scene. - Add: WebXRImageTracking methods for `setPrimaryImage` and `addImage` to simplify image tracking changes at runtime. - Add: Object3D `worldForward` can now be set (e.g. `myObject.worldForward = new Vector3(0,0,1)`) - Fix: [XR] Issue where NeedleXRSession would invoke controller-added callback twice - Fix: [XR] Issue where invalid value in XRControllerMovement would break rendering when using hand tracking - Fix: [XR] NeedleXRController getButton for xr-standard-trigger and getStick("primary") - Fix: Capsule collider height - Fix: Issue where disposing object resources would cause errors in three.js ## [4.8.9] - 2025-09-05 - Add: OrbitControls `fitCamera` has now additional options for `fitDirection`, `cameraOffset`, `relativeCameraOffset`, `targetOffset` and `relativeTargetOffset` giving more fine-grained control over the final camera view where necessary ([Stackblitz](<https://stackblitz.com/edit/needle-engine-fit-camera-options?file=src%2Fscripts%2FPanelsAndText.ts,index.html,src%2Fmain.ts>)). - Add: ContactShadows properties to `fitShadows` and static `ContactShadows.auto()` for more fine-grained control over which objects to fit the shadow to or to apply slight offsets to the shadow plane - Add: NestedGltf component `loaded` event property - Fix: OrbitControls should not override the camera FOV - Fix: Updating the `scene.background` when setting both <needle-engine> `background-color` and `background-image` or switching between one or the other - Fix: When setting `<needle-engine environment-image="url">` the assigned image should be respected by the engine and loaded glTF files (even if they bring their own skybox and environment images) - Fix: Issue with `<needle-engine autoplay>` animation speed and when using the AnimationUtils.autoplay feature where animations would play faster than expected - Fix: Minor fixes in Vite plugins - Change: ReflectionProbes are not applied on Objects that use lightmapping ## [4.8.8] - 2025-08-29 - Fix: iOS AR image tracking bug where having multiple `WebXRImageTracking` components in the scene cause unexpected behaviour or invalid USDZ files - Fix: DropListener `loadFromURL` now returns the promise to make awaiting the loaded asset much easier - Fix: Issue where `<needle-engine autoplay>` would play animations faster than expected - Change: OrbitControls with locked target constraint is now updating the constraint position when calling e.g. `setTargetPosition` - Add: `setCameraFocusRect` method on Needle Context for easier responsive layouting. With this you can e.g. overlay the webgl scene with HTML elements and pass in a div element for keeping important elements visible. [Example 1 Website](<https://responsive-layout-z23hmxb22no6t.needle.run/>) | [Code on Stackblitz](<https://stackblitz.com/edit/needle-engine-camera-focus-rect?file=src%2Fsidebar.ts,index.html,src%2Fmain.ts>) [![](https://cdn.needle.tools/static/images/changelog/4.8.8-focus-thumbnail.jpg)](<https://responsive-layout-z23hmxb22no6t.needle.run/>) [Example 2 Website](<https://responsive-layout-click-example-z23hmxbzuyk6y.needle.run/>) | [Code on Stackblitz](<https://stackblitz.com/edit/needle-engine-camera-focus-rect-click-to-move?file=index.html,src%2Fmain.ts>) [![](https://cdn.needle.tools/static/images/changelog/4.8.8-focus-2-thumbnail.jpg?)](<https://responsive-layout-click-example-z23hmxbzuyk6y.needle.run/>) ## [4.8.7] - 2025-08-27 - Add: New [@needle-tools/three-animation-pointer](<https://www.npmjs.com/package/@needle-tools/three-animation-pointer>) package - Add: `loadPMREM(<url>)` function ## [4.8.6] - 2025-08-20 - Bump three dependency to fix issue caused by KTX2Exporter ## [4.8.5] - 2025-08-20 - Add: Much faster loading for skyboxes and environment maps when using presets. E.g. `<needle-engine environment-image="studio"></needle-engine>`. Supported values are `studio`, `blurred-skybox`, `quicklook`, `quicklook-ar` - Change: TransformControls now also enable `fastMode` on the SyncedTransform component - Change: The mobile javascript console now needs to be explictly enabled using the `?console` flag. This change has been made to improve the local development experience. Previously the javascript console would be initialized in local development environments but stay invisible until e.g. an error would be detected. This did sometimes cause performance issues when very large objects would be logged in development ## [4.8.4] - 2025-08-18 - Update `@needle-tools/gltf-progressive` dependency which adds a `waitForFirstCapture` bool option to `awaitLoading(<opts>)`. With this you can call `manager.awaitLoading({waitForFirstCapture:true})` to get a promise that does not resolve until the next requested LOD levels have finished to load. [**Here**](<https://lods-loading-overlay-z23hmxbz29h8vr.needle.run/>) is an example deployed to Needle Cloud + [here](<https://stackblitz.com/edit/needle-engine-wait-for-lods?file=src%2Fmain.ts>) is a example on Stackblitz which makes use of this feature to add a custom loading overlay. - Fix: When using Needle Engine in Gemini Editor the webrtc dependency caused issues due to Gemini making `getUserMedia` read-only. [**Example React Shopping App**](<https://reactshoppingcart-z23hmxbzcfkmf.needle.run/>) built by Gemini with Needle Engine ([Code on Stackblitz](<https://stackblitz.com/edit/needle-react-shopping-cart-2?file=src%2FApp.tsx,index.html,src%2Fmain.tsx>)) - Fix: When using pre-bundled Needle Engine (e.g. from jsdelivr) the mesh-bvh worker path was not correctly resolved - Change: `<needle-engine>` CSS z-index setting where the `<needle-menu>` element would be rendered above elements outside the `<needle-engine>` component. This would cause issues where e.g. a sidebar should overlay the page. - Change: Reduce default z-index for Needle loading logo ## [4.8.3] - 2025-08-18 - Change: Clamp devicePixelRatio to `2` by default. This can be overriden by setting the Needle Engine Context's `devicePixelRatio` to e.g. `window.devicePixelRatio` - Update `@needle-tools/gltf-progressive` dependency to expose `overrideLodLevel`. This can be used to override which LOD level will be loaded instead of calculating the LOD level based on screen coverage: For example `context.lodsManager.manager!.overrideLodLevel = 0;` will always load the highest quality mesh + texture ## [4.8.1] - 2025-08-14 - Fix: SceneSwitcher dispose of background and environment texture causing lighting issues when `useSceneLight` is disabled in SceneSwitcher component - Fix: Detection of model/gltf+json by file header ## [4.8.0] - 2025-08-12 - Add: `Gizmos.DrawWireBox` now takes an optional `rotation` parameter - Add: Physics `boxOverlap` function - Fix: Vite plugin improvements - Fix: Issue where re-applying Postprocessing effects with custom devicePixelRatio did falsely reset devicePixelRatio - Update `@needle-tools/gltf-progressive` to version 3.2.0 with experimental javascript worker support. It can currently only be enabled by adding the URL query parameter `?gltf-progressive-worker` ## [4.7.4] - 2025-08-07 - Update `@needle-tools/gltf-progressive` to version 3.1.1 ## [4.7.3] - 2025-08-06 - Add: OrbitControls `rotateUp(<radians>)` function - Add: OrbitControls support for setting `targetElement` (e.g. `orbitControls.targetElement = myNewHtmlElement;`) - Fix: RemoteSkybox loading relative URIs like "folder/image.exr", catch errors in loadAsync - Update gltf-progressive dependency with improved performance when using skinned meshes and a concurrent LOD request limit (default: 100 concurrent requests) ## [4.7.2] - 2025-08-04 - Add: `loading-blur` attribute to `<needle-engine>` web component. With this attribute the 3D scene will be blurred using CSS during loading of initial LOD level. This feature can be used to hide initial low-resolution textures and meshes while already getting an interactive preview visible in the browser (e.g. when displaying high quality product models where the 3D model download should be fast and not block the website but low-res assets should never be visible to the user) Currently `loading-blur` is disabled by default but can simply be enabled: - Enable default blur: `<needle-engine loading-blur></needle-engine>` - Or to control the blur amount a pixel value can be passed in `<needle-engine loading-blur="30px">` - Add: You can now await LOD loading at any time by calling `context.lodsManager.manager?.awaitLoading()`. The method accepts an optional options argument and returns a promise that will resolve when all requested LOD level during the next frame have completed loading. Please review the jsdoc code documentation for details. - Add: The `physics.raycast` options now accept an optional argument (`allowSlowRaycastFallback`) which controls wether or not the traditional three.js `raycast` method is allowed. If this parameter is set to false then only objects with a finished bvh mesh will be used for raycasting to ensure raycasts are always fast and never fallback to the slow route. This is especially important for relative frequent raycasts like mouse-movements or camera-target updates where it's not crucial if objects are ignored for a few frames. Needle Engine does automatically calculate mesh BVHs for all meshes in the scene on a worker at the first time they're discovered to ensure optimal performance. - Add: OrbitControls methods for `pan(<delta-x>, <delta-y>)`, `zoomIn(<scale>)` and `rotateLeft<angleInRadians>`. These methods can be used to control camera movement from code or via custom key-bindings. - Update gltf-progressive which adds support awaiting LOD level + improved LOD level calculations where meshes have multiple primitives/submeshes. - Fix: `useKeys` in OrbitControls - it requires `tabindex` on the `<needle-engine>` web component to receive keyboard events - Fix: Clamp of tonemapping exposure in AgX - Fix: Issue in Vite plugin with logging of very large objects ## [4.7.1] - 2025-07-31 - Add: LODsManager parameter `skinnedMeshAutoUpdateBoundsInterval` - Fix: Issue where model fetch with query parameters was constructing a wrong URL ## [4.7.0] - 2025-07-28 - Improved Postprocessing performance and stability - [Live Example](<https://antialiasing-and-postprocessing-zubcksz1o8daw.needle.run/>) - Fix: Issue where Tonemapping would not be applied - Change: Improve `<needle-engine background-image="<url>" />` support and deprecate the old `skybox-image` attribute ## [4.6.3] - 2025-07-25 - Update Vite alias plugin to make sure the same postprocessing module is used - Improve postprocessing stability - Fix: Postprocessing with transparent background ## [4.6.2] - 2025-07-23 - Postprocessing performance and stability improvements - Add: Custom postprocessing effects can now use `PostProcessingEffectPriority` to ensure effects are correctly sorted (e.g. before DepthOfField) - Fix: Postprocessing multisampling (MSAA) causing issues with performance - Fix: `screenshot` correctly handling custom `devicePixelRatio` ## [4.6.1] - 2025-07-17 - Fix: Post-processing effects ordering and gamma correction handling - Fix: Renderer and ReflectionProbe update behaviour where changing the scene environment texture would not affect certain objects anymore - Fix: ReflectionProbe should not be applied if the component is inactive (e.g. on a disabled Object3D) - Fix: Internal resource dispose error when destroying objects with custom ShaderMaterials with certain uniform values ## [4.6.0] - 2025-07-14 - Add: Vite plugin to make remote assets local at build time. This currently supports google.font CSS and font assets as well as polyhaven HDRi/EXR textures. To use enable `makeFilesLocal` in your `vite.config.js`: ```js needlePlugins(command, needleConfig, { makeFilesLocal: true }), ``` - Change: AudioSource component `preload` option to `true` by default ## [4.5.8] - 2025-06-10 - Fix: QR code logo overlay now scales down for longer URLs and uses stronger error correction level ## [4.5.7] - 2025-06-10 - Fix: `instantiate({ visible: false })` should only set the root object's visible state ## [4.5.6] - 2025-05-21 - Add: `Cylinder` primitive to ObjectUtils - Add: QR code now displays the URL that will open - Fix: Issue where calling `NeedleXRSession.stop()` from within `update()` event caused an error ## [4.5.4] - 2025-05-21 - Add: DropListener now also allows custom file types - Fix: File loading range request url did not handle relative URLs properly - Fix: Vite built pipeline plugin ## [4.5.0] - 2025-05-21 - Add: `NeedleEngineModelLoader` namespace with methods to provide custom file loaders to load unsupported 3D model formats. For example to load STL files: ```ts import { NeedleEngineModelLoader } from "@needle-tools/engine"; import { STLLoader } from "three/examples/jsm/loaders/STLLoader.js"; // Register a callback for determining our custom loader mimetype NeedleEngineModelLoader.onDetermineModelMimetype(args => { // check if the mimetype is already provided by the server if (args.contentType === "model/stl") { return "model/stl"; } // use URL extension if available if (args.url.endsWith(".stl")) { return "model/stl"; } // check if first few bytes start with "solid" // this is a very naive check, but it works for most cases if(args.bytes[0] === 0x73 && args.bytes[1] === 0x74 && args.bytes[2] === 0x6c) { return "model/stl"; } return null; }); // Register a callback for creating our custom loader NeedleEngineModelLoader.onCreateCustomModelLoader(args => { if (args.mimetype === "model/stl") { const stlLoader = new STLLoader(); return stlLoader; } }); ``` - Add: Experimental attribute to autostart **AR**: `<needle-engine autostart="ar">` - Add: Modify the QR code button URL via `ButtonsFactory.instance.qrButtonUrl = https://yourwebsite.de` - Add: ContactShadows `manualUpdate` boolean. When enabled the ContactShadows component will not automatically re-render every frame. When enabled then set `needsUpdate=true` to manually schedule contact shadows re-render - Change: Needle Engine loading view is now transparent by default. The `loading-background` attribute can be used to add custom styling like `<needle-engine loading-background="#000" />`. Alternatively the `<needle-engine>` web component or background can be styled. - Removed: Web component attributes: `loading-background-color`, `loading-style`, `loading-text-color` - Fix: Vite HMR (Hot Module Replacement) working nicely with browser breakpoints and debugging - Fix: Debug stats (`?stats`) showing correct draw calls when using postprocessing - Fix: `findObjectOfType` does now also search components on the root scene object ## [4.4.6] - 2025-05-05 - Change: Networking disconnect() should reset state + leaveRoom does now reset allowEditing to true - Fix Vite prebundle engine with mesh bvh worker ## [4.4.5] - 2025-04-30 - Add: Support for easily adding an Animation component to the root object of a loaded glTF to automatically play animations. - Add: `loadAsset` function - Fix: OrbitControls issue where `fitCamera({immediate:true})` would not fit the camera immediately without lerping - Fix: Vite fetch public key causing build to fail ## [4.4.3] - 2025-04-29 - Add: Support for `getKeyDown`, `getKeyPressed` and `getKeyUp` to pass in key name to check the state of keyboard input, e.g. `context.getKeyDown(<key>)` - Add: License validation for webpack (nextjs) via access token or teamid. The `needleNext` plugin does now handle the license for passed in team or access tokens. For example the `next.config.js` can be modified like so `... }, { modules: { webpack }, license: {team: "needle"} })` to pass in the name of a team (or a Needle Cloud access token). - Change: License checks will now read the `NEEDLE_CLOUD_TOKEN` environment variable if no access token is provided. - Fix: SyncedTransform `fastmode` lerp - Fix: OrbitControls regression when calling `setCameraAndLookTarget` with a Camera object (or transform) where the forward direction (+Z) did not match the camera's look/render direction (-Z) ## [4.4.2] - 2025-04-24 - Fix: Vite license server timeout - Fix: Vite `manualChunks` should not be declared if `rollupOutput.inlineDynamicImports` is set to true ## [4.4.0] - 2025-04-17 **Added** - Add: The needle-engine web-component `contactshadows` attribute now allows you to specify a factor for controlling the darkness/lightness. E.g. `<needle-engine contactshadows="1">` will make the shadows appear darker vs. `<needle-engine contactshadows=".2">` will make the contact shadow appear lighter. - Add: The needle-engine web-component does now support transparency for `background-color`. For example: `rgba(255, 255, 100, .5)` or `#ffdddd99` or `transparent` are valid values: `<needle-engine background-color="rgba(255, 255, 100, .5)" />` - Add: `ObjectUtils.createPrimitive()` now supports scale as array e.g. `ObjectUtils.createPrimitive("Cube", { scale: [1, .25, 1] } );` - Add: Input `getGamepad(<index>)` function to query a connected gamepad. Example: `this.context.input.getGamepad()` - Add: `lookAtScreenPoint()` function which allows 3D object to look at points in 2D screen coordinates (e.g. your mouse position). **Example Component that makes the object look at the mouse** ```ts import { Behaviour, lookAtScreenPoint } from "@needle-tools/engine"; export class LookAtMouse extends Behaviour { update() { lookAtScreenPoint(this.gameObject, this.context.input.mousePosition, this.context.mainCamera); } } ``` - Add: Default environment lighting. If you don't configure any environment-image needle engine will now create a default scene to light your objects. Previously the scene was just black when the loaded model didn't contain any lighting information. - Add: SyncedTransform does now also sync scale changes - Add: SyncedTransform `freeOwnership()` method - Add: ReflectionProbe bounding box intersection check to automatically apply reflections to object's in a specific area (handled by the Renderer component) - Add: `devicePixelRatio` option on Needle Context. This option controls the window.devicePixelRatio set on the renderer by Needle Engine (default `auto`). It can be set to `manual` to disable this behaviour or a custom number which will then be set on the renderer or composer. **Fixed** - Fix: Implicit camera did not automatically set to skybox when using `background-image`. E.g. `<needle-engine background-image="<url>"> - Fix: Tonemapping falsely set tonemappingEsposure to undefined causing a black screen - Fix: `background-color` attribute was not always applied. E.g. `<needle-engine background-color="#ff3333">` - Fix: `screenshot()` checks if XR is presenting - Fix: Issue where MeshBVH worker import breaks for projects where the needle-engine vite plugins are not added to the plugins list - Fix: SceneSwitcher regression with `Object3D` objects in scenes array - Fix: SceneSwitcher preload was not using three.js FileLoader to re-use three's caching system - Fix: GroundProjection regression where background blurriness was hardcoded