@needle-tools/gltf-build-pipeline 1.5.0-alpha.3 → 1.5.0-alpha.4

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,11 @@ 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.5.0-alpha.4] - 2023-05-03
8
+ - fix: issue in NEEDLE_opaque resolving of VRM textures, also resolve `meta.texture`
9
+ - fix: VRMs now compress meshes with mesh-opt if nothing is specified
10
+ - change: include version in cache directory
11
+
7
12
  ## [1.5.0-alpha.3] - 2023-05-03
8
13
  - add: VRM progressive textures support
9
14
  - fix: VRM format should be saved as GLB. See https://github.com/donmccurdy/glTF-Transform/issues/1390
@@ -8,7 +8,7 @@ export declare function clearCache(): void;
8
8
  * Ensure that the cache size does not exceed the given maximum size in MB.
9
9
  * @param maxSizeMB The maximum size in MB.
10
10
  */
11
- export declare function ensureCacheSize(maxSizeMB: number): void;
11
+ export declare function limitCacheSize(maxSizeMB?: number): void;
12
12
  /**
13
13
  * Add data to the cache.
14
14
  * @param key The key to store the data under.
@@ -48,4 +48,4 @@ export declare function getKeyWithHash(property: ExtensibleProperty): {
48
48
  * @param property The property to get the hash for.
49
49
  * @returns The hash as a number.
50
50
  */
51
- export declare function getHash(property: ExtensibleProperty | object): number;
51
+ export declare function getHash(property: ExtensibleProperty | object, level?: number): number;
@@ -1,6 +1,6 @@
1
1
  import { ExtensibleProperty, Texture, Primitive, Accessor, Mesh } from "@gltf-transform/core";
2
2
  import tmp from 'tmp';
3
- import fs from 'fs';
3
+ import fs, { statSync } from 'fs';
4
4
  import path from 'path';
5
5
  import { getVersion } from "../utils/version.js";
6
6
  // import * as CHECKDISCSPACE from 'check-disk-space'
@@ -24,7 +24,7 @@ const buildPipelineVersion = getVersion(false);
24
24
  * This will remove all files in the cache directory.
25
25
  */
26
26
  export function clearCache() {
27
- const dir = getCacheDirectory();
27
+ const dir = getCacheDirectory(true);
28
28
  fs.rmSync(dir, { recursive: true });
29
29
  console.log(`Cleared cache at ${dir}`);
30
30
  }
