@needle-tools/gltf-progressive 4.0.0-alpha.1 → 4.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/LICENSE +21 -0
- package/README.md +47 -11
- package/examples/modelviewer-multiple.html +4 -4
- package/examples/modelviewer.html +4 -4
- package/examples/offscreen/index.html +15 -0
- package/examples/offscreen/main.js +98 -0
- package/examples/react-three-fiber/index.html +2 -2
- package/examples/react-three-fiber/package-lock.json +482 -484
- package/examples/react-three-fiber/package.json +4 -4
- package/examples/react-three-fiber/src/App.tsx +76 -21
- package/examples/react-three-fiber/src/styles.css +2 -4
- package/examples/react-three-fiber/vite.config.js +2 -2
- package/examples/shared/example-utils.js +297 -0
- package/examples/shared/example.css +44 -0
- package/examples/shared/runtime.js +34 -0
- package/examples/threejs/index.html +6 -10
- package/examples/threejs/main.js +5 -23
- package/examples/webgpu/index.html +15 -0
- package/examples/webgpu/main.js +105 -0
- package/examples/worker-rendering/index.html +15 -0
- package/examples/worker-rendering/main.js +109 -0
- package/examples/worker-rendering/worker.js +166 -0
- package/gltf-progressive.js +1025 -669
- package/gltf-progressive.min.js +9 -9
- package/gltf-progressive.umd.cjs +9 -9
- package/lib/extension.d.ts +73 -7
- package/lib/extension.js +351 -111
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/loaders.js +17 -3
- package/lib/lods.debug.js +2 -2
- package/lib/lods.manager.d.ts +93 -15
- package/lib/lods.manager.js +331 -157
- package/lib/lods.promise.js +1 -1
- package/lib/plugins/modelviewer.js +1 -1
- package/lib/utils.internal.js +20 -6
- package/lib/version.js +1 -1
- package/lib/worker/loader.mainthread.js +4 -1
- package/package.json +10 -3
package/lib/loaders.js
CHANGED
|
@@ -116,7 +116,9 @@ function prepareLoaders() {
|
|
|
116
116
|
dracoLoader = new DRACOLoader();
|
|
117
117
|
dracoLoader[$dracoDecoderPath] = DEFAULT_DRACO_DECODER_LOCATION;
|
|
118
118
|
dracoLoader.setDecoderPath(DEFAULT_DRACO_DECODER_LOCATION);
|
|
119
|
-
|
|
119
|
+
// three r185+ auto-selects WASM (preferred) or JS based on platform support, and
|
|
120
|
+
// setDecoderConfig is deprecated (removed in r194). The gstatic decoder path hosts both
|
|
121
|
+
// decoders, so dropping the forced-JS config lets it use the faster WASM decoder.
|
|
120
122
|
dracoLoader.preload();
|
|
121
123
|
}
|
|
122
124
|
if (!ktx2Loader) {
|
|
@@ -143,8 +145,8 @@ const originalLoadFunction = GLTFLoader.prototype.load;
|
|
|
143
145
|
function onLoad(...args) {
|
|
144
146
|
const config = gltfLoaderConfigurations.get(this);
|
|
145
147
|
let url_str = args[0];
|
|
146
|
-
const url =
|
|
147
|
-
if (url
|
|
148
|
+
const url = tryResolveUrl(url_str);
|
|
149
|
+
if (url?.hostname.endsWith("needle.tools")) {
|
|
148
150
|
const progressive = config?.progressive !== undefined ? config.progressive : true;
|
|
149
151
|
const usecase = config?.usecase ? config.usecase : "default";
|
|
150
152
|
if (progressive) {
|
|
@@ -160,3 +162,15 @@ function onLoad(...args) {
|
|
|
160
162
|
return res;
|
|
161
163
|
}
|
|
162
164
|
GLTFLoader.prototype.load = onLoad;
|
|
165
|
+
function tryResolveUrl(url) {
|
|
166
|
+
try {
|
|
167
|
+
if (url instanceof URL) {
|
|
168
|
+
return url;
|
|
169
|
+
}
|
|
170
|
+
const base = globalThis.location?.href;
|
|
171
|
+
return base ? new URL(url, base) : new URL(url);
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}
|
package/lib/lods.debug.js
CHANGED
|
@@ -2,8 +2,8 @@ import { getParam } from "./utils.internal.js";
|
|
|
2
2
|
export const debug = getParam("debugprogressive");
|
|
3
3
|
let debug_RenderWireframe = undefined;
|
|
4
4
|
export let debug_OverrideLodLevel = -1; // -1 is automatic
|
|
5
|
-
if (debug) {
|
|
6
|
-
|
|
5
|
+
if (debug && typeof window !== "undefined") {
|
|
6
|
+
const maxLevel = 6;
|
|
7
7
|
function debugToggleProgressive() {
|
|
8
8
|
debug_OverrideLodLevel += 1;
|
|
9
9
|
if (debug_OverrideLodLevel >= maxLevel) {
|
package/lib/lods.manager.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Camera, Material, Object3D, Scene, Texture, Vector3, WebGLRenderer } from "three";
|
|
1
|
+
import { Box3, BufferGeometry, Camera, Color, Material, Matrix4, Object3D, Scene, Texture, Vector3, WebGLRenderer } from "three";
|
|
2
2
|
import { NEEDLE_progressive_plugin } from "./plugins/plugin.js";
|
|
3
3
|
import { PromiseGroupOptions } from "./lods.promise.js";
|
|
4
4
|
export type LODManagerContext = {
|
|
@@ -8,6 +8,29 @@ export declare type LOD_Results = {
|
|
|
8
8
|
mesh_lod: number;
|
|
9
9
|
texture_lod: number;
|
|
10
10
|
};
|
|
11
|
+
export declare const lodDebugColors: number[];
|
|
12
|
+
export type MeshLODSelectionOptions = {
|
|
13
|
+
geometry: BufferGeometry;
|
|
14
|
+
matrixWorld: Matrix4;
|
|
15
|
+
camera: Camera;
|
|
16
|
+
projectionScreenMatrix: Matrix4;
|
|
17
|
+
desiredDensity: number;
|
|
18
|
+
canvasHeight?: number;
|
|
19
|
+
currentLevel?: number;
|
|
20
|
+
boundingBox?: Box3 | null;
|
|
21
|
+
xrEnabled?: boolean;
|
|
22
|
+
debugDrawLine?: (a: Vector3, b: Vector3, color: number) => void;
|
|
23
|
+
warnMissingPrimitiveDensities?: boolean;
|
|
24
|
+
target?: MeshLODSelectionResult;
|
|
25
|
+
};
|
|
26
|
+
export type MeshLODSelectionResult = {
|
|
27
|
+
level: number;
|
|
28
|
+
primitiveIndex: number;
|
|
29
|
+
screenCoverage: number;
|
|
30
|
+
screenspaceVolume: Vector3;
|
|
31
|
+
centrality: number;
|
|
32
|
+
};
|
|
33
|
+
export declare function calculateMeshLODLevel(options: MeshLODSelectionOptions): MeshLODSelectionResult;
|
|
11
34
|
declare type LODChangedEventListener = (args: {
|
|
12
35
|
type: "mesh" | "texture";
|
|
13
36
|
level: number;
|
|
@@ -52,6 +75,8 @@ export declare class LODsManager {
|
|
|
52
75
|
static getObjectLODState(object: Object3D): LOD_state | undefined;
|
|
53
76
|
static addPlugin(plugin: NEEDLE_progressive_plugin): void;
|
|
54
77
|
static removePlugin(plugin: NEEDLE_progressive_plugin): void;
|
|
78
|
+
/** Read-only snapshot of the currently registered plugins, for inspection. Use {@link addPlugin} / {@link removePlugin} to modify the registry. */
|
|
79
|
+
static getPlugins(): readonly NEEDLE_progressive_plugin[];
|
|
55
80
|
/**
|
|
56
81
|
* Gets the LODsManager for the given renderer. If the LODsManager does not exist yet, it will be created.
|
|
57
82
|
* @param renderer The renderer to get the LODsManager for.
|
|
@@ -98,17 +123,64 @@ export declare class LODsManager {
|
|
|
98
123
|
private readonly _newPromiseGroups;
|
|
99
124
|
private _promiseGroupIds;
|
|
100
125
|
/**
|
|
101
|
-
*
|
|
126
|
+
* Returns a promise that resolves once all LOD requests initiated during the next render cycles have finished loading.
|
|
127
|
+
* This is useful for hiding low-resolution placeholders (e.g. with a loading overlay or CSS blur) until high-quality assets are ready.
|
|
128
|
+
*
|
|
129
|
+
* By default, the returned promise captures LOD loading requests for 2 frames and resolves when all of them complete.
|
|
130
|
+
* Use `waitForFirstCapture` if no LOD requests may happen immediately (e.g. after a scene switch).
|
|
131
|
+
*
|
|
132
|
+
* @param opts - Optional configuration for how long to capture and what to wait for. See {@link PromiseGroupOptions}.
|
|
133
|
+
* @returns A promise that resolves with `{ cancelled, awaited_count, resolved_count }` once all captured LOD loads complete (or the signal aborts).
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* // Wait for initial LODs to finish loading, then remove a blur overlay
|
|
138
|
+
* const result = await lodsManager.awaitLoading({
|
|
139
|
+
* frames: 5,
|
|
140
|
+
* signal: AbortSignal.timeout(10_000),
|
|
141
|
+
* });
|
|
142
|
+
* console.log(`Loaded ${result.resolved_count} of ${result.awaited_count} LODs`);
|
|
143
|
+
* document.querySelector('.blur-overlay')?.remove();
|
|
144
|
+
* ```
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```ts
|
|
148
|
+
* // Wait until at least one LOD starts loading before resolving
|
|
149
|
+
* await lodsManager.awaitLoading({ waitForFirstCapture: true });
|
|
150
|
+
* ```
|
|
102
151
|
*/
|
|
103
152
|
awaitLoading(opts?: PromiseGroupOptions): Promise<{
|
|
104
153
|
cancelled: boolean;
|
|
105
154
|
awaited_count: number;
|
|
106
155
|
resolved_count: number;
|
|
107
156
|
}>;
|
|
157
|
+
/** Track LOD work started outside this manager so {@link awaitLoading} waits for it too. */
|
|
158
|
+
trackLoadingPromise<T>(type: "mesh" | "texture", object: object, promise: Promise<T>): Promise<T>;
|
|
108
159
|
private _postprocessPromiseGroups;
|
|
109
160
|
private readonly _lodchangedlisteners;
|
|
110
|
-
|
|
111
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Register a listener that is called whenever a mesh or texture LOD level has finished loading and has been applied.
|
|
163
|
+
* The listener receives the type of asset (`"mesh"` or `"texture"`), the new LOD level, and the affected object.
|
|
164
|
+
*
|
|
165
|
+
* @param evt - The event type. Currently only `"changed"` is supported.
|
|
166
|
+
* @param listener - Callback invoked after a LOD swap completes.
|
|
167
|
+
* @return A function to unregister the listener.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```ts
|
|
171
|
+
* lodsManager.addEventListener("changed", ({ type, level, object }) => {
|
|
172
|
+
* console.log(`${type} LOD changed to level ${level}`, object);
|
|
173
|
+
* });
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
addEventListener(evt: "changed", listener: LODChangedEventListener): () => void;
|
|
177
|
+
/**
|
|
178
|
+
* Remove a previously registered `"changed"` event listener.
|
|
179
|
+
* @param evt - The event type (`"changed"`).
|
|
180
|
+
* @param listener - The listener to remove.
|
|
181
|
+
* @return `true` if the listener was found and removed, `false` otherwise.
|
|
182
|
+
*/
|
|
183
|
+
removeEventListener(evt: "changed", listener: LODChangedEventListener): boolean;
|
|
112
184
|
private constructor();
|
|
113
185
|
private _fpsBuffer;
|
|
114
186
|
/**
|
|
@@ -116,12 +188,28 @@ export declare class LODsManager {
|
|
|
116
188
|
*/
|
|
117
189
|
enable(): void;
|
|
118
190
|
disable(): void;
|
|
191
|
+
/**
|
|
192
|
+
* Manually trigger a LOD update for a scene and camera.
|
|
193
|
+
* Only needed when {@link manual} is set to `true` — otherwise LOD updates happen automatically on each render call.
|
|
194
|
+
*
|
|
195
|
+
* @param scene - The scene containing objects with progressive LODs.
|
|
196
|
+
* @param camera - The camera used to determine screen coverage and LOD levels.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* const lodsManager = LODsManager.get(renderer);
|
|
201
|
+
* lodsManager.manual = true;
|
|
202
|
+
* // ... later, trigger an update at a specific point:
|
|
203
|
+
* lodsManager.update(scene, camera);
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
119
206
|
update(scene: Scene, camera: Camera): void;
|
|
120
207
|
private onAfterRender;
|
|
121
208
|
/**
|
|
122
209
|
* Update LODs in a scene
|
|
123
210
|
*/
|
|
124
211
|
private internalUpdate;
|
|
212
|
+
private getRenderList;
|
|
125
213
|
/** Update the LOD levels for the renderer. */
|
|
126
214
|
private updateLODs;
|
|
127
215
|
/** Load progressive textures for the given material
|
|
@@ -138,18 +226,7 @@ export declare class LODsManager {
|
|
|
138
226
|
*/
|
|
139
227
|
private loadProgressiveMeshes;
|
|
140
228
|
private readonly _sphere;
|
|
141
|
-
private readonly _tempBox;
|
|
142
|
-
private readonly _tempBox2;
|
|
143
|
-
private readonly tempMatrix;
|
|
144
229
|
private readonly _tempWorldPosition;
|
|
145
|
-
private readonly _tempBoxSize;
|
|
146
|
-
private readonly _tempBox2Size;
|
|
147
|
-
private static corner0;
|
|
148
|
-
private static corner1;
|
|
149
|
-
private static corner2;
|
|
150
|
-
private static corner3;
|
|
151
|
-
private static readonly _tempPtInside;
|
|
152
|
-
private static isInside;
|
|
153
230
|
private static skinnedMeshBoundsFrameOffsetCounter;
|
|
154
231
|
private static $skinnedMeshBoundsOffset;
|
|
155
232
|
private calculateLodLevel;
|
|
@@ -162,4 +239,5 @@ declare class LOD_state {
|
|
|
162
239
|
readonly lastScreenspaceVolume: Vector3;
|
|
163
240
|
lastCentrality: number;
|
|
164
241
|
}
|
|
242
|
+
export declare function getLODColor(level: number, target: Color): Color;
|
|
165
243
|
export {};
|