streaming-gltf 1.0.1 → 1.0.3
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/package.json +11 -2
- package/tools/bake-progressive.mjs +36 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "streaming-gltf",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Streaming progressive glTF LOD renderer (BatchedMesh/InstancedMesh tiers, network-lazy GPU-eager LOD streaming, on-GPU position lerping) plus the local bake/convert + streaming-download pipeline (tools/bake-*.mjs).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"exports": {
|
|
10
10
|
".": "./index.js",
|
|
11
11
|
"./model-pool": "./examples/local-progressive/model-pool.js",
|
|
12
|
-
"./batched-far-tier": "./examples/local-progressive/batched-far-tier.js"
|
|
12
|
+
"./batched-far-tier": "./examples/local-progressive/batched-far-tier.js",
|
|
13
|
+
"./bake": "./tools/bake-progressive.mjs"
|
|
13
14
|
},
|
|
14
15
|
"files": [
|
|
15
16
|
"index.js",
|
|
@@ -35,6 +36,14 @@
|
|
|
35
36
|
"three": ">= 0.160.0",
|
|
36
37
|
"@pixiv/three-vrm": ">= 3.0.0"
|
|
37
38
|
},
|
|
39
|
+
"optionalDependencies": {
|
|
40
|
+
"@gltf-transform/core": "^4.3.0",
|
|
41
|
+
"@gltf-transform/extensions": "^4.3.0",
|
|
42
|
+
"@gltf-transform/functions": "^4.3.0",
|
|
43
|
+
"draco3dgltf": "^1.5.7",
|
|
44
|
+
"meshoptimizer": "^1.1.1",
|
|
45
|
+
"sharp": "^0.34.5"
|
|
46
|
+
},
|
|
38
47
|
"devDependencies": {
|
|
39
48
|
"@gltf-transform/core": "^4.3.0",
|
|
40
49
|
"@gltf-transform/extensions": "^4.3.0",
|
|
@@ -13,7 +13,7 @@ import draco3dgltf from 'draco3dgltf';
|
|
|
13
13
|
import sharp from 'sharp';
|
|
14
14
|
import { mkdir, writeFile, rm, stat, readFile } from 'node:fs/promises';
|
|
15
15
|
import path from 'node:path';
|
|
16
|
-
import { fileURLToPath } from 'node:url';
|
|
16
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
17
17
|
|
|
18
18
|
// Read a GLB and return its JSON chunk as a parsed object plus the original
|
|
19
19
|
// binary chunk bytes. Used to round-trip extensions gltf-transform doesn't
|
|
@@ -207,16 +207,6 @@ async function rewriteGlbJson(filePath, mutator) {
|
|
|
207
207
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
208
208
|
const repoRoot = path.resolve(__dirname, '..');
|
|
209
209
|
|
|
210
|
-
const INPUT = process.argv[2] || path.join(repoRoot, 'model.glb');
|
|
211
|
-
// Default output dir is named after the input basename so multiple models
|
|
212
|
-
// can be baked into examples/local-progressive/ side by side.
|
|
213
|
-
const inputBase = path.basename(INPUT, path.extname(INPUT));
|
|
214
|
-
const DEFAULT_OUT = path.join(
|
|
215
|
-
repoRoot,
|
|
216
|
-
'examples/local-progressive',
|
|
217
|
-
inputBase === 'model' ? 'output' : `output_${inputBase}`,
|
|
218
|
-
);
|
|
219
|
-
const OUT_DIR = process.argv[3] || DEFAULT_OUT;
|
|
220
210
|
const LODS_SUBDIR = 'lods';
|
|
221
211
|
|
|
222
212
|
// LOD recipes from highest to lowest detail. Each entry: { ratio, kind }
|
|
@@ -232,7 +222,14 @@ const EXTRA_LOD_STAGES = [
|
|
|
232
222
|
];
|
|
233
223
|
const TEX_LOD_SIZES = [2048, 1024, 512, 256, 128];
|
|
234
224
|
|
|
235
|
-
|
|
225
|
+
// Bake a single source GLB into the progressive LOD format consumed by
|
|
226
|
+
// ModelPool: writes `<outDir>/model.progressive.glb` (lowest LOD inline + a
|
|
227
|
+
// LOCAL_progressive extension) plus sibling LOD/texture files under
|
|
228
|
+
// `<outDir>/lods/`. Exported so a server can bake on demand without shelling
|
|
229
|
+
// out to the CLI; the CLI entry below is a thin wrapper around it.
|
|
230
|
+
export async function bakeProgressive(INPUT, OUT_DIR) {
|
|
231
|
+
if (!INPUT) throw new Error('bakeProgressive: input path required');
|
|
232
|
+
if (!OUT_DIR) throw new Error('bakeProgressive: output dir required');
|
|
236
233
|
console.log(`[bake] input : ${INPUT}`);
|
|
237
234
|
console.log(`[bake] output : ${OUT_DIR}`);
|
|
238
235
|
|
|
@@ -426,9 +423,20 @@ async function main() {
|
|
|
426
423
|
let target = Math.min(FAR_TRI_CAP * 3, u32.length);
|
|
427
424
|
target -= target % 3;
|
|
428
425
|
target = Math.max(96, target); // >=32 tris
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
426
|
+
// simplifySloppy asserts on some inputs (degenerate / tiny / non-
|
|
427
|
+
// manifold index buffers). The unskinned LOD is an optimization,
|
|
428
|
+
// not a correctness requirement: on failure keep the meshopt-
|
|
429
|
+
// decoded indices as-is (a heavier-but-correct far dot) rather
|
|
430
|
+
// than aborting the whole bake.
|
|
431
|
+
try {
|
|
432
|
+
const res = MeshoptSimplifier.simplifySloppy(u32, f32, 3, null, target, 1e9);
|
|
433
|
+
const out = Array.isArray(res) ? res[0] : res;
|
|
434
|
+
if (out && out.length >= 3) {
|
|
435
|
+
idxAcc.setArray(out instanceof Uint32Array ? out : new Uint32Array(out));
|
|
436
|
+
}
|
|
437
|
+
} catch (e) {
|
|
438
|
+
console.warn(`[bake] simplifySloppy skipped for unskinned LOD (${u32.length / 3} tris): ${e.message}`);
|
|
439
|
+
}
|
|
432
440
|
}
|
|
433
441
|
} else {
|
|
434
442
|
await cloneDoc.transform(
|
|
@@ -660,4 +668,16 @@ async function main() {
|
|
|
660
668
|
console.log(`[bake] saving on initial load: ${(100 - (rootSize/origSize)*100).toFixed(1)}%`);
|
|
661
669
|
}
|
|
662
670
|
|
|
663
|
-
|
|
671
|
+
// CLI entry: only run when invoked directly (`node tools/bake-progressive.mjs
|
|
672
|
+
// <in> <out>`), not when imported for the on-demand server bake path.
|
|
673
|
+
if (import.meta.url === pathToFileURL(process.argv[1] || '').href) {
|
|
674
|
+
const INPUT = process.argv[2] || path.join(repoRoot, 'model.glb');
|
|
675
|
+
const inputBase = path.basename(INPUT, path.extname(INPUT));
|
|
676
|
+
const DEFAULT_OUT = path.join(
|
|
677
|
+
repoRoot,
|
|
678
|
+
'examples/local-progressive',
|
|
679
|
+
inputBase === 'model' ? 'output' : `output_${inputBase}`,
|
|
680
|
+
);
|
|
681
|
+
const OUT_DIR = process.argv[3] || DEFAULT_OUT;
|
|
682
|
+
bakeProgressive(INPUT, OUT_DIR).catch((e) => { console.error(e); process.exit(1); });
|
|
683
|
+
}
|