@@ -32,16 +32,27 @@ export function clearCache() {
32
32
  * Ensure that the cache size does not exceed the given maximum size in MB.
33
33
  * @param maxSizeMB The maximum size in MB.
34
34
  */
35
- export function ensureCacheSize(maxSizeMB) {
36
- const dir = getCacheDirectory();
35
+ export function limitCacheSize(maxSizeMB = 1024) {
36
+ const dir = getCacheDirectory(true);
37
+ console.log(`Limit cache size to ${maxSizeMB.toFixed(2)} MB at ${dir}...`);
37
38
  let totalSize = 0;
38
- const files = fs.readdirSync(dir).map(file => {
39
- const path = `${dir}/${file}`;
40
- const stats = fs.statSync(path);
41
- totalSize += stats.size;
42
- return { path, size: stats.size };
43
- });
39
+ function recurseDirectories(dir) {
40
+ const files = fs.readdirSync(dir).map(file => {
41
+ const path = `${dir}/${file}`;
42
+ const stats = statSync(path);
43
+ if (stats.isDirectory()) {
44
+ recurseDirectories(path);
45
+ }
46
+ else {
47
+ totalSize += stats.size;
48
+ }
49
+ return { path, size: stats.size };
50
+ });
51
+ return files;
52
+ }
53
+ const files = recurseDirectories(dir);
44
54
  const maxSizeInBytes = maxSizeMB * 1024 * 1024;
55
+ console.log(`Current cache size is ${(totalSize / (1024 * 1024)).toFixed(1)} MB`);
45
56
  if (totalSize < maxSizeInBytes)
46
57
  return;
47
58
  files.sort((a, b) => {
@@ -55,6 +66,7 @@ export function ensureCacheSize(maxSizeMB) {
55
66
  const file = files.shift();
56
67
  if (!file)
57
68
  break;
69
+ console.log(`Removing cache file ${file.path}...`);
58
70
  fs.rmSync(file.path);
59
71
  totalSize -= file.size;
60
72
  }
@@ -153,7 +165,7 @@ export function getKeyWithHash(property) {
153
165
  * @param property The property to get the hash for.
154
166
  * @returns The hash as a number.
155
167
  */
156
- export function getHash(property) {
168
+ export function getHash(property, level = 0) {
157
169
  let hash = 0;
158
170
  if (property instanceof ExtensibleProperty) {
159
171
  const extensions = property.listExtensions();
@@ -175,7 +187,7 @@ export function getHash(property) {
175
187
  hash += hashObject(weights);
176
188
  const primitives = property.listPrimitives();
177
189
  for (const prim of primitives)
178
- hash += getHash(prim);
190
+ hash += getHash(prim, level + 1);
179
191
  }
180
192
  else if (property instanceof Primitive) {
181
193
  const indices = property.getIndices();
@@ -198,8 +210,9 @@ export function getHash(property) {
198
210
  }
199
211
  return hash;
200
212
  }
201
- function getCacheDirectory() {
202
- const tmpDir = path.join(tmp.tmpdir, "Needle", "build-pipeline-cache");
213
+ const cleanBuildPipelineVersion = buildPipelineVersion.replace(/[^a-zA-Z0-9]/g, "_");
214
+ function getCacheDirectory(root) {
215
+ const tmpDir = path.join(tmp.tmpdir, "Needle", "build-pipeline-cache", root ? "" : cleanBuildPipelineVersion);
203
216
  if (!fs.existsSync(tmpDir)) {
204
217
  fs.mkdirSync(tmpDir, { recursive: true });
205
218
  }
@@ -211,12 +224,7 @@ function hashObject(obj) {
211
224
  return hashBuffer(buffer);
212
225
  }
213
226
  const str = JSON.stringify(obj);
214
- let hash = 0;
215
- for (let i = 0; i < str.length; i++) {
216
- hash = ((hash << 5) - hash) + str.charCodeAt(i);
217
- hash |= 0;
218
- }
219
- return hash;
227
+ return hashString(str);
220
228
  }
221
229
  function hashBuffer(buffer, offset, length) {
222
230
  let hash = 0;
@@ -227,3 +235,11 @@ function hashBuffer(buffer, offset, length) {
227
235
  }
228
236
  return hash;
229
237
  }
238
+ function hashString(str) {
239
+ let hash = 0;
240
+ for (let i = 0; i < str.length; i++) {
241
+ hash = ((hash << 5) - hash) + str.charCodeAt(i);
242
+ hash |= 0;
243
+ }
244
+ return hash;
245
+ }
@@ -557,6 +557,7 @@ class JsonPointerHandler {
557
557
  const object = tryGetInArray(context.textures, imageIndex);
558
558
  if (object) {
559
559
  const res = new TextureIndexResolver(this.document, object, definition);
560
+ res.debug = this.debug;
560
561
  res.init(context); // < init here otherwise the fields defined in the TexturePointer will be undefined (this caused e.g. finding the previous texture filter to fail)
561
562
  pointer = new JsonPointer(path, res, value);
562
563
  pointer.debug = this.debug;
@@ -590,6 +591,7 @@ class JsonPointerHandler {
590
591
  if (!pointer) {
591
592
  const definition = context.jsonDoc.json.materials[index];
592
593
  const res = new MaterialIndexResolver(this.document, mat, definition);
594
+ res.debug = this.debug;
593
595
  res.init(context); // < init here otherwise the fields defined in the TexturePointer will be undefined (this caused e.g. finding the previous texture filter to fail)
594
596
  pointer = new JsonPointer("/materials/", res, value);
595
597
  pointer.debug = this.debug;
@@ -605,6 +607,7 @@ class JsonPointerHandler {
605
607
  const object = context.nodes[value];
606
608
  if (object) {
607
609
  const res = new NodeIndexResolver(this.document, object, context.jsonDoc.json.nodes[value]);
610
+ res.debug = this.debug;
608
611
  res.init(context);
609
612
  const dictKey = `/${key}/${value}`;
610
613
  let pointer = this.map.get(dictKey);
@@ -616,10 +619,19 @@ class JsonPointerHandler {
616
619
  this.map.set(dictKey, pointer);
617
620
  }
618
621
  }
619
- else if (fullPath.match(/materialProperties\/\d+?\/textureProperties/g)) {
620
- const object = context.textures[value];
622
+ // key texture is matching for example for VRM meta/texture (AvatarSample_A) and the regex is also for handling VRM material properties
623
+ else if (key === "texture" || fullPath.match(/materialProperties\/\d+?\/textureProperties/g)) {
624
+ const index = value;
625
+ const definition = context.jsonDoc.json.textures[index];
626
+ const imageIndex = findSource(definition);
627
+ if (this.debug)
628
+ console.log("Texture index", index, imageIndex, context.jsonDoc.json.textures.length, "Textures:" + context.textures.length);
629
+ const object = tryGetInArray(context.textures, imageIndex);
621
630
  if (object) {
622
- const res = new TextureIndexResolver(this.document, object, context.jsonDoc.json.textures[value]);
631
+ if (this.debug)
632
+ console.log("Found texture index at " + fullPath + ": " + value);
633
+ const res = new TextureIndexResolver(this.document, object, definition);
634
+ res.debug = this.debug;
623
635
  res.init(context);
624
636
  const dictKey = `/textures/${value}`;
625
637
  let pointer = this.map.get(dictKey);
@@ -629,6 +641,9 @@ class JsonPointerHandler {
629
641
  pointer.debug = this.debug;
630
642
  pointer.register(obj, key);
631
643
  this.map.set(dictKey, pointer);
644
+ if (ext) {
645
+ ext.setReference(dictKey, object);
646
+ }
632
647
  }
633
648
  }
634
649
  break;
@@ -734,7 +749,7 @@ class TextureIndexResolver extends PointerResolver {
734
749
  // the texture was not found - add it
735
750
  // create a new texture def entry
736
751
  if (this.debug)
737
- console.log("Creating new texture", this._debugName);
752
+ console.log("Could not find texture, creating a new one: " + this._debugName);
738
753
  const hasExtensionWithSource = this.inputDefinition.extensions && Object.keys(this.inputDefinition.extensions).some(key => this.inputDefinition.extensions[key]["source"] !== undefined);
739
754
  const textureDef = {
740
755
  source: hasExtensionWithSource ? undefined : imgIndex,
@@ -1,4 +1,8 @@
1
1
  import { Transform, Document, Primitive, Mesh } from "@gltf-transform/core";
2
2
  import { SimplifyOptions, WeldOptions } from "@gltf-transform/functions";
3
- export declare const needle_mesh_transform: (_options: SimplifyOptions) => Transform;
3
+ declare type MeshTransformContext = {
4
+ file: string;
5
+ };
6
+ export declare const needle_mesh_transform: (context: MeshTransformContext, simplify: SimplifyOptions) => Transform;
4
7
  export declare function compressPrimitive(document: Document, mesh: Mesh, prim: Primitive, index: number, weldOptions: Required<WeldOptions>, meshOptions: Required<SimplifyOptions>): Promise<Primitive>;
8
+ export {};
@@ -3,14 +3,14 @@ import { meshopt, simplifyPrimitive, SIMPLIFY_DEFAULTS, weldPrimitive, WELD_DEFA
3
3
  import { MeshoptEncoder, MeshoptSimplifier } from "meshoptimizer";
4
4
  import { NEEDLE_mesh_compression } from "../extensions/index.js";
5
5
  const NAME = 'needle_mesh_transform';
6
- export const needle_mesh_transform = function (_options) {
6
+ export const needle_mesh_transform = function (context, simplify) {
7
7
  return async (document, _context) => {
8
8
  // TODO: needs to be moved into NEEDLE_progressive
9
- await simplifierTransform(document, _context, _options);
10
- await applyMeshCompression(document, _context);
9
+ await simplifierTransform(document, _context, simplify);
10
+ await applyMeshCompression(document, _context, context);
11
11
  };
12
12
  };
13
- async function applyMeshCompression(document, _context) {
13
+ async function applyMeshCompression(document, transform_context, context) {
14
14
  const rootExtension = document.getRoot().getExtension(NEEDLE_mesh_compression.EXTENSION_NAME);
15
15
  if (rootExtension) {
16
16
  const rootModel = rootExtension.model;
@@ -22,17 +22,23 @@ async function applyMeshCompression(document, _context) {
22
22
  console.log(`[${NAME}]: ${rootModel.compression.toUpperCase()} → will apply ${rootModel.compression} mesh compression`);
23
23
  if (rootModel.compression === "draco") {
24
24
  const transform = draco();
25
- return transform(document, _context);
25
+ return transform(document, transform_context);
26
26
  }
27
27
  else if (rootModel.compression === "meshopt") {
28
28
  const transform = meshopt({ encoder: MeshoptEncoder });
29
- return transform(document, _context);
29
+ return transform(document, transform_context);
30
30
  }
31
31
  }
32
32
  }
33
+ // If nothing is configured apply meshopt compression as long as we're running gltf-transform 3.x
34
+ if (context.file.endsWith(".vrm")) {
35
+ console.log(`[${NAME}]: VRM → will apply meshopt mesh compression`);
36
+ const transform = meshopt({ encoder: MeshoptEncoder });
37
+ return transform(document, transform_context);
38
+ }
33
39
  // by default we still want to run draco if the root doesnt have a compression model configured
34
40
  console.log(`[${NAME}]: No compression model configured → will apply draco mesh compression`);
35
- return draco()(document, _context);
41
+ return draco()(document, transform_context);
36
42
  }
37
43
  async function simplifierTransform(document, _context, _options) {
38
44
  const simplifier = MeshoptSimplifier;
@@ -1,17 +1,14 @@
1
- import { renameSync } from "fs";
1
+ import { writeFile } from "fs/promises";
2
2
  /**
3
3
  * Handle writing glTf, GLB and VRM files
4
4
  */
5
5
  export async function writeNodeIO(nodeio, filename, document) {
6
- let filename_write = filename;
7
6
  // see https://github.com/donmccurdy/glTF-Transform/issues/1390
8
7
  if (filename.endsWith(".vrm")) {
9
- filename_write = filename_write.replace(".vrm", ".glb");
10
- }
11
- await nodeio.write(filename_write, document);
12
- if (filename.endsWith(".vrm")) {
13
- // rename the file to .vrm
14
- renameSync(filename_write, filename);
8
+ const bin = await nodeio.writeBinary(document);
9
+ await writeFile(filename, bin);
15
10
  }
11
+ else
12
+ await nodeio.write(filename, document);
16
13
  return filename;
17
14
  }
@@ -0,0 +1,4 @@
1
+
2
+ import { limitCacheSize } from './dist/cache/index.js';
3
+
4
+ limitCacheSize(512);
package/pack-gltf.mjs CHANGED
@@ -12,7 +12,7 @@ import { needle_animation_transform } from "./dist/transforms/needle_animation_t
12
12
  import { foreachGLTF } from './fileutils.mjs';
13
13
  import { needle_asset } from './dist/transforms/needle_asset.js';
14
14
  import { MeshoptDecoder, MeshoptEncoder } from 'meshoptimizer';
15
- import { getVersion, getHash, addToCache, tryGetFromCache, isLOD, ensureCacheSize as ensureMaxCacheSize, isMeshLOD } from './dist/index.js';
15
+ import { getVersion, getHash, addToCache, tryGetFromCache, isLOD, limitCacheSize, isMeshLOD } from './dist/index.js';
16
16
  import { writeNodeIO } from './dist/utils/nodeio.js';
17
17
 
18
18
  console.log(`[Needle Build Pipeline] pack glTF — version ${getVersion()}`)
@@ -135,7 +135,7 @@ async function packFile(file) {
135
135
  debug: debug,
136
136
  reportGPUMemory: val => totalGPUTextureMemmory += val
137
137
  }),
138
- needle_mesh_transform({ ratio: 0.75, error: 0.0005 }),
138
+ needle_mesh_transform({ file }, { ratio: 0.75, error: 0.0005 }),
139
139
  needle_animation_transform(),
140
140
  // draco(),
141
141
  );
@@ -178,7 +178,7 @@ foreachGLTF(inputArgs, async (file) => {
178
178
  // if the user's cache directory has more than 25GB free space, we allow a cache of 2 GB - otherwise 1 GB
179
179
  // const freeSpaceInMB = (await getCacheAvailableSpaceOnDisc().catch(() => 0)) / 1024 / 1024;
180
180
  // const maxCacheSize = freeSpaceInMB > 25000 ? 2000 : 1000;
181
- ensureMaxCacheSize(1000);
181
+ limitCacheSize();
182
182
  }
183
183
  console.log(`[Needle Build Pipeline] v${getVersion()} — Finished packing ${totalFilesProcessed} files in ${durationInMinutes.toFixed(1)} minutes; total size ${totalFileSizeInMBBefore.toFixed(1)} MB → ${totalFileSizeInMB.toFixed(1)} MB, total GPU memory: ${totalGPUMemoryInMB.toFixed(1)} MB`);
184
184
  }).catch(err => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@needle-tools/gltf-build-pipeline",
3
- "version": "1.5.0-alpha.3",
3
+ "version": "1.5.0-alpha.4",
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",
@@ -13,6 +13,7 @@
13
13
  "pack-gltf": "node --no-experimental-fetch pack-gltf.mjs",
14
14
  "dev:pack-gltf": "npm run compile && node pack-gltf.mjs",
15
15
  "clear-caches": "node clear-caches.mjs",
16
+ "limit-caches": "node limit-caches.mjs",
16
17
  "compile": "tsc || exit 1"
17
18
  },
18
19
  "dependencies": {
@@ -1 +0,0 @@
1
- export declare function gzipFile(filepath: string): Promise<string>;
@@ -1,16 +0,0 @@
1
- import { promises as fs, existsSync } from 'fs';
2
- import { gzip } from 'node-gzip';
3
- export async function gzipFile(filepath) {
4
- if (filepath.endsWith('.gz')) {
5
- return filepath;
6
- }
7
- if (!existsSync(filepath)) {
8
- console.log("File not found: " + filepath);
9
- return filepath;
10
- }
11
- const inBuffer = await fs.readFile(filepath);
12
- const outBuffer = await gzip(inBuffer);
13
- const outPath = filepath;
14
- await fs.writeFile(outPath, outBuffer);
15
- return outPath;
16
- }
@@ -1 +0,0 @@
1
- export * from "./gzip.js";
@@ -1 +0,0 @@
1
- export * from "./gzip.js";
@@ -1 +0,0 @@
1
- export {};
@@ -1,35 +0,0 @@
1
- export {};
2
- // TODO: remove once this is resolved: https://github.com/donmccurdy/glTF-Transform/issues/855
3
- // modified to take a document as a parameter
4
- // export function listTextureSlots(texture: Texture, document: Document): string[] {
5
- // const root = document.getRoot();
6
- // const slots = texture
7
- // .getGraph()
8
- // .listParentEdges(texture)
9
- // .filter((edge) => edge.getParent() !== root)
10
- // .map((edge) => edge.getName());
11
- // return Array.from(new Set(slots));
12
- // }
13
- // export function getTextureChannelMask(texture: Texture, document: Document): number {
14
- // let mask = 0x0000;
15
- // for (const edge of document.getGraph().listParentEdges(texture)) {
16
- // const parent = edge.getParent();
17
- // let { channels } = edge.getAttributes() as { channels: number | undefined };
18
- // if (
19
- // channels &&
20
- // edge.getName() === 'baseColorTexture' &&
21
- // parent instanceof Material &&
22
- // parent.getAlphaMode() === Material.AlphaMode.OPAQUE
23
- // ) {
24
- // channels &= ~TextureChannel.A;
25
- // }
26
- // if (channels) {
27
- // mask |= channels;
28
- // continue;
29
- // }
30
- // if (parent.propertyType !== PropertyType.ROOT) {
31
- // document.getLogger().warn(`Missing attribute ".channels" on edge, "${edge.getName()}".`);
32
- // }
33
- // }
34
- // return mask;
35
- // }
@@ -1,3 +0,0 @@
1
- import { Transform } from "@gltf-transform/core";
2
- import { SimplifyOptions } from "@gltf-transform/functions";
3
- export declare const needle_mesh_transform: (options: SimplifyOptions) => Transform;
@@ -1,76 +0,0 @@
1
- import { Primitive } from "@gltf-transform/core";
2
- import { simplifyPrimitive, weldPrimitive } from "@gltf-transform/functions";
3
- import { MeshoptSimplifier } from "meshoptimizer";
4
- import { NEEDLE_mesh_compression } from "../extensions/index.js";
5
- const NAME = 'needle_simplify';
6
- export const needle_mesh_transform = function (options) {
7
- const simplifier = MeshoptSimplifier;
8
- if (!simplifier) {
9
- throw new Error(`${NAME}: simplifier dependency required — install "meshoptimizer".`);
10
- }
11
- return (document, _context) => {
12
- const logger = document.getLogger();
13
- options = { ...options, simplifier: simplifier };
14
- const weldOptions = {
15
- tolerance: 0.00000000001,
16
- overwrite: true
17
- };
18
- for (const mesh of document.getRoot().listMeshes()) {
19
- for (const prim of mesh.listPrimitives()) {
20
- // const key = getKey(prim);
21
- // const cached = tryGetFromCache(key);
22
- // if (cached) {
23
- // logger.debug(`${NAME}: Skipping primitive of mesh "${mesh.getName()}": Already cached.`);
24
- // continue;
25
- // }
26
- // updatePrimitive(prim, simplifier, null, prim.getIndices());
27
- // continue;
28
- const ext = prim.getExtension(NEEDLE_mesh_compression.EXTENSION_NAME);
29
- if (!ext) {
30
- // logger.warn("Skipping primitive of mesh " + mesh.getName() + ": No NEEDLE_compression_mesh extension.");
31
- continue;
32
- }
33
- let meshOptions = { ...options };
34
- if (ext.model) {
35
- const model = ext.model;
36
- if (!model.useSimplifier) {
37
- logger.debug(`${NAME}: Skipping primitive of mesh "${mesh.getName()}": useSimplifier is false.`);
38
- continue;
39
- }
40
- if (model.error >= 0)
41
- meshOptions.error = model.error;
42
- if (model.ratio >= 0)
43
- meshOptions.ratio = model.ratio;
44
- meshOptions.lockBorder = model.lockBorder;
45
- }
46
- if (prim.getMode() !== Primitive.Mode.TRIANGLES) {
47
- logger.warn(`${NAME}: Skipping primitive of mesh "${mesh.getName()}": Requires TRIANGLES draw mode.`);
48
- continue;
49
- }
50
- logger.debug(`${NAME}: Welding primitive of mesh "${mesh.getName()}" → tolerance: ${weldOptions.tolerance}`);
51
- weldPrimitive(document, prim, weldOptions);
52
- logger.debug(`${NAME}: Simplifying primitive of mesh "${mesh.getName()}" → ratio: ${meshOptions.ratio}, error: ${meshOptions.error}, lockBorder: ${meshOptions.lockBorder}`);
53
- simplifyPrimitive(document, prim, meshOptions);
54
- }
55
- }
56
- };
57
- };
58
- // function updatePrimitive(prim: Primitive, simplifier: any, positionArray, dstIndicesArray) {
59
- // const position = prim.getAttribute('POSITION')!;
60
- // const srcIndices = prim.getIndices()!;
61
- // const srcVertexCount = position.getCount();
62
- // const [remap, unique] = simplifier.compactMesh(dstIndicesArray);
63
- // // logger.debug(`${NAME}: ${formatDeltaOp(position.getCount(), unique)} vertices, error: ${error.toFixed(4)}.`);
64
- // // (3) Write vertex attributes.
65
- // for (const srcAttribute of deepListAttributes(prim)) {
66
- // const dstAttribute = srcAttribute.clone();
67
- // remapAttribute(dstAttribute, remap, unique);
68
- // deepSwapAttribute(prim, srcAttribute, dstAttribute);
69
- // if (srcAttribute.listParents().length === 1) srcAttribute.dispose();
70
- // }
71
- // // (4) Write indices.
72
- // const dstIndices = srcIndices.clone();
73
- // dstIndices.setArray(srcVertexCount <= 65534 ? new Uint16Array(dstIndicesArray) : dstIndicesArray);
74
- // prim.setIndices(dstIndices);
75
- // if (srcIndices.listParents().length === 1) srcIndices.dispose();
76
- // }
@@ -1,31 +0,0 @@
1
- export declare class WebPEncoderOptions {
2
- quality: number;
3
- target_size: number;
4
- target_PSNR: number;
5
- method: number;
6
- sns_strength: number;
7
- filter_strength: number;
8
- filter_sharpness: number;
9
- /** 1 = strong filter */
10
- filter_type: number;
11
- partitions: number;
12
- segments: number;
13
- pass: number;
14
- show_compressed: number;
15
- preprocessing: number;
16
- autofilter: number;
17
- partition_limit: number;
18
- alpha_compression: number;
19
- alpha_filtering: number;
20
- alpha_quality: number;
21
- lossless: number;
22
- exact: number;
23
- image_hint: number;
24
- emulate_jpeg_size: number;
25
- thread_level: number;
26
- low_memory: number;
27
- near_lossless: number;
28
- use_delta_palette: number;
29
- /** probably sharp rgb -> YUV conversion */
30
- use_sharp_yuv: number;
31
- }
@@ -1,33 +0,0 @@
1
- // client: https://github.com/GoogleChromeLabs/squoosh/blob/97d13de273b67ee01a80cb32161f1bb2103b73cb/src/features/encoders/webP/client/index.tsx#L292
2
- // emscripten bindings:
3
- export class WebPEncoderOptions {
4
- quality = 75;
5
- target_size = 0;
6
- target_PSNR = 0;
7
- method = 4;
8
- sns_strength = 50;
9
- filter_strength = 60;
10
- filter_sharpness = 0;
11
- /** 1 = strong filter */
12
- filter_type = 1;
13
- partitions = 0;
14
- segments = 4;
15
- pass = 1;
16
- show_compressed = 0;
17
- preprocessing = 0;
18
- autofilter = 0;
19
- partition_limit = 0;
20
- alpha_compression = 1;
21
- alpha_filtering = 1;
22
- alpha_quality = 100;
23
- lossless = 0;
24
- exact = 0;
25
- image_hint = 0;
26
- emulate_jpeg_size = 0;
27
- thread_level = 0;
28
- low_memory = 0;
29
- near_lossless = 100;
30
- use_delta_palette = 0;
31
- /** probably sharp rgb -> YUV conversion */
32
- use_sharp_yuv = 0;
33
- }