@needle-tools/gltf-build-pipeline 1.4.4 → 1.4.6

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 CHANGED
@@ -4,6 +4,13 @@ All notable changes to this package will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [1.4.6] - 2023-04-10
8
+ - fix: NEEDLE_progressive meshes do not revert primitive data for skinned meshes anymore. See NE-4596
9
+
10
+ ## [1.4.5] - 2023-04-05
11
+ - fix: generating mesh and texture LOD for glbs without `NEEDLE_` extension
12
+ - fix: guid generation for progressive meshes when no `NEEDLE_` extension is present
13
+
7
14
  ## [1.4.4] - 2023-04-03
8
15
  - change: clamp simplification error for LOD meshes to 5%
9
16
 
@@ -2,7 +2,7 @@ import { BufferUtils, Document, NodeIO, PropertyType } from '@gltf-transform/cor
2
2
  import { SIMPLIFY_DEFAULTS, WELD_DEFAULTS, listTextureSlots, sparse } from '@gltf-transform/functions';
3
3
  import { NEEDLE_PROGRESSIVE_EXTENSION_NAME, NEEDLE_progressive } from "../extensions/NEEDLE_progressive/index.js";
4
4
  import { createOpaqueExtension, currentGenerator, NEEDLE_compression_texture, NEEDLE_mesh_compression, NEEDLE_progressive_mesh_settings, NEEDLE_progressive_texture_settings, registerExtensions as registerDefaultExtensions } from '../extensions/index.js';
5
- import path from 'path';
5
+ import path, { basename } from 'path';
6
6
  import { existsSync, readFileSync, rmSync, statSync, writeFileSync } from 'fs';
7
7
  import { addMetaToCache, addToCache, getHash, getKey, tryGetFromCache, tryGetMetaFromCache } from '../cache/index.js';
8
8
  import sharp from "sharp";
