@loaders.gl/draco
Version:
Framework-independent loader and writer for Draco compressed meshes and point clouds
1,323 lines (1,305 loc) • 489 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if (typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if (typeof define === 'function' && define.amd) define([], factory);
else if (typeof exports === 'object') exports['loaders'] = factory();
else root['loaders'] = factory();})(globalThis, function () {
"use strict";
var __exports__ = (() => {
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// external-global-plugin:@loaders.gl/core
var require_core = __commonJS({
"external-global-plugin:@loaders.gl/core"(exports, module) {
module.exports = globalThis.loaders;
}
});
// bundle.ts
var bundle_exports = {};
__export(bundle_exports, {
DRACO_EXTERNAL_LIBRARIES: () => DRACO_EXTERNAL_LIBRARIES,
DRACO_EXTERNAL_LIBRARY_URLS: () => DRACO_EXTERNAL_LIBRARY_URLS,
DracoArrowLoader: () => DracoArrowLoader,
DracoLoader: () => DracoLoader,
DracoWorkerLoader: () => DracoWorkerLoader,
DracoWriter: () => DracoWriter,
DracoWriterWorker: () => DracoWriterWorker
});
__reExport(bundle_exports, __toESM(require_core(), 1));
// ../worker-utils/src/lib/npm-tag.ts
var NPM_TAG = "latest";
// ../worker-utils/src/lib/env-utils/version.ts
var warningIssued = false;
function getVersion() {
if (!globalThis._loadersgl_?.version) {
globalThis._loadersgl_ = globalThis._loadersgl_ || {};
if (typeof __VERSION__ === "undefined" && !warningIssued) {
console.warn(
"loaders.gl: The __VERSION__ variable is not injected using babel plugin. Latest unstable workers would be fetched from the CDN."
);
globalThis._loadersgl_.version = NPM_TAG;
warningIssued = true;
} else {
globalThis._loadersgl_.version = __VERSION__;
}
}
return globalThis._loadersgl_.version;
}
var VERSION = getVersion();
// ../worker-utils/src/lib/env-utils/assert.ts
function assert(condition, message) {
if (!condition) {
throw new Error(message || "loaders.gl assertion failed.");
}
}
// ../worker-utils/src/lib/env-utils/globals.ts
var globals = {
self: typeof self !== "undefined" && self,
window: typeof window !== "undefined" && window,
global: typeof global !== "undefined" && global,
document: typeof document !== "undefined" && document
};
var self_ = globals.self || globals.window || globals.global || {};
var window_ = globals.window || globals.self || globals.global || {};
var global_ = globals.global || globals.self || globals.window || {};
var document_ = globals.document || {};
var isBrowser = (
// @ts-ignore process.browser
typeof process !== "object" || String(process) !== "[object process]" || process.browser
);
var isWorker = typeof importScripts === "function";
var isMobile = typeof window !== "undefined" && typeof window.orientation !== "undefined";
var matches = typeof process !== "undefined" && process.version && /v([0-9]*)/.exec(process.version);
var nodeVersion = matches && parseFloat(matches[1]) || 0;
// ../worker-utils/src/lib/library-utils/library-utils.ts
var loadLibraryPromises = {};
function extractLoadLibraryOptions(options = {}) {
const useLocalLibraries = options.useLocalLibraries ?? options.core?.useLocalLibraries;
const CDN = options.CDN ?? options.core?.CDN;
const modules = options.modules;
return {
...useLocalLibraries !== void 0 ? { useLocalLibraries } : {},
...CDN !== void 0 ? { CDN } : {},
...modules !== void 0 ? { modules } : {}
};
}
async function loadLibrary(libraryUrl, moduleName = null, options = {}, libraryName = null) {
if (moduleName) {
libraryUrl = getLibraryUrl(libraryUrl, moduleName, options, libraryName);
}
loadLibraryPromises[libraryUrl] = // eslint-disable-next-line @typescript-eslint/no-misused-promises
loadLibraryPromises[libraryUrl] || loadLibraryFromFile(libraryUrl);
return await loadLibraryPromises[libraryUrl];
}
function getLibraryUrl(library, moduleName, options = {}, libraryName = null) {
if (options?.core) {
throw new Error("loadLibrary: options.core must be pre-normalized");
}
if (!options.useLocalLibraries && library.startsWith("http")) {
return library;
}
libraryName = libraryName || library;
const modules = options.modules || {};
if (modules[libraryName]) {
return modules[libraryName];
}
if (!isBrowser) {
return `modules/${moduleName}/dist/libs/${libraryName}`;
}
if (options.CDN) {
assert(options.CDN.startsWith("http"));
return `${options.CDN}/${moduleName}@${VERSION}/dist/libs/${libraryName}`;
}
if (isWorker) {
return `../src/libs/${libraryName}`;
}
return `modules/${moduleName}/src/libs/${libraryName}`;
}
async function loadLibraryFromFile(libraryUrl) {
if (libraryUrl.endsWith("wasm")) {
return await loadAsArrayBuffer(libraryUrl);
}
if (!isBrowser) {
const { requireFromFile } = globalThis.loaders || {};
try {
const result = await requireFromFile?.(libraryUrl);
if (result || !libraryUrl.includes("/dist/libs/")) {
return result;
}
return await requireFromFile?.(libraryUrl.replace("/dist/libs/", "/src/libs/"));
} catch (error) {
if (libraryUrl.includes("/dist/libs/")) {
try {
return await requireFromFile?.(libraryUrl.replace("/dist/libs/", "/src/libs/"));
} catch {
}
}
console.error(error);
return null;
}
}
if (isWorker) {
return importScripts(libraryUrl);
}
const scriptSource = await loadAsText(libraryUrl);
return loadLibraryFromString(scriptSource, libraryUrl);
}
function loadLibraryFromString(scriptSource, id) {
if (!isBrowser) {
const { requireFromString } = globalThis.loaders || {};
return requireFromString?.(scriptSource, id);
}
if (isWorker) {
eval.call(globalThis, scriptSource);
return null;
}
const script = document.createElement("script");
script.id = id;
try {
script.appendChild(document.createTextNode(scriptSource));
} catch (e) {
script.text = scriptSource;
}
document.body.appendChild(script);
return null;
}
async function loadAsArrayBuffer(url) {
const { readFileAsArrayBuffer } = globalThis.loaders || {};
if (isBrowser || !readFileAsArrayBuffer || url.startsWith("http")) {
const response = await fetch(url);
return await response.arrayBuffer();
}
try {
return await readFileAsArrayBuffer(url);
} catch {
if (url.includes("/dist/libs/")) {
return await readFileAsArrayBuffer(url.replace("/dist/libs/", "/src/libs/"));
}
throw new Error(`Failed to load ArrayBuffer from ${url}`);
}
}
async function loadAsText(url) {
const { readFileAsText } = globalThis.loaders || {};
if (isBrowser || !readFileAsText || url.startsWith("http")) {
const response = await fetch(url);
return await response.text();
}
try {
return await readFileAsText(url);
} catch {
if (url.includes("/dist/libs/")) {
return await readFileAsText(url.replace("/dist/libs/", "/src/libs/"));
}
throw new Error(`Failed to load text from ${url}`);
}
}
// src/lib/draco-module-loader.ts
var DRACO_DECODER_VERSION = "1.5.6";
var DRACO_ENCODER_VERSION = "1.4.1";
var STATIC_DECODER_URL = `https://www.gstatic.com/draco/versioned/decoders/${DRACO_DECODER_VERSION}`;
var DRACO_EXTERNAL_LIBRARIES = {
/** The primary Draco3D encoder, javascript wrapper part */
DECODER: "draco_wasm_wrapper.js",
/** The primary draco decoder, compiled web assembly part */
DECODER_WASM: "draco_decoder.wasm",
/** Fallback decoder for non-webassebly environments. Very big bundle, lower performance */
FALLBACK_DECODER: "draco_decoder.js",
/** Draco encoder */
ENCODER: "draco_encoder.js"
};
var DRACO_EXTERNAL_LIBRARY_URLS = {
[DRACO_EXTERNAL_LIBRARIES.DECODER]: `${STATIC_DECODER_URL}/${DRACO_EXTERNAL_LIBRARIES.DECODER}`,
[DRACO_EXTERNAL_LIBRARIES.DECODER_WASM]: `${STATIC_DECODER_URL}/${DRACO_EXTERNAL_LIBRARIES.DECODER_WASM}`,
[DRACO_EXTERNAL_LIBRARIES.FALLBACK_DECODER]: `${STATIC_DECODER_URL}/${DRACO_EXTERNAL_LIBRARIES.FALLBACK_DECODER}`,
[DRACO_EXTERNAL_LIBRARIES.ENCODER]: `https://raw.githubusercontent.com/google/draco/${DRACO_ENCODER_VERSION}/javascript/${DRACO_EXTERNAL_LIBRARIES.ENCODER}`
};
var loadDecoderPromise;
var loadEncoderPromise;
async function loadDracoDecoderModule(options = {}, type) {
const modules = options.modules || {};
if (modules.draco3d) {
loadDecoderPromise ||= modules.draco3d.createDecoderModule({}).then((draco) => {
return { draco };
});
} else {
loadDecoderPromise ||= loadDracoDecoder(options, type);
}
return await loadDecoderPromise;
}
async function loadDracoEncoderModule(options) {
const modules = options.modules || {};
if (modules.draco3d) {
loadEncoderPromise ||= modules.draco3d.createEncoderModule({}).then((draco) => {
return { draco };
});
} else {
loadEncoderPromise ||= loadDracoEncoder(options);
}
return await loadEncoderPromise;
}
function getLibraryExport(library, exportName) {
if (library && typeof library === "object") {
if (library.default) {
return library.default;
}
if (library[exportName]) {
return library[exportName];
}
}
return library;
}
async function loadDracoDecoder(options, type) {
let DracoDecoderModule;
let wasmBinary;
switch (type) {
case "js":
DracoDecoderModule = await loadLibrary(
DRACO_EXTERNAL_LIBRARY_URLS[DRACO_EXTERNAL_LIBRARIES.FALLBACK_DECODER],
"draco",
options,
DRACO_EXTERNAL_LIBRARIES.FALLBACK_DECODER
);
break;
case "wasm":
default:
try {
[DracoDecoderModule, wasmBinary] = await Promise.all([
await loadLibrary(
DRACO_EXTERNAL_LIBRARY_URLS[DRACO_EXTERNAL_LIBRARIES.DECODER],
"draco",
options,
DRACO_EXTERNAL_LIBRARIES.DECODER
),
await loadLibrary(
DRACO_EXTERNAL_LIBRARY_URLS[DRACO_EXTERNAL_LIBRARIES.DECODER_WASM],
"draco",
options,
DRACO_EXTERNAL_LIBRARIES.DECODER_WASM
)
]);
} catch {
DracoDecoderModule = null;
wasmBinary = null;
}
}
DracoDecoderModule = getLibraryExport(DracoDecoderModule, "DracoDecoderModule");
DracoDecoderModule = DracoDecoderModule || globalThis.DracoDecoderModule;
if (!DracoDecoderModule && !isBrowser) {
[DracoDecoderModule, wasmBinary] = await Promise.all([
await loadLibrary(
DRACO_EXTERNAL_LIBRARY_URLS[DRACO_EXTERNAL_LIBRARIES.DECODER],
"draco",
{ ...options, useLocalLibraries: true },
DRACO_EXTERNAL_LIBRARIES.DECODER
),
await loadLibrary(
DRACO_EXTERNAL_LIBRARY_URLS[DRACO_EXTERNAL_LIBRARIES.DECODER_WASM],
"draco",
{ ...options, useLocalLibraries: true },
DRACO_EXTERNAL_LIBRARIES.DECODER_WASM
)
]);
DracoDecoderModule = getLibraryExport(DracoDecoderModule, "DracoDecoderModule");
DracoDecoderModule = DracoDecoderModule || globalThis.DracoDecoderModule;
}
return await initializeDracoDecoder(DracoDecoderModule, wasmBinary);
}
function initializeDracoDecoder(DracoDecoderModule, wasmBinary) {
if (typeof DracoDecoderModule !== "function") {
throw new Error("DracoDecoderModule could not be loaded");
}
const options = {};
if (wasmBinary) {
options.wasmBinary = wasmBinary;
}
return new Promise((resolve) => {
DracoDecoderModule({
...options,
onModuleLoaded: (draco) => resolve({ draco })
// Module is Promise-like. Wrap in object to avoid loop.
});
});
}
async function loadDracoEncoder(options) {
let DracoEncoderModule = await loadLibrary(
DRACO_EXTERNAL_LIBRARY_URLS[DRACO_EXTERNAL_LIBRARIES.ENCODER],
"draco",
options,
DRACO_EXTERNAL_LIBRARIES.ENCODER
);
DracoEncoderModule = getLibraryExport(DracoEncoderModule, "DracoEncoderModule");
DracoEncoderModule = DracoEncoderModule || globalThis.DracoEncoderModule;
if (!DracoEncoderModule && !isBrowser) {
DracoEncoderModule = await loadLibrary(
DRACO_EXTERNAL_LIBRARY_URLS[DRACO_EXTERNAL_LIBRARIES.ENCODER],
"draco",
{ ...options, useLocalLibraries: true },
DRACO_EXTERNAL_LIBRARIES.ENCODER
);
DracoEncoderModule = getLibraryExport(DracoEncoderModule, "DracoEncoderModule");
DracoEncoderModule = DracoEncoderModule || globalThis.DracoEncoderModule;
}
if (typeof DracoEncoderModule !== "function") {
throw new Error("DracoEncoderModule could not be loaded");
}
return new Promise((resolve) => {
DracoEncoderModule({
onModuleLoaded: (draco) => resolve({ draco })
// Module is Promise-like. Wrap in object to avoid loop.
});
});
}
// src/lib/draco-builder.ts
var GLTF_TO_DRACO_ATTRIBUTE_NAME_MAP = {
POSITION: "POSITION",
NORMAL: "NORMAL",
COLOR_0: "COLOR",
TEXCOORD_0: "TEX_COORD"
};
var noop = () => {
};
var DracoBuilder = class {
draco;
dracoEncoder;
dracoMeshBuilder;
dracoMetadataBuilder;
log;
// draco - the draco decoder, either import `draco3d` or load dynamically
constructor(draco) {
this.draco = draco;
this.dracoEncoder = new this.draco.Encoder();
this.dracoMeshBuilder = new this.draco.MeshBuilder();
this.dracoMetadataBuilder = new this.draco.MetadataBuilder();
}
destroy() {
this.destroyEncodedObject(this.dracoMeshBuilder);
this.destroyEncodedObject(this.dracoEncoder);
this.destroyEncodedObject(this.dracoMetadataBuilder);
this.dracoMeshBuilder = null;
this.dracoEncoder = null;
this.draco = null;
}
// TBD - when does this need to be called?
destroyEncodedObject(object) {
if (object) {
this.draco.destroy(object);
}
}
/**
* Encode mesh or point cloud
* @param mesh =({})
* @param options
*/
encodeSync(mesh, options = {}) {
this.log = noop;
this._setOptions(options);
return options.pointcloud ? this._encodePointCloud(mesh, options) : this._encodeMesh(mesh, options);
}
// PRIVATE
_getAttributesFromMesh(mesh) {
const attributes = { ...mesh, ...mesh.attributes };
if (mesh.indices) {
attributes.indices = mesh.indices;
}
return attributes;
}
_encodePointCloud(pointcloud, options) {
const dracoPointCloud = new this.draco.PointCloud();
if (options.metadata) {
this._addGeometryMetadata(dracoPointCloud, options.metadata);
}
const attributes = this._getAttributesFromMesh(pointcloud);
this._createDracoPointCloud(dracoPointCloud, attributes, options);
const dracoData = new this.draco.DracoInt8Array();
try {
const encodedLen = this.dracoEncoder.EncodePointCloudToDracoBuffer(
dracoPointCloud,
false,
dracoData
);
if (!(encodedLen > 0)) {
throw new Error("Draco encoding failed.");
}
this.log(`DRACO encoded ${dracoPointCloud.num_points()} points
with ${dracoPointCloud.num_attributes()} attributes into ${encodedLen} bytes`);
return dracoInt8ArrayToArrayBuffer(dracoData);
} finally {
this.destroyEncodedObject(dracoData);
this.destroyEncodedObject(dracoPointCloud);
}
}
_encodeMesh(mesh, options) {
const dracoMesh = new this.draco.Mesh();
if (options.metadata) {
this._addGeometryMetadata(dracoMesh, options.metadata);
}
const attributes = this._getAttributesFromMesh(mesh);
this._createDracoMesh(dracoMesh, attributes, options);
const dracoData = new this.draco.DracoInt8Array();
try {
const encodedLen = this.dracoEncoder.EncodeMeshToDracoBuffer(dracoMesh, dracoData);
if (encodedLen <= 0) {
throw new Error("Draco encoding failed.");
}
this.log(`DRACO encoded ${dracoMesh.num_points()} points
with ${dracoMesh.num_attributes()} attributes into ${encodedLen} bytes`);
return dracoInt8ArrayToArrayBuffer(dracoData);
} finally {
this.destroyEncodedObject(dracoData);
this.destroyEncodedObject(dracoMesh);
}
}
/**
* Set encoding options.
* @param {{speed?: any; method?: any; quantization?: any;}} options
*/
_setOptions(options) {
if ("speed" in options) {
this.dracoEncoder.SetSpeedOptions(...options.speed);
}
if ("method" in options) {
const dracoMethod = this.draco[options.method || "MESH_SEQUENTIAL_ENCODING"];
this.dracoEncoder.SetEncodingMethod(dracoMethod);
}
if ("quantization" in options) {
for (const attribute in options.quantization) {
const bits = options.quantization[attribute];
const dracoPosition = this.draco[attribute];
this.dracoEncoder.SetAttributeQuantization(dracoPosition, bits);
}
}
}
/**
* @param {Mesh} dracoMesh
* @param {object} attributes
* @returns {Mesh}
*/
_createDracoMesh(dracoMesh, attributes, options) {
const optionalMetadata = options.attributesMetadata || {};
try {
const positions = this._getPositionAttribute(attributes);
if (!positions) {
throw new Error("positions");
}
const vertexCount = positions.length / 3;
for (let attributeName in attributes) {
const attribute = attributes[attributeName];
attributeName = GLTF_TO_DRACO_ATTRIBUTE_NAME_MAP[attributeName] || attributeName;
const uniqueId = this._addAttributeToMesh(dracoMesh, attributeName, attribute, vertexCount);
if (uniqueId !== -1) {
this._addAttributeMetadata(dracoMesh, uniqueId, {
name: attributeName,
...optionalMetadata[attributeName] || {}
});
}
}
} catch (error) {
this.destroyEncodedObject(dracoMesh);
throw error;
}
return dracoMesh;
}
/**
* @param {} dracoPointCloud
* @param {object} attributes
*/
_createDracoPointCloud(dracoPointCloud, attributes, options) {
const optionalMetadata = options.attributesMetadata || {};
try {
const positions = this._getPositionAttribute(attributes);
if (!positions) {
throw new Error("positions");
}
const vertexCount = positions.length / 3;
for (let attributeName in attributes) {
const attribute = attributes[attributeName];
attributeName = GLTF_TO_DRACO_ATTRIBUTE_NAME_MAP[attributeName] || attributeName;
const uniqueId = this._addAttributeToMesh(
dracoPointCloud,
attributeName,
attribute,
vertexCount
);
if (uniqueId !== -1) {
this._addAttributeMetadata(dracoPointCloud, uniqueId, {
name: attributeName,
...optionalMetadata[attributeName] || {}
});
}
}
} catch (error) {
this.destroyEncodedObject(dracoPointCloud);
throw error;
}
return dracoPointCloud;
}
/**
* @param mesh
* @param attributeName
* @param attribute
* @param vertexCount
*/
_addAttributeToMesh(mesh, attributeName, attribute, vertexCount) {
if (!ArrayBuffer.isView(attribute)) {
return -1;
}
const type = this._getDracoAttributeType(attributeName);
const size = attribute.length / vertexCount;
if (type === "indices") {
const numFaces = attribute.length / 3;
this.log(`Adding attribute ${attributeName}, size ${numFaces}`);
this.dracoMeshBuilder.AddFacesToMesh(mesh, numFaces, attribute);
return -1;
}
this.log(`Adding attribute ${attributeName}, size ${size}`);
const builder = this.dracoMeshBuilder;
const { buffer } = attribute;
switch (attribute.constructor) {
case Int8Array:
return builder.AddInt8Attribute(mesh, type, vertexCount, size, new Int8Array(buffer));
case Int16Array:
return builder.AddInt16Attribute(mesh, type, vertexCount, size, new Int16Array(buffer));
case Int32Array:
return builder.AddInt32Attribute(mesh, type, vertexCount, size, new Int32Array(buffer));
case Uint8Array:
case Uint8ClampedArray:
return builder.AddUInt8Attribute(mesh, type, vertexCount, size, new Uint8Array(buffer));
case Uint16Array:
return builder.AddUInt16Attribute(mesh, type, vertexCount, size, new Uint16Array(buffer));
case Uint32Array:
return builder.AddUInt32Attribute(mesh, type, vertexCount, size, new Uint32Array(buffer));
case Float32Array:
return builder.AddFloatAttribute(mesh, type, vertexCount, size, new Float32Array(buffer));
default:
console.warn("Unsupported attribute type", attribute);
return -1;
}
}
/**
* DRACO can compress attributes of know type better
* TODO - expose an attribute type map?
* @param attributeName
*/
_getDracoAttributeType(attributeName) {
switch (attributeName.toLowerCase()) {
case "indices":
return "indices";
case "position":
case "positions":
case "vertices":
return this.draco.POSITION;
case "normal":
case "normals":
return this.draco.NORMAL;
case "color":
case "colors":
return this.draco.COLOR;
case "texcoord":
case "texcoords":
return this.draco.TEX_COORD;
default:
return this.draco.GENERIC;
}
}
_getPositionAttribute(attributes) {
for (const attributeName in attributes) {
const attribute = attributes[attributeName];
const dracoType = this._getDracoAttributeType(attributeName);
if (dracoType === this.draco.POSITION) {
return attribute;
}
}
return null;
}
/**
* Add metadata for the geometry.
* @param dracoGeometry - WASM Draco Object
* @param metadata
*/
_addGeometryMetadata(dracoGeometry, metadata) {
const dracoMetadata = new this.draco.Metadata();
this._populateDracoMetadata(dracoMetadata, metadata);
this.dracoMeshBuilder.AddMetadata(dracoGeometry, dracoMetadata);
}
/**
* Add metadata for an attribute to geometry.
* @param dracoGeometry - WASM Draco Object
* @param uniqueAttributeId
* @param metadata
*/
_addAttributeMetadata(dracoGeometry, uniqueAttributeId, metadata) {
const dracoAttributeMetadata = new this.draco.Metadata();
this._populateDracoMetadata(dracoAttributeMetadata, metadata);
this.dracoMeshBuilder.SetMetadataForAttribute(
dracoGeometry,
uniqueAttributeId,
dracoAttributeMetadata
);
}
/**
* Add contents of object or map to a WASM Draco Metadata Object
* @param dracoMetadata - WASM Draco Object
* @param metadata
*/
_populateDracoMetadata(dracoMetadata, metadata) {
for (const [key, value] of getEntries(metadata)) {
switch (typeof value) {
case "number":
if (Math.trunc(value) === value) {
this.dracoMetadataBuilder.AddIntEntry(dracoMetadata, key, value);
} else {
this.dracoMetadataBuilder.AddDoubleEntry(dracoMetadata, key, value);
}
break;
case "object":
if (value instanceof Int32Array) {
this.dracoMetadataBuilder.AddIntEntryArray(dracoMetadata, key, value, value.length);
}
break;
case "string":
default:
this.dracoMetadataBuilder.AddStringEntry(dracoMetadata, key, value);
}
}
}
};
function dracoInt8ArrayToArrayBuffer(dracoData) {
const byteLength = dracoData.size();
const outputBuffer = new ArrayBuffer(byteLength);
const outputData = new Int8Array(outputBuffer);
for (let i = 0; i < byteLength; ++i) {
outputData[i] = dracoData.GetValue(i);
}
return outputBuffer;
}
function getEntries(container) {
const hasEntriesFunc = container.entries && !container.hasOwnProperty("entries");
return hasEntriesFunc ? container.entries() : Object.entries(container);
}
// src/lib/utils/version.ts
var VERSION2 = typeof __VERSION__ !== "undefined" ? __VERSION__ : "latest";
// src/draco-writer.ts
var DEFAULT_DRACO_WRITER_OPTIONS = {
pointcloud: false,
// Set to true if pointcloud (mode: 0, no indices)
attributeNameEntry: "name"
// Draco Compression Parameters
// method: 'MESH_EDGEBREAKER_ENCODING', // Use draco defaults
// speed: [5, 5], // Use draco defaults
// quantization: { // Use draco defaults
// POSITION: 10
// }
};
var DracoWriterWorker = {
id: "draco-writer",
name: "Draco compressed geometry writer",
module: "draco",
version: VERSION2,
worker: true,
options: {
draco: {},
source: null
}
};
var DracoWriter = {
name: "DRACO",
id: "draco",
module: "draco",
version: VERSION2,
extensions: ["drc"],
mimeTypes: ["application/octet-stream"],
options: {
draco: DEFAULT_DRACO_WRITER_OPTIONS
},
encode
};
async function encode(data, options = {}) {
const { draco } = await loadDracoEncoderModule(extractLoadLibraryOptions(options));
const dracoBuilder = new DracoBuilder(draco);
try {
return dracoBuilder.encodeSync(data, options.draco);
} finally {
dracoBuilder.destroy();
}
}
// ../schema-utils/src/lib/schema/data-type.ts
function getDataTypeFromValue(value, defaultNumberType = "float32") {
if (value instanceof Date) {
return "date-millisecond";
}
if (value instanceof Number) {
return defaultNumberType;
}
if (typeof value === "string") {
return "utf8";
}
if (value === null || value === "undefined") {
return "null";
}
return "null";
}
function getDataTypeFromArray(array) {
let type = getDataTypeFromTypedArray(array);
if (type !== "null") {
return { type, nullable: false };
}
if (array.length > 0) {
type = getDataTypeFromValue(array[0]);
return { type, nullable: true };
}
return { type: "null", nullable: true };
}
function getDataTypeFromTypedArray(array) {
switch (array.constructor) {
case Int8Array:
return "int8";
case Uint8Array:
case Uint8ClampedArray:
return "uint8";
case Int16Array:
return "int16";
case Uint16Array:
return "uint16";
case Int32Array:
return "int32";
case Uint32Array:
return "uint32";
case Float32Array:
return "float32";
case Float64Array:
return "float64";
default:
return "null";
}
}
// ../../node_modules/tslib/tslib.es6.mjs
function __rest(s, e) {
var t = {};
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m)
return m.call(o);
if (o && typeof o.length === "number")
return {
next: function() {
if (o && i >= o.length)
o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __await(v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
}
function __asyncGenerator(thisArg, _arguments, generator) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function() {
return this;
}, i;
function awaitReturn(f) {
return function(v) {
return Promise.resolve(v).then(f, reject);
};
}
function verb(n, f) {
if (g[n]) {
i[n] = function(v) {
return new Promise(function(a, b) {
q.push([n, v, a, b]) > 1 || resume(n, v);
});
};
if (f)
i[n] = f(i[n]);
}
}
function resume(n, v) {
try {
step(g[n](v));
} catch (e) {
settle(q[0][3], e);
}
}
function step(r) {
r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
}
function fulfill(value) {
resume("next", value);
}
function reject(value) {
resume("throw", value);
}
function settle(f, v) {
if (f(v), q.shift(), q.length)
resume(q[0][0], q[0][1]);
}
}
function __asyncDelegator(o) {
var i, p;
return i = {}, verb("next"), verb("throw", function(e) {
throw e;
}), verb("return"), i[Symbol.iterator] = function() {
return this;
}, i;
function verb(n, f) {
i[n] = o[n] ? function(v) {
return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v;
} : f;
}
}
function __asyncValues(o) {
if (!Symbol.asyncIterator)
throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
return this;
}, i);
function verb(n) {
i[n] = o[n] && function(v) {
return new Promise(function(resolve, reject) {
v = o[n](v), settle(resolve, reject, v.done, v.value);
});
};
}
function settle(resolve, reject, d, v) {
Promise.resolve(v).then(function(v2) {
resolve({ value: v2, done: d });
}, reject);
}
}
// ../../node_modules/apache-arrow/util/buffer.mjs
var buffer_exports = {};
__export(buffer_exports, {
compareArrayLike: () => compareArrayLike,
joinUint8Arrays: () => joinUint8Arrays,
memcpy: () => memcpy,
rebaseValueOffsets: () => rebaseValueOffsets,
toArrayBufferView: () => toArrayBufferView,
toArrayBufferViewAsyncIterator: () => toArrayBufferViewAsyncIterator,
toArrayBufferViewIterator: () => toArrayBufferViewIterator,
toBigInt64Array: () => toBigInt64Array,
toBigUint64Array: () => toBigUint64Array,
toFloat32Array: () => toFloat32Array,
toFloat32ArrayAsyncIterator: () => toFloat32ArrayAsyncIterator,
toFloat32ArrayIterator: () => toFloat32ArrayIterator,
toFloat64Array: () => toFloat64Array,
toFloat64ArrayAsyncIterator: () => toFloat64ArrayAsyncIterator,
toFloat64ArrayIterator: () => toFloat64ArrayIterator,
toInt16Array: () => toInt16Array,
toInt16ArrayAsyncIterator: () => toInt16ArrayAsyncIterator,
toInt16ArrayIterator: () => toInt16ArrayIterator,
toInt32Array: () => toInt32Array,
toInt32ArrayAsyncIterator: () => toInt32ArrayAsyncIterator,
toInt32ArrayIterator: () => toInt32ArrayIterator,
toInt8Array: () => toInt8Array,
toInt8ArrayAsyncIterator: () => toInt8ArrayAsyncIterator,
toInt8ArrayIterator: () => toInt8ArrayIterator,
toUint16Array: () => toUint16Array,
toUint16ArrayAsyncIterator: () => toUint16ArrayAsyncIterator,
toUint16ArrayIterator: () => toUint16ArrayIterator,
toUint32Array: () => toUint32Array,
toUint32ArrayAsyncIterator: () => toUint32ArrayAsyncIterator,
toUint32ArrayIterator: () => toUint32ArrayIterator,
toUint8Array: () => toUint8Array,
toUint8ArrayAsyncIterator: () => toUint8ArrayAsyncIterator,
toUint8ArrayIterator: () => toUint8ArrayIterator,
toUint8ClampedArray: () => toUint8ClampedArray,
toUint8ClampedArrayAsyncIterator: () => toUint8ClampedArrayAsyncIterator,
toUint8ClampedArrayIterator: () => toUint8ClampedArrayIterator
});
// ../../node_modules/apache-arrow/util/utf8.mjs
var decoder = new TextDecoder("utf-8");
var decodeUtf8 = decoder.decode.bind(decoder);
var encoder = new TextEncoder();
var encodeUtf8 = (value) => encoder.encode(value);
// ../../node_modules/apache-arrow/util/compat.mjs
var isNumber = (x) => typeof x === "number";
var isBoolean = (x) => typeof x === "boolean";
var isFunction = (x) => typeof x === "function";
var isObject = (x) => x != null && Object(x) === x;
var isPromise = (x) => {
return isObject(x) && isFunction(x.then);
};
var isIterable = (x) => {
return isObject(x) && isFunction(x[Symbol.iterator]);
};
var isAsyncIterable = (x) => {
return isObject(x) && isFunction(x[Symbol.asyncIterator]);
};
var isArrowJSON = (x) => {
return isObject(x) && isObject(x["schema"]);
};
var isIteratorResult = (x) => {
return isObject(x) && "done" in x && "value" in x;
};
var isFileHandle = (x) => {
return isObject(x) && isFunction(x["stat"]) && isNumber(x["fd"]);
};
var isFetchResponse = (x) => {
return isObject(x) && isReadableDOMStream(x["body"]);
};
var isReadableInterop = (x) => "_getDOMStream" in x && "_getNodeStream" in x;
var isWritableDOMStream = (x) => {
return isObject(x) && isFunction(x["abort"]) && isFunction(x["getWriter"]) && !isReadableInterop(x);
};
var isReadableDOMStream = (x) => {
return isObject(x) && isFunction(x["cancel"]) && isFunction(x["getReader"]) && !isReadableInterop(x);
};
var isWritableNodeStream = (x) => {
return isObject(x) && isFunction(x["end"]) && isFunction(x["write"]) && isBoolean(x["writable"]) && !isReadableInterop(x);
};
var isReadableNodeStream = (x) => {
return isObject(x) && isFunction(x["read"]) && isFunction(x["pipe"]) && isBoolean(x["readable"]) && !isReadableInterop(x);
};
var isFlatbuffersByteBuffer = (x) => {
return isObject(x) && isFunction(x["clear"]) && isFunction(x["bytes"]) && isFunction(x["position"]) && isFunction(x["setPosition"]) && isFunction(x["capacity"]) && isFunction(x["getBufferIdentifier"]) && isFunction(x["createLong"]);
};
// ../../node_modules/apache-arrow/util/buffer.mjs
var SharedArrayBuf = typeof SharedArrayBuffer !== "undefined" ? SharedArrayBuffer : ArrayBuffer;
function collapseContiguousByteRanges(chunks) {
const result = chunks[0] ? [chunks[0]] : [];
let xOffset, yOffset, xLen, yLen;
for (let x, y, i = 0, j = 0, n = chunks.length; ++i < n; ) {
x = result[j];
y = chunks[i];
if (!x || !y || x.buffer !== y.buffer || y.byteOffset < x.byteOffset) {
y && (result[++j] = y);
continue;
}
({ byteOffset: xOffset, byteLength: xLen } = x);
({ byteOffset: yOffset, byteLength: yLen } = y);
if (xOffset + xLen < yOffset || yOffset + yLen < xOffset) {
y && (result[++j] = y);
continue;
}
result[j] = new Uint8Array(x.buffer, xOffset, yOffset - xOffset + yLen);
}
return result;
}
function memcpy(target, source, targetByteOffset = 0, sourceByteLength = source.byteLength) {
const targetByteLength = target.byteLength;
const dst = new Uint8Array(target.buffer, target.byteOffset, targetByteLength);
const src = new Uint8Array(source.buffer, source.byteOffset, Math.min(sourceByteLength, targetByteLength));
dst.set(src, targetByteOffset);
return target;
}
function joinUint8Arrays(chunks, size) {
const result = collapseContiguousByteRanges(chunks);
const byteLength = result.reduce((x, b) => x + b.byteLength, 0);
let source, sliced, buffer;
let offset = 0, index = -1;
const length = Math.min(size || Number.POSITIVE_INFINITY, byteLength);
for (const n = result.length; ++index < n; ) {
source = result[index];
sliced = source.subarray(0, Math.min(source.length, length - offset));
if (length <= offset + sliced.length) {
if (sliced.length < source.length) {
result[index] = source.subarray(sliced.length);
} else if (sliced.length === source.length) {
index++;
}
buffer ? memcpy(buffer, sliced, offset) : buffer = sliced;
break;
}
memcpy(buffer || (buffer = new Uint8Array(length)), sliced, offset);
offset += sliced.length;
}
return [buffer || new Uint8Array(0), result.slice(index), byteLength - (buffer ? buffer.byteLength : 0)];
}
function toArrayBufferView(ArrayBufferViewCtor, input) {
let value = isIteratorResult(input) ? input.value : input;
if (value instanceof ArrayBufferViewCtor) {
if (ArrayBufferViewCtor === Uint8Array) {
return new ArrayBufferViewCtor(value.buffer, value.byteOffset, value.byteLength);
}
return value;
}
if (!value) {
return new ArrayBufferViewCtor(0);
}
if (typeof value === "string") {
value = encodeUtf8(value);
}
if (value instanceof ArrayBuffer) {
return new ArrayBufferViewCtor(value);
}
if (value instanceof SharedArrayBuf) {
return new ArrayBufferViewCtor(value);
}
if (isFlatbuffersByteBuffer(value)) {
return toArrayBufferView(ArrayBufferViewCtor, value.bytes());
}
return !ArrayBuffer.isView(value) ? ArrayBufferViewCtor.from(value) : value.byteLength <= 0 ? new ArrayBufferViewCtor(0) : new ArrayBufferViewCtor(value.buffer, value.byteOffset, value.byteLength / ArrayBufferViewCtor.BYTES_PER_ELEMENT);
}
var toInt8Array = (input) => toArrayBufferView(Int8Array, input);
var toInt16Array = (input) => toArrayBufferView(Int16Array, input);
var toInt32Array = (input) => toArrayBufferView(Int32Array, input);
var toBigInt64Array = (input) => toArrayBufferView(BigInt64Array, input);
var toUint8Array = (input) => toArrayBufferView(Uint8Array, input);
var toUint16Array = (input) => toArrayBufferView(Uint16Array, input);
var toUint32Array = (input) => toArrayBufferView(Uint32Array, input);
var toBigUint64Array = (input) => toArrayBufferView(BigUint64Array, input);
var toFloat32Array = (input) => toArrayBufferView(Float32Array, input);
var toFloat64Array = (input) => toArrayBufferView(Float64Array, input);
var toUint8ClampedArray = (input) => toArrayBufferView(Uint8ClampedArray, input);
var pump = (iterator) => {
iterator.next();
return iterator;
};
function* toArrayBufferViewIterator(ArrayCtor, source) {
const wrap = function* (x) {
yield x;
};
const buffers = typeof source === "string" ? wrap(source) : ArrayBuffer.isView(source) ? wrap(source) : source instanceof ArrayBuffer ? wrap(source) : source instanceof SharedArrayBuf ? wrap(source) : !isIterable(source) ? wrap(source) : source;
yield* pump(function* (it) {
let r = null;
do {
r = it.next(yield toArrayBufferView(ArrayCtor, r));
} while (!r.done);
}(buffers[Symbol.iterator]()));
return new ArrayCtor();
}
var toInt8ArrayIterator = (input) => toArrayBufferViewIterator(Int8Array, input);
var toInt16ArrayIterator = (input) => toArrayBufferViewIterator(Int16Array, input);
var toInt32ArrayIterator = (input) => toArrayBufferViewIterator(Int32Array, input);
var toUint8ArrayIterator = (input) => toArrayBufferViewIterator(Uint8Array, input);
var toUint16ArrayIterator = (input) => toArrayBufferViewIterator(Uint16Array, input);
var toUint32ArrayIterator = (input) => toArrayBufferViewIterator(Uint32Array, input);
var toFloat32ArrayIterator = (input) => toArrayBufferViewIterator(Float32Array, input);
var toFloat64ArrayIterator = (input) => toArrayBufferViewIterator(Float64Array, input);
var toUint8ClampedArrayIterator = (input) => toArrayBufferViewIterator(Uint8ClampedArray, input);
function toArrayBufferViewAsyncIterator(ArrayCtor, source) {
return __asyncGenerator(this, arguments, function* toArrayBufferViewAsyncIterator_1() {
if (isPromise(source)) {
return yield __await(yield __await(yield* __asyncDelegator(__asyncValues(toArrayBufferViewAsyncIterator(ArrayCtor, yield __await(source))))));
}
const wrap = function(x) {
return __asyncGenerator(this, arguments, function* () {
yield yield __await(yield __await(x));
});
};
const emit = function(source2) {
return __asyncGenerator(this, arguments, function* () {
yield __await(yield* __asyncDelegator(__asyncValues(pump(function* (it) {
let r = null;
do {
r = it.next(yield r === null || r === void 0 ? void 0 : r.value);
} while (!r.done);
}(source2[Symbol.iterator]())))));
});
};
const buffers = typeof source === "string" ? wrap(source) : ArrayBuffer.isView(source) ? wrap(source) : source instanceof ArrayBuffer ? wrap(source) : source instanceof SharedArrayBuf ? wrap(source) : isIterable(source) ? emit(source) : !isAsyncIterable(source) ? wrap(source) : source;
yield __await(
// otherwise if AsyncIterable, use it
yield* __asyncDelegator(__asyncValues(pump(function(it) {
return __asyncGenerator(this, arguments, function* () {
let r = null;
do {
r = yield __await(it.next(yield yield __await(toArrayBufferView(ArrayCtor, r))));
} while (!r.done);
});
}(buffers[Symbol.asyncIterator]()))))
);
return yield __await(new ArrayCtor());
});
}
var toInt8ArrayAsyncIterator = (input) => toArrayBufferViewAsyncIterator(Int8Array, input);
var toInt16ArrayAsyncIterator = (input) => toArrayBufferViewAsyncIterator(Int16Array, input);
var toInt32ArrayAsyncIterator = (input) => toArrayBufferViewAsyncIterator(Int32Array, input);
var toUint8ArrayAsyncIterator = (input) => toArrayBufferViewAsyncIterator(Uint8Array, input);
var toUint16ArrayAsyncIterator = (input) => toArrayBufferViewAsyncIterator(Uint16Array, input);
var toUint32ArrayAsyncIterator = (input) => toArrayBufferViewAsyncIterator(Uint32Array, input);
var toFloat32ArrayAsyncIterator = (input) => toArrayBufferViewAsyncIterator(Float32Array, input);
var toFloat64ArrayAsyncIterator = (input) => toArrayBufferViewAsyncIterator(Float64Array, input);
var toUint8ClampedArrayAsyncIterator = (input) => toArrayBufferViewAsyncIterator(Uint8ClampedArray, input);
function rebaseValueOffsets(offset, length, valueOffsets) {
if (offset !== 0) {
valueOffsets = valueOffsets.slice(0, length);
for (let i = -1, n = valueOffsets.length; ++i < n; ) {
valueOffsets[i] += offset;
}
}
return valueOffsets.subarray(0, length);
}
function compareArrayLike(a, b) {
let i = 0;
const n = a.length;
if (n !== b.length) {
return false;
}
if (n > 0) {
do {
if (a[i] !== b[i]) {
return false;
}
} while (++i < n);
}
return true;
}
// ../../node_modules/apache-arrow/io/adapters.mjs
var adapters_default = {
fromIterable(source) {
return pump2(fromIterable(source));
},
fromAsyncIterable(source) {
return pump2(fromAsyncIterable(source));
},
fromDOMStream(source) {
return pump2(fromDOMStream(source));
},
fromNodeStream(stream) {
return pump2(fromNodeStream(stream));
},
// @ts-ignore
toDOMStream(source, options) {
throw new Error(`"toDOMStream" not available in this environment`);
},
// @ts-ignore
toNodeStream(source, options) {
throw new Error(`"toNodeStream" not available in this environment`);
}
};
var pump2 = (iterator) => {
iterator.next();
return iterator;
};
function* fromIterable(source) {
let done, threw = false;
let buffers = [], buffer;
let cmd, size, bufferLength = 0;
function byteRange() {
if (cmd === "peek") {
return joinUint8Arrays(buffers, size)[0];
}
[buffer, buffers, bufferLength] = joinUint8Arrays(buffers, size);
return buffer;
}
({ cmd, size } = (yield (() => null)()) || { cmd: "read", size: 0 });
const it = toUint8ArrayIterator(source)[Symbol.iterator]();
try {
do {
({ done, value: buffer } = Number.isNaN(size - bufferLength) ? it.next() : it.next(size - bufferLength));
if (!done && buffer.byteLength > 0) {
buffers.push(buffer);
bufferLength += buffer.byteLength;
}
if (done || size <= bufferLength) {
do {
({ cmd, size } = yield byteRange());
} while (size < bufferLength);
}
} while (!done);
} catch (e) {
threw = true;
typeof it.throw === "function" && it.throw(e);
} finally {
threw === false && typeof it.return === "function" && it.return(null);
}
return null;
}
function fromAsyncIterable(source) {
return __asyncGenerator(this, arguments, function* fromAsyncIterable_1() {
let done, threw = false;
let buffers = [], buffer;
let cmd, size, bufferLength = 0;
function byteRange() {
if (cmd === "peek") {
return joinUint8Arrays(buffers, size)[0];
}
[buffer, buffers, bufferLength] = joinUint8Arrays(buffers, size);
return buffer;
}
({ cmd, size } = (yield yield __await((() => null)())) || { cmd: "read", size: 0 });
const it = toUint8ArrayAsyncIterator(source)[Symbol.asyncIterator]();
try {
do {
({ done, value: buffer } = Number.isNaN(size - bufferLength) ? yield __await(it.next()) : yield __await(it.next(size - bufferLength)));
if (!done && buffer.byteLength > 0) {
buffers.push(buffer);
bufferLength += buffer.byteLength;
}
if (done || size <= bufferLength) {
do {
({ cmd, size } = yield yield __await(byteRange()));
} while (size < bufferLength);
}
} while (!done);
} catch (e) {
threw = true;
typeof it.throw === "function" && (yield __await(it.throw(e)));
} finally {
threw === false && typeof it.return === "function" && (yield __await(it.return(new Uint8Array(0))));
}
return yield __await(null);
});
}
function fromDOMStream(source) {
return __asyncGenerator(this, arguments, fun