@@ -97,6 +97,7 @@ const NAME = 'NEEDLE_progressive';
97
97
  export function make_progressive_textures(filePath, _options = TEXTURE_RESIZE_DEFAULTS, opts) {
98
98
  console.log("Make progressive: " + filePath);
99
99
  const startTime = Date.now();
100
+ const filename = basename(filePath);
100
101
  const options = { ...TEXTURE_RESIZE_DEFAULTS, ..._options };
101
102
  const directory = path.dirname(filePath);
102
103
  // const fileNameWithoutExtension = path.basename(filePath, path.extname(filePath));
@@ -122,13 +123,23 @@ export function make_progressive_textures(filePath, _options = TEXTURE_RESIZE_DE
122
123
  logger.debug(`[${NAME}] Skipping, [${slots.join(', ')}] excluded by "slots" parameter. ${textureIndex}`);
123
124
  continue;
124
125
  }
125
- const settings = texture.getExtension(NEEDLE_progressive_texture_settings.EXTENSION_NAME);
126
+ let settings = texture.getExtension(NEEDLE_progressive_texture_settings.EXTENSION_NAME);
126
127
  if (!settings) {
127
- logger.warn(`[${NAME}] Skipping, no settings found ${textureIndex}`);
128
- continue;
128
+ const size = texture.getSize();
129
+ if (size?.length >= 2 && size[0] <= 128 && size[1] <= 128) {
130
+ logger.warn(`[${NAME}] Skipping texture[${textureIndex}], no settings found`);
131
+ continue;
132
+ }
133
+ else {
134
+ settings = {
135
+ guid: generateGuid(filename + "_texture_" + index.toString()),
136
+ maxSize: 128,
137
+ };
138
+ logger.debug(`[${NAME}] No settings found for texture[${index}] - will use default settings (maxSize: ${settings.maxSize}, guid: ${settings.guid})`);
139
+ }
129
140
  }
130
- if (!settings.isValid) {
131
- logger.warn(`[${NAME}] Skipping, settings are invalid ${textureIndex}`);
141
+ if (settings.maxSize == undefined || settings.maxSize <= 0) {
142
+ logger.warn(`[${NAME}] Skipping texture[${textureIndex}], settings are invalid (maxSize: ${settings.maxSize})`);
132
143
  continue;
133
144
  }
134
145
  options.size[0] = settings.maxSize;
@@ -343,10 +354,10 @@ export function make_progressive_meshes(filePath, _options, opts) {
343
354
  const root = doc.getRoot();
344
355
  const meshes = root.listMeshes();
345
356
  for (const mesh of meshes) {
346
- await processMesh(mesh);
357
+ await processMesh(mesh, { filename });
347
358
  }
348
359
  console.log(`[${NAME}]: Finished generating progressive meshes for \"${filename}\"`);
349
- async function processMesh(mesh) {
360
+ async function processMesh(mesh, args) {
350
361
  /** The size and vertex count of the original mesh */
351
362
  const originalMeshInformation = getMeshInformation(mesh);
352
363
  const { totalVertexCount: originalTotalVertexCount, maxVertexCount: originalMaxVertexCount } = originalMeshInformation;
@@ -358,7 +369,7 @@ export function make_progressive_meshes(filePath, _options, opts) {
358
369
  }
359
370
  else {
360
371
  settings = {
361
- guid: generateGuid(path + "_mesh_" + index.toString()),
372
+ guid: generateGuid(args.filename + "_mesh_" + index.toString()),
362
373
  generateLods: true,
363
374
  };
364
375
  logger.debug(`[${NAME}] No settings found for mesh[${index}] with ${originalTotalVertexCount} vertices (max: ${originalMaxVertexCount}) - will use default settings (guid: ${settings.guid})`);
@@ -463,11 +474,13 @@ export function make_progressive_meshes(filePath, _options, opts) {
463
474
  let maxDensity = 0;
464
475
  let primitiveIndex = 0;
465
476
  const lodLevelInFile = generatedLODInfos.length;
466
- const clonedData = new Array();
477
+ const clonedData = { primitives: [], weights: [...mesh.getWeights()] };
467
478
  for (const prim of mesh.listPrimitives()) {
468
479
  const data = clonePrimitiveData(prim);
469
- clonedData.push(data);
470
- console.log(`[${NAME}] Simplify mesh[${index}] primitive[${primitiveIndex}] with ${data.indices.length / 3} triangles`);
480
+ if (data != null) {
481
+ clonedData.primitives.push(data);
482
+ }
483
+ console.log(`[${NAME}] Simplify mesh[${index}] primitive[${primitiveIndex}] (embedded)`);
471
484
  const lastLod = LODS[lodLevelInFile];
472
485
  // TODO: this should be run after simplification but then we need to change the runtime to use the LOD 0 density
473
486
  const density = calculateMeshDensity(prim);
@@ -485,7 +498,7 @@ export function make_progressive_meshes(filePath, _options, opts) {
485
498
  }
486
499
  else if (difference < 32 || diff01 <= 0.05) {
487
500
  // the lowest LOD has the same vertex count as the original mesh → we don't need to write the extension and can also delete previously generated LODs
488
- console.log(`[${NAME}]: Flag mesh LOD ${generatedLODInfos.length}: vertex count difference below threshold (removed ${difference} vertices, ${(-diff01 * 100).toFixed(2)} %) → will remove LODs. \"${mesh.getName()}\"`);
501
+ console.log(`[${NAME}]: Flag mesh LOD ${generatedLODInfos.length} (embedded): vertex count difference below threshold (removed ${difference} vertices, ${(-diff01 * 100).toFixed(2)} %) → will remove LOD. \"${mesh.getName()}\"`);
489
502
  try {
490
503
  for (const lodInfo of generatedLODInfos) {
491
504
  rmSync(outputDirectory + "/" + lodInfo.path);
@@ -496,9 +509,12 @@ export function make_progressive_meshes(filePath, _options, opts) {
496
509
  }
497
510
  // reset data (simplify might have changed the mesh data that we cloned before)
498
511
  const primitives = mesh.listPrimitives();
499
- if (clonedData.length == primitives.length) {
512
+ if (clonedData.primitives.length == primitives.length) {
513
+ if (clonedData.weights?.length > 0) {
514
+ mesh.setWeights(clonedData.weights);
515
+ }
500
516
  for (let i = 0; i < primitives.length; i++) {
501
- setPrimitiveData(primitives[i], clonedData[i]);
517
+ setPrimitiveData(primitives[i], clonedData.primitives[i]);
502
518
  }
503
519
  }
504
520
  return;
@@ -529,9 +545,14 @@ export function make_progressive_meshes(filePath, _options, opts) {
529
545
  });
530
546
  }
531
547
  function clonePrimitiveData(prim) {
548
+ const semantics = prim.listSemantics();
549
+ if (semantics.some(s => s.includes("JOINTS"))) {
550
+ return null;
551
+ }
532
552
  const indices = new Uint32Array(prim.getIndices().getArray());
533
553
  const attributes = {};
534
- for (const attr of prim.listSemantics()) {
554
+ for (const attr of semantics) {
555
+ console.log(`[${NAME}] Clone attribute ${attr}`);
535
556
  const accessor = prim.getAttribute(attr);
536
557
  if (accessor) {
537
558
  attributes[attr] = new Float32Array(accessor.getArray());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/gltf-build-pipeline",
3
- "version": "1.4.4",
3
+ "version": "1.4.6",
4
4
  "description": "Pipeline and tools for optimizing gltf files using gltf-transform and compression settings within glTF extensions",
5
5
  "main": "index.mjs",
6
6
  "type": "module",