(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['luma'] = factory(); else root['luma'] = factory();})(globalThis, function () { 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:@luma.gl/core var require_core = __commonJS({ "external-global-plugin:@luma.gl/core"(exports, module) { module.exports = globalThis.luma; } }); // external-global-plugin:@luma.gl/engine var require_engine = __commonJS({ "external-global-plugin:@luma.gl/engine"(exports, module) { module.exports = globalThis.luma; } }); // bundle.ts var bundle_exports = {}; __export(bundle_exports, { GLTFAnimator: () => GLTFAnimator, createScenegraphsFromGLTF: () => createScenegraphsFromGLTF, loadPBREnvironment: () => loadPBREnvironment, parsePBRMaterial: () => parsePBRMaterial }); __reExport(bundle_exports, __toESM(require_core(), 1)); // src/pbr/parse-pbr-material.ts var import_core = __toESM(require_core(), 1); function parsePBRMaterial(device, material, attributes, options) { const parsedMaterial = { defines: { // TODO: Use EXT_sRGB if available (Standard in WebGL 2.0) MANUAL_SRGB: 1, SRGB_FAST_APPROXIMATION: 1 }, bindings: {}, uniforms: { // TODO: find better values? u_Camera: [0, 0, 0], // Model should override u_MetallicRoughnessValues: [1, 1] // Default is 1 and 1 }, parameters: {}, glParameters: {}, generatedTextures: [] }; parsedMaterial.defines.USE_TEX_LOD = 1; const { imageBasedLightingEnvironment } = options; if (imageBasedLightingEnvironment) { parsedMaterial.bindings.u_DiffuseEnvSampler = imageBasedLightingEnvironment.diffuseEnvSampler; parsedMaterial.bindings.u_SpecularEnvSampler = imageBasedLightingEnvironment.specularEnvSampler; parsedMaterial.bindings.u_brdfLUT = imageBasedLightingEnvironment.brdfLutTexture; parsedMaterial.uniforms.u_ScaleIBLAmbient = [1, 1]; } if (options?.pbrDebug) { parsedMaterial.defines.PBR_DEBUG = 1; parsedMaterial.uniforms.u_ScaleDiffBaseMR = [0, 0, 0, 0]; parsedMaterial.uniforms.u_ScaleFGDSpec = [0, 0, 0, 0]; } if (attributes.NORMAL) parsedMaterial.defines.HAS_NORMALS = 1; if (attributes.TANGENT && options?.useTangents) parsedMaterial.defines.HAS_TANGENTS = 1; if (attributes.TEXCOORD_0) parsedMaterial.defines.HAS_UV = 1; if (options?.imageBasedLightingEnvironment) parsedMaterial.defines.USE_IBL = 1; if (options?.lights) parsedMaterial.defines.USE_LIGHTS = 1; if (material) { parseMaterial(device, material, parsedMaterial); } return parsedMaterial; } function parseMaterial(device, material, parsedMaterial) { parsedMaterial.uniforms.pbr_uUnlit = Boolean(material.unlit); if (material.pbrMetallicRoughness) { parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial); } if (material.normalTexture) { addTexture(device, material.normalTexture, "u_NormalSampler", "HAS_NORMALMAP", parsedMaterial); const { scale: scale4 = 1 } = material.normalTexture; parsedMaterial.uniforms.u_NormalScale = scale4; } if (material.occlusionTexture) { addTexture( device, material.occlusionTexture, "u_OcclusionSampler", "HAS_OCCLUSIONMAP", parsedMaterial ); const { strength = 1 } = material.occlusionTexture; parsedMaterial.uniforms.u_OcclusionStrength = strength; } if (material.emissiveTexture) { addTexture( device, material.emissiveTexture, "u_EmissiveSampler", "HAS_EMISSIVEMAP", parsedMaterial ); parsedMaterial.uniforms.u_EmissiveFactor = material.emissiveFactor || [0, 0, 0]; } switch (material.alphaMode) { case "MASK": const { alphaCutoff = 0.5 } = material; parsedMaterial.defines.ALPHA_CUTOFF = 1; parsedMaterial.uniforms.u_AlphaCutoff = alphaCutoff; break; case "BLEND": import_core.log.warn("glTF BLEND alphaMode might not work well because it requires mesh sorting")(); parsedMaterial.parameters.blendColorOperation = "add"; parsedMaterial.parameters.blendColorSrcFactor = "src-alpha"; parsedMaterial.parameters.blendColorDstFactor = "one-minus-src-alpha"; parsedMaterial.parameters.blendAlphaOperation = "add"; parsedMaterial.parameters.blendAlphaSrcFactor = "one"; parsedMaterial.parameters.blendAlphaDstFactor = "one-minus-src-alpha"; parsedMaterial.glParameters.blend = true; parsedMaterial.glParameters.blendEquation = 32774 /* FUNC_ADD */; parsedMaterial.glParameters.blendFunc = [ 770 /* SRC_ALPHA */, 771 /* ONE_MINUS_SRC_ALPHA */, 1 /* ONE */, 771 /* ONE_MINUS_SRC_ALPHA */ ]; break; } } function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial) { if (pbrMetallicRoughness.baseColorTexture) { addTexture( device, pbrMetallicRoughness.baseColorTexture, "u_BaseColorSampler", "HAS_BASECOLORMAP", parsedMaterial ); } parsedMaterial.uniforms.u_BaseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1]; if (pbrMetallicRoughness.metallicRoughnessTexture) { addTexture( device, pbrMetallicRoughness.metallicRoughnessTexture, "u_MetallicRoughnessSampler", "HAS_METALROUGHNESSMAP", parsedMaterial ); } const { metallicFactor = 1, roughnessFactor = 1 } = pbrMetallicRoughness; parsedMaterial.uniforms.u_MetallicRoughnessValues = [metallicFactor, roughnessFactor]; } function addTexture(device, gltfTexture, uniformName, define = null, parsedMaterial) { const parameters = gltfTexture?.texture?.sampler?.parameters || {}; const image = gltfTexture.texture.source.image; let textureOptions; let specialTextureParameters = {}; if (image.compressed) { textureOptions = image; specialTextureParameters = { [10241 /* TEXTURE_MIN_FILTER */]: image.data.length > 1 ? 9985 /* LINEAR_MIPMAP_NEAREST */ : 9729 /* LINEAR */ }; } else { textureOptions = { data: image }; } const texture = device.createTexture({ id: gltfTexture.uniformName || gltfTexture.id, parameters: { ...parameters, ...specialTextureParameters }, pixelStore: { [37440 /* UNPACK_FLIP_Y_WEBGL */]: false }, ...textureOptions }); parsedMaterial.bindings[uniformName] = texture; if (define) parsedMaterial.defines[define] = 1; parsedMaterial.generatedTextures.push(texture); } // ../../node_modules/@loaders.gl/loader-utils/dist/lib/env-utils/assert.js function assert(condition, message) { if (!condition) { throw new Error(message || "loader assertion failed."); } } // ../../node_modules/@loaders.gl/loader-utils/dist/lib/env-utils/globals.js 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 does not exist on browser Boolean(typeof process !== "object" || String(process) !== "[object process]" || process.browser) ); var matches = typeof process !== "undefined" && process.version && /v([0-9]*)/.exec(process.version); var nodeVersion = matches && parseFloat(matches[1]) || 0; // ../../node_modules/@loaders.gl/loader-utils/dist/lib/path-utils/file-aliases.js var pathPrefix = ""; var fileAliases = {}; function resolvePath(filename) { for (const alias in fileAliases) { if (filename.startsWith(alias)) { const replacement = fileAliases[alias]; filename = filename.replace(alias, replacement); } } if (!filename.startsWith("http://") && !filename.startsWith("https://")) { filename = `${pathPrefix}${filename}`; } return filename; } // ../../node_modules/@loaders.gl/images/dist/lib/utils/version.js var VERSION = true ? "4.2.1" : "latest"; // ../../node_modules/@loaders.gl/images/dist/lib/category-api/image-type.js var parseImageNode = globalThis.loaders?.parseImageNode; var IMAGE_SUPPORTED = typeof Image !== "undefined"; var IMAGE_BITMAP_SUPPORTED = typeof ImageBitmap !== "undefined"; var NODE_IMAGE_SUPPORTED = Boolean(parseImageNode); var DATA_SUPPORTED = isBrowser ? true : NODE_IMAGE_SUPPORTED; function isImageTypeSupported(type) { switch (type) { case "auto": return IMAGE_BITMAP_SUPPORTED || IMAGE_SUPPORTED || DATA_SUPPORTED; case "imagebitmap": return IMAGE_BITMAP_SUPPORTED; case "image": return IMAGE_SUPPORTED; case "data": return DATA_SUPPORTED; default: throw new Error(`@loaders.gl/images: image ${type} not supported in this environment`); } } function getDefaultImageType() { if (IMAGE_BITMAP_SUPPORTED) { return "imagebitmap"; } if (IMAGE_SUPPORTED) { return "image"; } if (DATA_SUPPORTED) { return "data"; } throw new Error("Install '@loaders.gl/polyfills' to parse images under Node.js"); } // ../../node_modules/@loaders.gl/images/dist/lib/category-api/parsed-image-api.js function getImageType(image) { const format = getImageTypeOrNull(image); if (!format) { throw new Error("Not an image"); } return format; } function getImageSize(image) { return getImageData(image); } function getImageData(image) { switch (getImageType(image)) { case "data": return image; case "image": case "imagebitmap": const canvas = document.createElement("canvas"); const context = canvas.getContext("2d"); if (!context) { throw new Error("getImageData"); } canvas.width = image.width; canvas.height = image.height; context.drawImage(image, 0, 0); return context.getImageData(0, 0, image.width, image.height); default: throw new Error("getImageData"); } } function getImageTypeOrNull(image) { if (typeof ImageBitmap !== "undefined" && image instanceof ImageBitmap) { return "imagebitmap"; } if (typeof Image !== "undefined" && image instanceof Image) { return "image"; } if (image && typeof image === "object" && image.data && image.width && image.height) { return "data"; } return null; } // ../../node_modules/@loaders.gl/images/dist/lib/parsers/svg-utils.js var SVG_DATA_URL_PATTERN = /^data:image\/svg\+xml/; var SVG_URL_PATTERN = /\.svg((\?|#).*)?$/; function isSVG(url) { return url && (SVG_DATA_URL_PATTERN.test(url) || SVG_URL_PATTERN.test(url)); } function getBlobOrSVGDataUrl(arrayBuffer, url) { if (isSVG(url)) { const textDecoder = new TextDecoder(); let xmlText = textDecoder.decode(arrayBuffer); try { if (typeof unescape === "function" && typeof encodeURIComponent === "function") { xmlText = unescape(encodeURIComponent(xmlText)); } } catch (error) { throw new Error(error.message); } const src = `data:image/svg+xml;base64,${btoa(xmlText)}`; return src; } return getBlob(arrayBuffer, url); } function getBlob(arrayBuffer, url) { if (isSVG(url)) { throw new Error("SVG cannot be parsed directly to imagebitmap"); } return new Blob([new Uint8Array(arrayBuffer)]); } // ../../node_modules/@loaders.gl/images/dist/lib/parsers/parse-to-image.js async function parseToImage(arrayBuffer, options, url) { const blobOrDataUrl = getBlobOrSVGDataUrl(arrayBuffer, url); const URL = self.URL || self.webkitURL; const objectUrl = typeof blobOrDataUrl !== "string" && URL.createObjectURL(blobOrDataUrl); try { return await loadToImage(objectUrl || blobOrDataUrl, options); } finally { if (objectUrl) { URL.revokeObjectURL(objectUrl); } } } async function loadToImage(url, options) { const image = new Image(); image.src = url; if (options.image && options.image.decode && image.decode) { await image.decode(); return image; } return await new Promise((resolve, reject) => { try { image.onload = () => resolve(image); image.onerror = (error) => { const message = error instanceof Error ? error.message : "error"; reject(new Error(message)); }; } catch (error) { reject(error); } }); } // ../../node_modules/@loaders.gl/images/dist/lib/parsers/parse-to-image-bitmap.js var EMPTY_OBJECT = {}; var imagebitmapOptionsSupported = true; async function parseToImageBitmap(arrayBuffer, options, url) { let blob; if (isSVG(url)) { const image = await parseToImage(arrayBuffer, options, url); blob = image; } else { blob = getBlob(arrayBuffer, url); } const imagebitmapOptions = options && options.imagebitmap; return await safeCreateImageBitmap(blob, imagebitmapOptions); } async function safeCreateImageBitmap(blob, imagebitmapOptions = null) { if (isEmptyObject(imagebitmapOptions) || !imagebitmapOptionsSupported) { imagebitmapOptions = null; } if (imagebitmapOptions) { try { return await createImageBitmap(blob, imagebitmapOptions); } catch (error) { console.warn(error); imagebitmapOptionsSupported = false; } } return await createImageBitmap(blob); } function isEmptyObject(object) { for (const key in object || EMPTY_OBJECT) { return false; } return true; } // ../../node_modules/@loaders.gl/images/dist/lib/category-api/parse-isobmff-binary.js function getISOBMFFMediaType(buffer) { if (!checkString(buffer, "ftyp", 4)) { return null; } if ((buffer[8] & 96) === 0) { return null; } return decodeMajorBrand(buffer); } function decodeMajorBrand(buffer) { const brandMajor = getUTF8String(buffer, 8, 12).replace("\0", " ").trim(); switch (brandMajor) { case "avif": case "avis": return { extension: "avif", mimeType: "image/avif" }; default: return null; } } function getUTF8String(array, start, end) { return String.fromCharCode(...array.slice(start, end)); } function stringToBytes(string) { return [...string].map((character) => character.charCodeAt(0)); } function checkString(buffer, header, offset = 0) { const headerBytes = stringToBytes(header); for (let i = 0; i < headerBytes.length; ++i) { if (headerBytes[i] !== buffer[i + offset]) { return false; } } return true; } // ../../node_modules/@loaders.gl/images/dist/lib/category-api/binary-image-api.js var BIG_ENDIAN = false; var LITTLE_ENDIAN = true; function getBinaryImageMetadata(binaryData) { const dataView = toDataView(binaryData); return getPngMetadata(dataView) || getJpegMetadata(dataView) || getGifMetadata(dataView) || getBmpMetadata(dataView) || getISOBMFFMetadata(dataView); } function getISOBMFFMetadata(binaryData) { const buffer = new Uint8Array(binaryData instanceof DataView ? binaryData.buffer : binaryData); const mediaType = getISOBMFFMediaType(buffer); if (!mediaType) { return null; } return { mimeType: mediaType.mimeType, // TODO - decode width and height width: 0, height: 0 }; } function getPngMetadata(binaryData) { const dataView = toDataView(binaryData); const isPng = dataView.byteLength >= 24 && dataView.getUint32(0, BIG_ENDIAN) === 2303741511; if (!isPng) { return null; } return { mimeType: "image/png", width: dataView.getUint32(16, BIG_ENDIAN), height: dataView.getUint32(20, BIG_ENDIAN) }; } function getGifMetadata(binaryData) { const dataView = toDataView(binaryData); const isGif = dataView.byteLength >= 10 && dataView.getUint32(0, BIG_ENDIAN) === 1195984440; if (!isGif) { return null; } return { mimeType: "image/gif", width: dataView.getUint16(6, LITTLE_ENDIAN), height: dataView.getUint16(8, LITTLE_ENDIAN) }; } function getBmpMetadata(binaryData) { const dataView = toDataView(binaryData); const isBmp = dataView.byteLength >= 14 && dataView.getUint16(0, BIG_ENDIAN) === 16973 && dataView.getUint32(2, LITTLE_ENDIAN) === dataView.byteLength; if (!isBmp) { return null; } return { mimeType: "image/bmp", width: dataView.getUint32(18, LITTLE_ENDIAN), height: dataView.getUint32(22, LITTLE_ENDIAN) }; } function getJpegMetadata(binaryData) { const dataView = toDataView(binaryData); const isJpeg = dataView.byteLength >= 3 && dataView.getUint16(0, BIG_ENDIAN) === 65496 && dataView.getUint8(2) === 255; if (!isJpeg) { return null; } const { tableMarkers, sofMarkers } = getJpegMarkers(); let i = 2; while (i + 9 < dataView.byteLength) { const marker = dataView.getUint16(i, BIG_ENDIAN); if (sofMarkers.has(marker)) { return { mimeType: "image/jpeg", height: dataView.getUint16(i + 5, BIG_ENDIAN), // Number of lines width: dataView.getUint16(i + 7, BIG_ENDIAN) // Number of pixels per line }; } if (!tableMarkers.has(marker)) { return null; } i += 2; i += dataView.getUint16(i, BIG_ENDIAN); } return null; } function getJpegMarkers() { const tableMarkers = /* @__PURE__ */ new Set([65499, 65476, 65484, 65501, 65534]); for (let i = 65504; i < 65520; ++i) { tableMarkers.add(i); } const sofMarkers = /* @__PURE__ */ new Set([ 65472, 65473, 65474, 65475, 65477, 65478, 65479, 65481, 65482, 65483, 65485, 65486, 65487, 65502 ]); return { tableMarkers, sofMarkers }; } function toDataView(data) { if (data instanceof DataView) { return data; } if (ArrayBuffer.isView(data)) { return new DataView(data.buffer); } if (data instanceof ArrayBuffer) { return new DataView(data); } throw new Error("toDataView"); } // ../../node_modules/@loaders.gl/images/dist/lib/parsers/parse-to-node-image.js async function parseToNodeImage(arrayBuffer, options) { const { mimeType } = getBinaryImageMetadata(arrayBuffer) || {}; const parseImageNode2 = globalThis.loaders?.parseImageNode; assert(parseImageNode2); return await parseImageNode2(arrayBuffer, mimeType); } // ../../node_modules/@loaders.gl/images/dist/lib/parsers/parse-image.js async function parseImage(arrayBuffer, options, context) { options = options || {}; const imageOptions = options.image || {}; const imageType = imageOptions.type || "auto"; const { url } = context || {}; const loadType = getLoadableImageType(imageType); let image; switch (loadType) { case "imagebitmap": image = await parseToImageBitmap(arrayBuffer, options, url); break; case "image": image = await parseToImage(arrayBuffer, options, url); break; case "data": image = await parseToNodeImage(arrayBuffer, options); break; default: assert(false); } if (imageType === "data") { image = getImageData(image); } return image; } function getLoadableImageType(type) { switch (type) { case "auto": case "data": return getDefaultImageType(); default: isImageTypeSupported(type); return type; } } // ../../node_modules/@loaders.gl/images/dist/image-loader.js var EXTENSIONS = ["png", "jpg", "jpeg", "gif", "webp", "bmp", "ico", "svg", "avif"]; var MIME_TYPES = [ "image/png", "image/jpeg", "image/gif", "image/webp", "image/avif", "image/bmp", "image/vnd.microsoft.icon", "image/svg+xml" ]; var DEFAULT_IMAGE_LOADER_OPTIONS = { image: { type: "auto", decode: true // if format is HTML } // imagebitmap: {} - passes (platform dependent) parameters to ImageBitmap constructor }; var ImageLoader = { dataType: null, batchType: null, id: "image", module: "images", name: "Images", version: VERSION, mimeTypes: MIME_TYPES, extensions: EXTENSIONS, parse: parseImage, // TODO: byteOffset, byteLength; tests: [(arrayBuffer) => Boolean(getBinaryImageMetadata(new DataView(arrayBuffer)))], options: DEFAULT_IMAGE_LOADER_OPTIONS }; // ../../node_modules/@loaders.gl/textures/dist/lib/texture-api/generate-url.js function generateUrl(getUrl, options, urlOptions) { let url = typeof getUrl === "function" ? getUrl({ ...options, ...urlOptions }) : getUrl; const baseUrl = options.baseUrl; if (baseUrl) { url = baseUrl[baseUrl.length - 1] === "/" ? `${baseUrl}${url}` : `${baseUrl}/${url}`; } return resolvePath(url); } // ../../node_modules/@loaders.gl/textures/dist/lib/texture-api/async-deep-map.js var isObject = (value) => value && typeof value === "object"; async function asyncDeepMap(tree, func, options = {}) { return await mapSubtree(tree, func, options); } async function mapSubtree(object, func, options) { if (Array.isArray(object)) { return await mapArray(object, func, options); } if (isObject(object)) { return await mapObject(object, func, options); } const url = object; return await func(url, options); } async function mapObject(object, func, options) { const promises = []; const values = {}; for (const key in object) { const url = object[key]; const promise = mapSubtree(url, func, options).then((value) => { values[key] = value; }); promises.push(promise); } await Promise.all(promises); return values; } async function mapArray(urlArray, func, options = {}) { const promises = urlArray.map((url) => mapSubtree(url, func, options)); return await Promise.all(promises); } // ../../node_modules/@loaders.gl/textures/dist/lib/texture-api/deep-load.js async function deepLoad(urlTree, load, options) { return await asyncDeepMap(urlTree, (url) => shallowLoad(url, load, options)); } async function shallowLoad(url, load, options) { const response = await fetch(url, options.fetch); const arrayBuffer = await response.arrayBuffer(); return await load(arrayBuffer, options); } // ../../node_modules/@loaders.gl/textures/dist/lib/texture-api/load-image.js async function loadImageTexture(getUrl, options = {}) { const imageUrls = await getImageUrls(getUrl, options); return await deepLoad(imageUrls, ImageLoader.parse, options); } async function getImageUrls(getUrl, options, urlOptions = {}) { const mipLevels = options && options.image && options.image.mipLevels || 0; return mipLevels !== 0 ? await getMipmappedImageUrls(getUrl, mipLevels, options, urlOptions) : generateUrl(getUrl, options, urlOptions); } async function getMipmappedImageUrls(getUrl, mipLevels, options, urlOptions) { const urls = []; if (mipLevels === "auto") { const url = generateUrl(getUrl, options, { ...urlOptions, lod: 0 }); const image = await shallowLoad(url, ImageLoader.parse, options); const { width, height } = getImageSize(image); mipLevels = getMipLevels({ width, height }); urls.push(url); } assert(mipLevels > 0); for (let mipLevel = urls.length; mipLevel < mipLevels; ++mipLevel) { const url = generateUrl(getUrl, options, { ...urlOptions, lod: mipLevel }); urls.push(url); } return urls; } function getMipLevels(size) { return 1 + Math.floor(Math.log2(Math.max(size.width, size.height))); } // src/pbr/pbr-environment.ts function loadPBREnvironment(device, props) { const brdfLutTexture = device.createTexture({ id: "brdfLUT", sampler: { wrapS: "clamp-to-edge", wrapT: "clamp-to-edge", minFilter: "linear", maxFilter: "linear" }, // Texture accepts a promise that returns an image as data (Async Textures) data: loadImageTexture(props.brdfLutUrl) }); const diffuseEnvSampler = makeCube(device, { id: "DiffuseEnvSampler", getTextureForFace: (dir) => loadImageTexture(props.getTexUrl("diffuse", dir, 0)), sampler: { wrapS: "clamp-to-edge", wrapT: "clamp-to-edge", minFilter: "linear", maxFilter: "linear" } }); const specularEnvSampler = makeCube(device, { id: "SpecularEnvSampler", getTextureForFace: (dir) => { const imageArray = []; for (let lod = 0; lod <= props.specularMipLevels - 1; lod++) { imageArray.push(loadImageTexture(props.getTexUrl("specular", dir, lod))); } return imageArray; }, sampler: { wrapS: "clamp-to-edge", wrapT: "clamp-to-edge", minFilter: "linear", // [GL.TEXTURE_MIN_FILTER]: GL.LINEAR_MIPMAP_LINEAR, maxFilter: "linear" } }); return { brdfLutTexture, diffuseEnvSampler, specularEnvSampler }; } var FACES = [0, 1, 2, 3, 4, 5]; function makeCube(device, { id, getTextureForFace, sampler }) { const data = {}; FACES.forEach((face) => { data[String(face)] = getTextureForFace(face); }); return device.createTexture({ id, dimension: "cube", mipmaps: false, sampler, data }); } // src/gltf/gltf-instantiator.ts var import_engine2 = __toESM(require_engine(), 1); // ../../node_modules/@math.gl/core/dist/lib/common.js var RADIANS_TO_DEGREES = 1 / Math.PI * 180; var DEGREES_TO_RADIANS = 1 / 180 * Math.PI; var DEFAULT_CONFIG = { EPSILON: 1e-12, debug: false, precision: 4, printTypes: false, printDegrees: false, printRowMajor: true, _cartographicRadians: false }; globalThis.mathgl = globalThis.mathgl || { config: { ...DEFAULT_CONFIG } }; var config = globalThis.mathgl.config; function formatValue(value, { precision = config.precision } = {}) { value = round(value); return `${parseFloat(value.toPrecision(precision))}`; } function isArray(value) { return Array.isArray(value) || ArrayBuffer.isView(value) && !(value instanceof DataView); } function equals(a, b, epsilon) { const oldEpsilon = config.EPSILON; if (epsilon) { config.EPSILON = epsilon; } try { if (a === b) { return true; } if (isArray(a) && isArray(b)) { if (a.length !== b.length) { return false; } for (let i = 0; i < a.length; ++i) { if (!equals(a[i], b[i])) { return false; } } return true; } if (a && a.equals) { return a.equals(b); } if (b && b.equals) { return b.equals(a); } if (typeof a === "number" && typeof b === "number") { return Math.abs(a - b) <= config.EPSILON * Math.max(1, Math.abs(a), Math.abs(b)); } return false; } finally { config.EPSILON = oldEpsilon; } } function round(value) { return Math.round(value / config.EPSILON) * config.EPSILON; } // ../../node_modules/@math.gl/core/dist/classes/base/math-array.js var MathArray = class extends Array { // Common methods /** * Clone the current object * @returns a new copy of this object */ clone() { return new this.constructor().copy(this); } fromArray(array, offset = 0) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] = array[i + offset]; } return this.check(); } toArray(targetArray = [], offset = 0) { for (let i = 0; i < this.ELEMENTS; ++i) { targetArray[offset + i] = this[i]; } return targetArray; } toObject(targetObject) { return targetObject; } from(arrayOrObject) { return Array.isArray(arrayOrObject) ? this.copy(arrayOrObject) : ( // @ts-ignore this.fromObject(arrayOrObject) ); } to(arrayOrObject) { if (arrayOrObject === this) { return this; } return isArray(arrayOrObject) ? this.toArray(arrayOrObject) : this.toObject(arrayOrObject); } toTarget(target) { return target ? this.to(target) : this; } /** @deprecated */ toFloat32Array() { return new Float32Array(this); } toString() { return this.formatString(config); } /** Formats string according to options */ formatString(opts) { let string = ""; for (let i = 0; i < this.ELEMENTS; ++i) { string += (i > 0 ? ", " : "") + formatValue(this[i], opts); } return `${opts.printTypes ? this.constructor.name : ""}[${string}]`; } equals(array) { if (!array || this.length !== array.length) { return false; } for (let i = 0; i < this.ELEMENTS; ++i) { if (!equals(this[i], array[i])) { return false; } } return true; } exactEquals(array) { if (!array || this.length !== array.length) { return false; } for (let i = 0; i < this.ELEMENTS; ++i) { if (this[i] !== array[i]) { return false; } } return true; } // Modifiers /** Negates all values in this object */ negate() { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] = -this[i]; } return this.check(); } lerp(a, b, t) { if (t === void 0) { return this.lerp(this, a, b); } for (let i = 0; i < this.ELEMENTS; ++i) { const ai = a[i]; const endValue = typeof b === "number" ? b : b[i]; this[i] = ai + t * (endValue - ai); } return this.check(); } /** Minimal */ min(vector) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] = Math.min(vector[i], this[i]); } return this.check(); } /** Maximal */ max(vector) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] = Math.max(vector[i], this[i]); } return this.check(); } clamp(minVector, maxVector) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] = Math.min(Math.max(this[i], minVector[i]), maxVector[i]); } return this.check(); } add(...vectors) { for (const vector of vectors) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] += vector[i]; } } return this.check(); } subtract(...vectors) { for (const vector of vectors) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] -= vector[i]; } } return this.check(); } scale(scale4) { if (typeof scale4 === "number") { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] *= scale4; } } else { for (let i = 0; i < this.ELEMENTS && i < scale4.length; ++i) { this[i] *= scale4[i]; } } return this.check(); } /** * Multiplies all elements by `scale` * Note: `Matrix4.multiplyByScalar` only scales its 3x3 "minor" */ multiplyByScalar(scalar) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] *= scalar; } return this.check(); } // Debug checks /** Throws an error if array length is incorrect or contains illegal values */ check() { if (config.debug && !this.validate()) { throw new Error(`math.gl: ${this.constructor.name} some fields set to invalid numbers'`); } return this; } /** Returns false if the array length is incorrect or contains illegal values */ validate() { let valid = this.length === this.ELEMENTS; for (let i = 0; i < this.ELEMENTS; ++i) { valid = valid && Number.isFinite(this[i]); } return valid; } // three.js compatibility /** @deprecated */ sub(a) { return this.subtract(a); } /** @deprecated */ setScalar(a) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] = a; } return this.check(); } /** @deprecated */ addScalar(a) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] += a; } return this.check(); } /** @deprecated */ subScalar(a) { return this.addScalar(-a); } /** @deprecated */ multiplyScalar(scalar) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] *= scalar; } return this.check(); } /** @deprecated */ divideScalar(a) { return this.multiplyByScalar(1 / a); } /** @deprecated */ clampScalar(min, max) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] = Math.min(Math.max(this[i], min), max); } return this.check(); } /** @deprecated */ get elements() { return this; } }; // ../../node_modules/@math.gl/core/dist/lib/validators.js function validateVector(v, length4) { if (v.length !== length4) { return false; } for (let i = 0; i < v.length; ++i) { if (!Number.isFinite(v[i])) { return false; } } return true; } function checkNumber(value) { if (!Number.isFinite(value)) { throw new Error(`Invalid number ${JSON.stringify(value)}`); } return value; } function checkVector(v, length4, callerName = "") { if (config.debug && !validateVector(v, length4)) { throw new Error(`math.gl: ${callerName} some fields set to invalid numbers'`); } return v; } // ../../node_modules/@math.gl/core/dist/lib/assert.js function assert2(condition, message) { if (!condition) { throw new Error(`math.gl assertion ${message}`); } } // ../../node_modules/@math.gl/core/dist/classes/base/vector.js var Vector = class extends MathArray { // ACCESSORS get x() { return this[0]; } set x(value) { this[0] = checkNumber(value); } get y() { return this[1]; } set y(value) { this[1] = checkNumber(value); } /** * Returns the length of the vector from the origin to the point described by this vector * * @note `length` is a reserved word for Arrays, so `v.length()` will return number of elements * Instead we provide `len` and `magnitude` */ len() { return Math.sqrt(this.lengthSquared()); } /** * Returns the length of the vector from the origin to the point described by this vector */ magnitude() { return this.len(); } /** * Returns the squared length of the vector from the origin to the point described by this vector */ lengthSquared() { let length4 = 0; for (let i = 0; i < this.ELEMENTS; ++i) { length4 += this[i] * this[i]; } return length4; } /** * Returns the squared length of the vector from the origin to the point described by this vector */ magnitudeSquared() { return this.lengthSquared(); } distance(mathArray) { return Math.sqrt(this.distanceSquared(mathArray)); } distanceSquared(mathArray) { let length4 = 0; for (let i = 0; i < this.ELEMENTS; ++i) { const dist = this[i] - mathArray[i]; length4 += dist * dist; } return checkNumber(length4); } dot(mathArray) { let product = 0; for (let i = 0; i < this.ELEMENTS; ++i) { product += this[i] * mathArray[i]; } return checkNumber(product); } // MODIFIERS normalize() { const length4 = this.magnitude(); if (length4 !== 0) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] /= length4; } } return this.check(); } multiply(...vectors) { for (const vector of vectors) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] *= vector[i]; } } return this.check(); } divide(...vectors) { for (const vector of vectors) { for (let i = 0; i < this.ELEMENTS; ++i) { this[i] /= vector[i]; } } return this.check(); } // THREE.js compatibility lengthSq() { return this.lengthSquared(); } distanceTo(vector) { return this.distance(vector); } distanceToSquared(vector) { return this.distanceSquared(vector); } getComponent(i) { assert2(i >= 0 && i < this.ELEMENTS, "index is out of range"); return checkNumber(this[i]); } setComponent(i, value) { assert2(i >= 0 && i < this.ELEMENTS, "index is out of range"); this[i] = value; return this.check(); } addVectors(a, b) { return this.copy(a).add(b); } subVectors(a, b) { return this.copy(a).subtract(b); } multiplyVectors(a, b) { return this.copy(a).multiply(b); } addScaledVector(a, b) { return this.add(new this.constructor(a).multiplyScalar(b)); } }; // ../../node_modules/@math.gl/core/dist/gl-matrix/common.js var EPSILON = 1e-6; var ARRAY_TYPE = typeof Float32Array !== "undefined" ? Float32Array : Array; var degree = Math.PI / 180; // ../../node_modules/@math.gl/core/dist/gl-matrix/vec2.js function create() { const out = new ARRAY_TYPE(2); if (ARRAY_TYPE != Float32Array) { out[0] = 0; out[1] = 0; } return out; } function transformMat4(out, a, m) { const x = a[0]; const y = a[1]; out[0] = m[0] * x + m[4] * y + m[12]; out[1] = m[1] * x + m[5] * y + m[13]; return out; } var forEach = function() { const vec = create(); return function(a, stride, offset, count, fn, arg) { let i; let l; if (!stride) { stride = 2; } if (!offset) { offset = 0; } if (count) { l = Math.min(count * stride + offset, a.length); } else { l = a.length; } for (i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i + 1]; fn(vec, vec, arg); a[i] = vec[0]; a[i + 1] = vec[1]; } return a; }; }(); // ../../node_modules/@math.gl/core/dist/lib/gl-matrix-extras.js function vec2_transformMat4AsVector(out, a, m) { const x = a[0]; const y = a[1]; const w = m[3] * x + m[7] * y || 1; out[0] = (m[0] * x + m[4] * y) / w; out[1] = (m[1] * x + m[5] * y) / w; return out; } function vec3_transformMat4AsVector(out, a, m) { const x = a[0]; const y = a[1]; const z = a[2]; const w = m[3] * x + m[7] * y + m[11] * z || 1; out[0] = (m[0] * x + m[4] * y + m[8] * z) / w; out[1] = (m[1] * x + m[5] * y + m[9] * z) / w; out[2] = (m[2] * x + m[6] * y + m[10] * z) / w; return out; } function vec4_transformMat2(out, a, m) { const x = a[0]; const y = a[1]; out[0] = m[0] * x + m[2] * y; out[1] = m[1] * x + m[3] * y; out[2] = a[2]; out[3] = a[3]; return out; } function vec4_transformMat3(out, a, m) { const x = a[0]; const y = a[1]; const z = a[2]; out[0] = m[0] * x + m[3] * y + m[6] * z; out[1] = m[1] * x + m[4] * y + m[7] * z; out[2] = m[2] * x + m[5] * y + m[8] * z; out[3] = a[3]; return out; } // ../../node_modules/@math.gl/core/dist/gl-matrix/vec3.js function create2() { const out = new ARRAY_TYPE(3); if (ARRAY_TYPE != Float32Array) { out[0] = 0; out[1] = 0; out[2] = 0; } return out; } function length(a) { const x = a[0]; const y = a[1]; const z = a[2]; return Math.sqrt(x * x + y * y + z * z); } function fromValues(x, y, z) { const out = new ARRAY_TYPE(3); out[0] = x; out[1] = y; out[2] = z; return out; } function normalize(out, a) { const x = a[0]; const y = a[1]; const z = a[2]; let len2 = x * x + y * y + z * z; if (len2 > 0) { len2 = 1 / Math.sqrt(len2); } out[0] = a[0] * len2; out[1] = a[1] * len2; out[2] = a[2] * len2; return out; } function dot(a, b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; } function cross(out, a, b) { const ax = a[0]; const ay = a[1]; const az = a[2]; const bx = b[0]; const by = b[1]; const bz = b[2]; out[0] = ay * bz - az * by; out[1] = az * bx - ax * bz; out[2] = ax * by - ay * bx; return out; } function transformMat42(out, a, m) { const x = a[0]; const y = a[1]; const z = a[2]; let w = m[3] * x + m[7] * y + m[11] * z + m[15]; w = w || 1; out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) / w; out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) / w; out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) / w; return out; } function transformQuat(out, a, q) { const qx = q[0]; const qy = q[1]; const qz = q[2]; const qw = q[3]; const x = a[0]; const y = a[1]; const z = a[2]; let uvx = qy * z - qz * y; let uvy = qz * x - qx * z; let uvz = qx * y - qy * x; let uuvx = qy * uvz - qz * uvy; let uuvy = qz * uvx - qx * uvz; let uuvz = qx * uvy - qy * uvx; const w2 = qw * 2; uvx *= w2; uvy *= w2; uvz *= w2; uuvx *= 2; uuvy *= 2; uuvz *= 2; out[0] = x + uvx + uuvx; out[1] = y + uvy + uuvy; out[2] = z + uvz + uuvz; return out; } var len = length; var forEach2 = function() { const vec = create2(); return function(a, stride, offset, count, fn, arg) { let i; let l; if (!stride) { stride = 3; } if (!offset) { offset = 0; } if (count) { l = Math.min(count * stride + offset, a.length); } else { l = a.length; } for (i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i + 1]; vec[2] = a[i + 2]; fn(vec, vec, arg); a[i] = vec[0]; a[i + 1] = vec[1]; a[i + 2] = vec[2]; } return a; }; }(); // ../../node_modules/@math.gl/core/dist/classes/vector4.js var ZERO; var Vector4 = class extends Vector { static get ZERO() { if (!ZERO) { ZERO = new Vector4(0, 0, 0, 0); Object.freeze(ZERO); } return ZERO; } constructor(x = 0, y = 0, z = 0, w = 0) { super(-0, -0, -0, -0); if (isArray(x) && arguments.length === 1) { this.copy(x); } else { if (config.debug) { checkNumber(x); checkNumber(y); checkNumber(z); checkNumber(w); } this[0] = x; this[1] = y; this[2] = z; this[3] = w; } } set(x, y, z, w) { this[0] = x; this[1] = y; this[2] = z; this[3] = w; return this.check(); } copy(array) { this[0] = array[0]; this[1] = array[1]; this[2] = array[2]; this[3] = array[3]; return this.check(); } fromObject(object) { if (config.debug) { checkNumber(object.x); checkNumber(object.y); checkNumber(object.z); checkNumber(object.w); } this[0] = object.x; this[1] = object.y; this[2] = object.z; this[3] = object.w; return this; } toObject(object) { object.x = this[0]; object.y = this[1]; object.z = this[2]; object.w = this[3]; return object; } // Getters/setters /* eslint-disable no-multi-spaces, brace-style, no-return-assign */ get ELEMENTS() { return 4; } get z() { return this[2]; } set z(value) { this[2] = checkNumber(value); } get w() { return this[3]; } set w(value) { this[3] = checkNumber(value); } transform(matrix4) { transformMat42(this, this, matrix4); return this.check(); } transformByMatrix3(matrix3) { vec4_transformMat3(this, this, matrix3); return this.check(); } transformByMatrix2(matrix2) { vec4_transformMat2(this, this, matrix2); return this.check(); } transformByQuaternion(quaternion2) { transformQuat(this, this, quaternion2); return this.check(); } // three.js compatibility applyMatrix4(m) { m.transform(this, this); return this; } }; // ../../node_modules/@math.gl/core/dist/classes/base/matrix.js var Matrix = class extends MathArray { // fromObject(object) { // const array = object.elements; // return this.fromRowMajor(array); // } // toObject(object) { // const array = object.elements; // this.toRowMajor(array); // return object; // } // TODO better override formatString? toString() { let string = "["; if (config.printRowMajor) { string += "row-major:"; for (let row = 0; row < this.RANK; ++row) { for (let col = 0; col < this.RANK; ++col) { string += ` ${this[col * this.RANK + row]}`; } } } else { string += "column-major:"; for (let i = 0; i < this.ELEMENTS; ++i) { string += ` ${this[i]}`; } } string += "]"; return string; } getElementIndex(row, col) { return col * this.RANK + row; } // By default assumes row major indices getElement(row, col) { return this[col * this.RANK + row]; } // By default assumes row major indices setElement(row, col, value) { this[col * this.RANK + row] = checkNumber(value); return this; } getColumn(columnIndex, result = new Array(this.RANK).fill(-0)) { const firstIndex = columnIndex * this.RANK; for (let i = 0; i < this.RANK; ++i) { result[i] = this[firstIndex + i]; } return result; } setColumn(columnIndex, columnVector) { const firstIndex = columnIndex * this.RANK; for (let i = 0; i < this.RANK; ++i) { this[firstIndex + i] = columnVector[i]; } return this; } }; // ../../node_modules/@math.gl/core/dist/gl-matrix/mat3.js function create3() { const out = new ARRAY_TYPE(9); if (ARRAY_TYPE != Float32Array) { out[1] = 0; out[2] = 0; out[3] = 0; out[5] = 0; out[6] = 0; out[7] = 0; } out[0] = 1; out[4] = 1; out[8] = 1; return out; } // ../../node_modules/@math.gl/core/dist/gl-matrix/mat4.js function identity(out) { out[0] = 1; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = 1; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 1; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; } function transpose(out, a) { if (out === a) { const a01 = a[1]; const a02 = a[2]; const a03 = a[3]; const a12 = a[6]; const a13 = a[7]; const a23 = a[11]; out[1] = a[4]; out[2] = a[8]; out[3] = a[12]; out[4] = a01; out[6] = a[9]; out[7] = a[13]; out[8] = a02; out[9] = a12; out[11] = a[14]; out[12] = a03; out[13] = a13; out[14] = a23; } else { out[0] = a[0]; out[1] = a[4]; out[2] = a[8]; out[3] = a[12]; out[4] = a[1]; out[5] = a[5]; out[6] = a[9]; out[7] = a[13]; out[8] = a[2]; out[9] = a[6]; out[10] = a[10]; out[11] = a[14]; out[12] = a[3]; out[13] = a[7]; out[14] = a[11]; out[15] = a[15]; } return out; } function invert(out, a) { const a00 = a[0]; const a01 = a[1]; const a02 = a[2]; const a03 = a[3]; const a10 = a[4]; const a11 = a[5]; const a12 = a[6]; const a13 = a[7]; const a20 = a[8]; const a21 = a[9]; const a22 = a[10]; const a23 = a[11]; const a30 = a[12]; const a31 = a[13]; const a32 = a[14]; const a33 = a[15]; const b00 = a00 * a11 - a01 * a10; const b01 = a00 * a12 - a02 * a10; const b02 = a00 * a13 - a03 * a10; const b03 = a01 * a12 - a02 * a11; const b04 = a01 * a13 - a03 * a11; const b05 = a02 * a13 - a03 * a12; const b06 = a20 * a31 - a21 * a30; const b07 = a20 * a32 - a22 * a30; const b08 = a20 * a33 - a23 * a30; const b09 = a21 * a32 - a22 * a31; const b10 = a21 * a33 - a23 * a31; const b11 = a22 * a33 - a23 * a32; let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; if (!det) { return null; } det = 1 / det; out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; return out; } function determinant(a) { const a00 = a[0]; const a01 = a[1]; const a02 = a[2]; const a03 = a[3]; const a10 = a[4]; const a11 = a[5]; const a12 = a[6]; const a13 = a[7]; const a20 = a[8]; const a21 = a[9]; const a22 = a[10]; const a23 = a[11]; const a30 = a[12]; const a31 = a[13]; const a32 = a[14]; const a33 = a[15]; const b0 = a00 * a11 - a01 * a10; const b1 = a00 * a12 - a02 * a10; const b2 = a01 * a12 - a02 * a11; const b3 = a20 * a31 - a21 * a30; const b4 = a20 * a32 - a22 * a30; const b5 = a21 * a32 - a22 * a31; const b6 = a00 * b5 - a01 * b4 + a02 * b3; const b7 = a10 * b5 - a11 * b4 + a12 * b3; const b8 = a20 * b2 - a21 * b1 + a22 * b0; const b9 = a30 * b2 - a31 * b1 + a32 * b0; return a13 * b6 - a03 * b7 + a33 * b8 - a23 * b9; } function multiply(out, a, b) { const a00 = a[0]; const a01 = a[1]; const a02 = a[2]; const a03 = a[3]; const a10 = a[4]; const a11 = a[5]; const a12 = a[6]; const a13 = a[7]; const a20 = a[8]; const a21 = a[9]; const a22 = a[10]; const a23 = a[11]; const a30 = a[12]; const a31 = a[13]; const a32 = a[14]; const a33 = a[15]; let b0 = b[0]; let b1 = b[1]; let b2 = b[2]; let b3 = b[3]; out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7]; out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11]; out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15]; out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30; out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31; out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32; out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33; return out; } function translate(out, a, v) { const x = v[0]; const y = v[1]; const z = v[2]; let a00; let a01; let a02; let a03; let a10; let a11; let a12; let a13; let a20; let a21; let a22; let a23; if (a === out) { out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; } else { a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; out[12] = a00 * x + a10 * y + a20 * z + a[12]; out[13] = a01 * x + a11 * y + a21 * z + a[13]; out[14] = a02 * x + a12 * y + a22 * z + a[14]; out[15] = a03 * x + a13 * y + a23 * z + a[15]; } return out; } function scale(out, a, v) { const x = v[0]; const y = v[1]; const z = v[2]; out[0] = a[0] * x; out[1] = a[1] * x; out[2] = a[2] * x; out[3] = a[3] * x; out[4] = a[4] * y; out[5] = a[5] * y; out[6] = a[6] * y; out[7] = a[7] * y; out[8] = a[8] * z; out[9] = a[9] * z; out[10] = a[10] * z; out[11] = a[11] * z; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; return out; } function rotate(out, a, rad, axis) { let x = axis[0]; let y = axis[1]; let z = axis[2]; let len2 = Math.sqrt(x * x + y * y + z * z); let c; let s; let t; let a00; let a01; let a02; let a03; let a10; let a11; let a12; let a13; let a20; let a21; let a22; let a23; let b00; let b01; let b02; let b10; let b11; let b12; let b20; let b21; let b22; if (len2 < EPSILON) { return null; } len2 = 1 / len2; x *= len2; y *= len2; z *= len2; s = Math.sin(rad); c = Math.cos(rad); t = 1 - c; a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; out[0] = a00 * b00 + a10 * b01 + a20 * b02; out[1] = a01 * b00 + a11 * b01 + a21 * b02; out[2] = a02 * b00 + a12 * b01 + a22 * b02; out[3] = a03 * b00 + a13 * b01 + a23 * b02; out[4] = a00 * b10 + a10 * b11 + a20 * b12; out[5] = a01 * b10 + a11 * b11 + a21 * b12; out[6] = a02 * b10 + a12 * b11 + a22 * b12; out[7] = a03 * b10 + a13 * b11 + a23 * b12; out[8] = a00 * b20 + a10 * b21 + a20 * b22; out[9] = a01 * b20 + a11 * b21 + a21 * b22; out[10] = a02 * b20 + a12 * b21 + a22 * b22; out[11] = a03 * b20 + a13 * b21 + a23 * b22; if (a !== out) { out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } return out; } function rotateX(out, a, rad) { const s = Math.sin(rad); const c = Math.cos(rad); const a10 = a[4]; const a11 = a[5]; const a12 = a[6]; const a13 = a[7]; const a20 = a[8]; const a21 = a[9]; const a22 = a[10]; const a23 = a[11]; if (a !== out) { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = a[3]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } out[4] = a10 * c + a20 * s; out[5] = a11 * c + a21 * s; out[6] = a12 * c + a22 * s; out[7] = a13 * c + a23 * s; out[8] = a20 * c - a10 * s; out[9] = a21 * c - a11 * s; out[10] = a22 * c - a12 * s; out[11] = a23 * c - a13 * s; return out; } function rotateY(out, a, rad) { const s = Math.sin(rad); const c = Math.cos(rad); const a00 = a[0]; const a01 = a[1]; const a02 = a[2]; const a03 = a[3]; const a20 = a[8]; const a21 = a[9]; const a22 = a[10]; const a23 = a[11]; if (a !== out) { out[4] = a[4]; out[5] = a[5]; out[6] = a[6]; out[7] = a[7]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } out[0] = a00 * c - a20 * s; out[1] = a01 * c - a21 * s; out[2] = a02 * c - a22 * s; out[3] = a03 * c - a23 * s; out[8] = a00 * s + a20 * c; out[9] = a01 * s + a21 * c; out[10] = a02 * s + a22 * c; out[11] = a03 * s + a23 * c; return out; } function rotateZ(out, a, rad) { const s = Math.sin(rad); const c = Math.cos(rad); const a00 = a[0]; const a01 = a[1]; const a02 = a[2]; const a03 = a[3]; const a10 = a[4]; const a11 = a[5]; const a12 = a[6]; const a13 = a[7]; if (a !== out) { out[8] = a[8]; out[9] = a[9]; out[10] = a[10]; out[11] = a[11]; out[12] = a[12]; out[13] = a[13]; out[14] = a[14]; out[15] = a[15]; } out[0] = a00 * c + a10 * s; out[1] = a01 * c + a11 * s; out[2] = a02 * c + a12 * s; out[3] = a03 * c + a13 * s; out[4] = a10 * c - a00 * s; out[5] = a11 * c - a01 * s; out[6] = a12 * c - a02 * s; out[7] = a13 * c - a03 * s; return out; } function fromQuat(out, q) { const x = q[0]; const y = q[1]; const z = q[2]; const w = q[3]; const x2 = x + x; const y2 = y + y; const z2 = z + z; const xx = x * x2; const yx = y * x2; const yy = y * y2; const zx = z * x2; const zy = z * y2; const zz = z * z2; const wx = w * x2; const wy = w * y2; const wz = w * z2; out[0] = 1 - yy - zz; out[1] = yx + wz; out[2] = zx - wy; out[3] = 0; out[4] = yx - wz; out[5] = 1 - xx - zz; out[6] = zy + wx; out[7] = 0; out[8] = zx + wy; out[9] = zy - wx; out[10] = 1 - xx - yy; out[11] = 0; out[12] = 0; out[13] = 0; out[14] = 0; out[15] = 1; return out; } function frustum(out, left, right, bottom, top, near, far) { const rl = 1 / (right - left); const tb = 1 / (top - bottom); const nf = 1 / (near - far); out[0] = near * 2 * rl; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = near * 2 * tb; out[6] = 0; out[7] = 0; out[8] = (right + left) * rl; out[9] = (top + bottom) * tb; out[10] = (far + near) * nf; out[11] = -1; out[12] = 0; out[13] = 0; out[14] = far * near * 2 * nf; out[15] = 0; return out; } function perspectiveNO(out, fovy, aspect, near, far) { const f = 1 / Math.tan(fovy / 2); out[0] = f / aspect; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = f; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[11] = -1; out[12] = 0; out[13] = 0; out[15] = 0; if (far != null && far !== Infinity) { const nf = 1 / (near - far); out[10] = (far + near) * nf; out[14] = 2 * far * near * nf; } else { out[10] = -1; out[14] = -2 * near; } return out; } var perspective = perspectiveNO; function orthoNO(out, left, right, bottom, top, near, far) { const lr = 1 / (left - right); const bt = 1 / (bottom - top); const nf = 1 / (near - far); out[0] = -2 * lr; out[1] = 0; out[2] = 0; out[3] = 0; out[4] = 0; out[5] = -2 * bt; out[6] = 0; out[7] = 0; out[8] = 0; out[9] = 0; out[10] = 2 * nf; out[11] = 0; out[12] = (left + right) * lr; out[13] = (top + bottom) * bt; out[14] = (far + near) * nf; out[15] = 1; return out; } var ortho = orthoNO; function lookAt(out, eye, center, up) { let len2; let x0; let x1; let x2; let y0; let y1; let y2; let z0; let z1; let z2; const eyex = eye[0]; const eyey = eye[1]; const eyez = eye[2]; const upx = up[0]; const upy = up[1]; const upz = up[2]; const centerx = center[0]; const centery = center[1]; const centerz = center[2]; if (Math.abs(eyex - centerx) < EPSILON && Math.abs(eyey - centery) < EPSILON && Math.abs(eyez - centerz) < EPSILON) { return identity(out); } z0 = eyex - centerx; z1 = eyey - centery; z2 = eyez - centerz; len2 = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); z0 *= len2; z1 *= len2; z2 *= len2; x0 = upy * z2 - upz * z1; x1 = upz * z0 - upx * z2; x2 = upx * z1 - upy * z0; len2 = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); if (!len2) { x0 = 0; x1 = 0; x2 = 0; } else { len2 = 1 / len2; x0 *= len2; x1 *= len2; x2 *= len2; } y0 = z1 * x2 - z2 * x1; y1 = z2 * x0 - z0 * x2; y2 = z0 * x1 - z1 * x0; len2 = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); if (!len2) { y0 = 0; y1 = 0; y2 = 0; } else { len2 = 1 / len2; y0 *= len2; y1 *= len2; y2 *= len2; } out[0] = x0; out[1] = y0; out[2] = z0; out[3] = 0; out[4] = x1; out[5] = y1; out[6] = z1; out[7] = 0; out[8] = x2; out[9] = y2; out[10] = z2; out[11] = 0; out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); out[15] = 1; return out; } // ../../node_modules/@math.gl/core/dist/gl-matrix/vec4.js function create4() { const out = new ARRAY_TYPE(4); if (ARRAY_TYPE != Float32Array) { out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 0; } return out; } function add(out, a, b) { out[0] = a[0] + b[0]; out[1] = a[1] + b[1]; out[2] = a[2] + b[2]; out[3] = a[3] + b[3]; return out; } function scale2(out, a, b) { out[0] = a[0] * b; out[1] = a[1] * b; out[2] = a[2] * b; out[3] = a[3] * b; return out; } function length2(a) { const x = a[0]; const y = a[1]; const z = a[2]; const w = a[3]; return Math.sqrt(x * x + y * y + z * z + w * w); } function squaredLength(a) { const x = a[0]; const y = a[1]; const z = a[2]; const w = a[3]; return x * x + y * y + z * z + w * w; } function normalize2(out, a) { const x = a[0]; const y = a[1]; const z = a[2]; const w = a[3]; let len2 = x * x + y * y + z * z + w * w; if (len2 > 0) { len2 = 1 / Math.sqrt(len2); } out[0] = x * len2; out[1] = y * len2; out[2] = z * len2; out[3] = w * len2; return out; } function dot2(a, b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; } function lerp(out, a, b, t) { const ax = a[0]; const ay = a[1]; const az = a[2]; const aw = a[3]; out[0] = ax + t * (b[0] - ax); out[1] = ay + t * (b[1] - ay); out[2] = az + t * (b[2] - az); out[3] = aw + t * (b[3] - aw); return out; } function transformMat43(out, a, m) { const x = a[0]; const y = a[1]; const z = a[2]; const w = a[3]; out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w; out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w; out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w; out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w; return out; } function transformQuat2(out, a, q) { const x = a[0]; const y = a[1]; const z = a[2]; const qx = q[0]; const qy = q[1]; const qz = q[2]; const qw = q[3]; const ix = qw * x + qy * z - qz * y; const iy = qw * y + qz * x - qx * z; const iz = qw * z + qx * y - qy * x; const iw = -qx * x - qy * y - qz * z; out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy; out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz; out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx; out[3] = a[3]; return out; } var forEach3 = function() { const vec = create4(); return function(a, stride, offset, count, fn, arg) { let i; let l; if (!stride) { stride = 4; } if (!offset) { offset = 0; } if (count) { l = Math.min(count * stride + offset, a.length); } else { l = a.length; } for (i = offset; i < l; i += stride) { vec[0] = a[i]; vec[1] = a[i + 1]; vec[2] = a[i + 2]; vec[3] = a[i + 3]; fn(vec, vec, arg); a[i] = vec[0]; a[i + 1] = vec[1]; a[i + 2] = vec[2]; a[i + 3] = vec[3]; } return a; }; }(); // ../../node_modules/@math.gl/core/dist/classes/matrix4.js var INDICES; (function(INDICES2) { INDICES2[INDICES2["COL0ROW0"] = 0] = "COL0ROW0"; INDICES2[INDICES2["COL0ROW1"] = 1] = "COL0ROW1"; INDICES2[INDICES2["COL0ROW2"] = 2] = "COL0ROW2"; INDICES2[INDICES2["COL0ROW3"] = 3] = "COL0ROW3"; INDICES2[INDICES2["COL1ROW0"] = 4] = "COL1ROW0"; INDICES2[INDICES2["COL1ROW1"] = 5] = "COL1ROW1"; INDICES2[INDICES2["COL1ROW2"] = 6] = "COL1ROW2"; INDICES2[INDICES2["COL1ROW3"] = 7] = "COL1ROW3"; INDICES2[INDICES2["COL2ROW0"] = 8] = "COL2ROW0"; INDICES2[INDICES2["COL2ROW1"] = 9] = "COL2ROW1"; INDICES2[INDICES2["COL2ROW2"] = 10] = "COL2ROW2"; INDICES2[INDICES2["COL2ROW3"] = 11] = "COL2ROW3"; INDICES2[INDICES2["COL3ROW0"] = 12] = "COL3ROW0"; INDICES2[INDICES2["COL3ROW1"] = 13] = "COL3ROW1"; INDICES2[INDICES2["COL3ROW2"] = 14] = "COL3ROW2"; INDICES2[INDICES2["COL3ROW3"] = 15] = "COL3ROW3"; })(INDICES || (INDICES = {})); var DEFAULT_FOVY = 45 * Math.PI / 180; var DEFAULT_ASPECT = 1; var DEFAULT_NEAR = 0.1; var DEFAULT_FAR = 500; var IDENTITY_MATRIX = Object.freeze([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]); var Matrix4 = class extends Matrix { static get IDENTITY() { return getIdentityMatrix(); } static get ZERO() { return getZeroMatrix(); } get ELEMENTS() { return 16; } get RANK() { return 4; } get INDICES() { return INDICES; } constructor(array) { super(-0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0); if (arguments.length === 1 && Array.isArray(array)) { this.copy(array); } else { this.identity(); } } copy(array) { this[0] = array[0]; this[1] = array[1]; this[2] = array[2]; this[3] = array[3]; this[4] = array[4]; this[5] = array[5]; this[6] = array[6]; this[7] = array[7]; this[8] = array[8]; this[9] = array[9]; this[10] = array[10]; this[11] = array[11]; this[12] = array[12]; this[13] = array[13]; this[14] = array[14]; this[15] = array[15]; return this.check(); } // eslint-disable-next-line max-params set(m00, m10, m20, m30, m01, m11, m21, m31, m02, m12, m22, m32, m03, m13, m23, m33) { this[0] = m00; this[1] = m10; this[2] = m20; this[3] = m30; this[4] = m01; this[5] = m11; this[6] = m21; this[7] = m31; this[8] = m02; this[9] = m12; this[10] = m22; this[11] = m32; this[12] = m03; this[13] = m13; this[14] = m23; this[15] = m33; return this.check(); } // accepts row major order, stores as column major // eslint-disable-next-line max-params setRowMajor(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) { this[0] = m00; this[1] = m10; this[2] = m20; this[3] = m30; this[4] = m01; this[5] = m11; this[6] = m21; this[7] = m31; this[8] = m02; this[9] = m12; this[10] = m22; this[11] = m32; this[12] = m03; this[13] = m13; this[14] = m23; this[15] = m33; return this.check(); } toRowMajor(result) { result[0] = this[0]; result[1] = this[4]; result[2] = this[8]; result[3] = this[12]; result[4] = this[1]; result[5] = this[5]; result[6] = this[9]; result[7] = this[13]; result[8] = this[2]; result[9] = this[6]; result[10] = this[10]; result[11] = this[14]; result[12] = this[3]; result[13] = this[7]; result[14] = this[11]; result[15] = this[15]; return result; } // Constructors /** Set to identity matrix */ identity() { return this.copy(IDENTITY_MATRIX); } /** * * @param object * @returns self */ // eslint-disable-next-line @typescript-eslint/no-unused-vars fromObject(object) { return this.check(); } /** * Calculates a 4x4 matrix from the given quaternion * @param quaternion Quaternion to create matrix from * @returns self */ fromQuaternion(quaternion2) { fromQuat(this, quaternion2); return this.check(); } /** * Generates a frustum matrix with the given bounds * @param view.left - Left bound of the frustum * @param view.right - Right bound of the frustum * @param view.bottom - Bottom bound of the frustum * @param view.top - Top bound of the frustum * @param view.near - Near bound of the frustum * @param view.far - Far bound of the frustum. Can be set to Infinity. * @returns self */ frustum(view) { const { left, right, bottom, top, near = DEFAULT_NEAR, far = DEFAULT_FAR } = view; if (far === Infinity) { computeInfinitePerspectiveOffCenter(this, left, right, bottom, top, near); } else { frustum(this, left, right, bottom, top, near, far); } return this.check(); } /** * Generates a look-at matrix with the given eye position, focal point, * and up axis * @param view.eye - (vector) Position of the viewer * @param view.center - (vector) Point the viewer is looking at * @param view.up - (vector) Up axis * @returns self */ lookAt(view) { const { eye, center = [0, 0, 0], up = [0, 1, 0] } = view; lookAt(this, eye, center, up); return this.check(); } /** * Generates a orthogonal projection matrix with the given bounds * from "traditional" view space parameters * @param view.left - Left bound of the frustum * @param view.right number Right bound of the frustum * @param view.bottom - Bottom bound of the frustum * @param view.top number Top bound of the frustum * @param view.near - Near bound of the frustum * @param view.far number Far bound of the frustum * @returns self */ ortho(view) { const { left, right, bottom, top, near = DEFAULT_NEAR, far = DEFAULT_FAR } = view; ortho(this, left, right, bottom, top, near, far); return this.check(); } /** * Generates an orthogonal projection matrix with the same parameters * as a perspective matrix (plus focalDistance) * @param view.fovy Vertical field of view in radians * @param view.aspect Aspect ratio. Typically viewport width / viewport height * @param view.focalDistance Distance in the view frustum used for extent calculations * @param view.near Near bound of the frustum * @param view.far Far bound of the frustum * @returns self */ orthographic(view) { const { fovy = DEFAULT_FOVY, aspect = DEFAULT_ASPECT, focalDistance = 1, near = DEFAULT_NEAR, far = DEFAULT_FAR } = view; checkRadians(fovy); const halfY = fovy / 2; const top = focalDistance * Math.tan(halfY); const right = top * aspect; return this.ortho({ left: -right, right, bottom: -top, top, near, far }); } /** * Generates a perspective projection matrix with the given bounds * @param view.fovy Vertical field of view in radians * @param view.aspect Aspect ratio. typically viewport width/height * @param view.near Near bound of the frustum * @param view.far Far bound of the frustum * @returns self */ perspective(view) { const { fovy = 45 * Math.PI / 180, aspect = 1, near = 0.1, far = 500 } = view; checkRadians(fovy); perspective(this, fovy, aspect, near, far); return this.check(); } // Accessors determinant() { return determinant(this); } /** * Extracts the non-uniform scale assuming the matrix is an affine transformation. * The scales are the "lengths" of the column vectors in the upper-left 3x3 matrix. * @param result * @returns self */ getScale(result = [-0, -0, -0]) { result[0] = Math.sqrt(this[0] * this[0] + this[1] * this[1] + this[2] * this[2]); result[1] = Math.sqrt(this[4] * this[4] + this[5] * this[5] + this[6] * this[6]); result[2] = Math.sqrt(this[8] * this[8] + this[9] * this[9] + this[10] * this[10]); return result; } /** * Gets the translation portion, assuming the matrix is a affine transformation matrix. * @param result * @returns self */ getTranslation(result = [-0, -0, -0]) { result[0] = this[12]; result[1] = this[13]; result[2] = this[14]; return result; } /** * Gets upper left 3x3 pure rotation matrix (non-scaling), assume affine transformation matrix * @param result * @param scaleResult * @returns self */ getRotation(result, scaleResult) { result = result || [-0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0, -0]; scaleResult = scaleResult || [-0, -0, -0]; const scale4 = this.getScale(scaleResult); const inverseScale0 = 1 / scale4[0]; const inverseScale1 = 1 / scale4[1]; const inverseScale2 = 1 / scale4[2]; result[0] = this[0] * inverseScale0; result[1] = this[1] * inverseScale1; result[2] = this[2] * inverseScale2; result[3] = 0; result[4] = this[4] * inverseScale0; result[5] = this[5] * inverseScale1; result[6] = this[6] * inverseScale2; result[7] = 0; result[8] = this[8] * inverseScale0; result[9] = this[9] * inverseScale1; result[10] = this[10] * inverseScale2; result[11] = 0; result[12] = 0; result[13] = 0; result[14] = 0; result[15] = 1; return result; } /** * * @param result * @param scaleResult * @returns self */ getRotationMatrix3(result, scaleResult) { result = result || [-0, -0, -0, -0, -0, -0, -0, -0, -0]; scaleResult = scaleResult || [-0, -0, -0]; const scale4 = this.getScale(scaleResult); const inverseScale0 = 1 / scale4[0]; const inverseScale1 = 1 / scale4[1]; const inverseScale2 = 1 / scale4[2]; result[0] = this[0] * inverseScale0; result[1] = this[1] * inverseScale1; result[2] = this[2] * inverseScale2; result[3] = this[4] * inverseScale0; result[4] = this[5] * inverseScale1; result[5] = this[6] * inverseScale2; result[6] = this[8] * inverseScale0; result[7] = this[9] * inverseScale1; result[8] = this[10] * inverseScale2; return result; } // Modifiers transpose() { transpose(this, this); return this.check(); } invert() { invert(this, this); return this.check(); } // Operations multiplyLeft(a) { multiply(this, a, this); return this.check(); } multiplyRight(a) { multiply(this, this, a); return this.check(); } // Rotates a matrix by the given angle around the X axis rotateX(radians) { rotateX(this, this, radians); return this.check(); } // Rotates a matrix by the given angle around the Y axis. rotateY(radians) { rotateY(this, this, radians); return this.check(); } /** * Rotates a matrix by the given angle around the Z axis. * @param radians * @returns self */ rotateZ(radians) { rotateZ(this, this, radians); return this.check(); } /** * * @param param0 * @returns self */ rotateXYZ(angleXYZ) { return this.rotateX(angleXYZ[0]).rotateY(angleXYZ[1]).rotateZ(angleXYZ[2]); } /** * * @param radians * @param axis * @returns self */ rotateAxis(radians, axis) { rotate(this, this, radians, axis); return this.check(); } /** * * @param factor * @returns self */ scale(factor) { scale(this, this, Array.isArray(factor) ? factor : [factor, factor, factor]); return this.check(); } /** * * @param vec * @returns self */ translate(vector) { translate(this, this, vector); return this.check(); } // Transforms /** * Transforms any 2, 3 or 4 element vector. 2 and 3 elements are treated as points * @param vector * @param result * @returns self */ transform(vector, result) { if (vector.length === 4) { result = transformMat43(result || [-0, -0, -0, -0], vector, this); checkVector(result, 4); return result; } return this.transformAsPoint(vector, result); } /** * Transforms any 2 or 3 element array as point (w implicitly 1) * @param vector * @param result * @returns self */ transformAsPoint(vector, result) { const { length: length4 } = vector; let out; switch (length4) { case 2: out = transformMat4(result || [-0, -0], vector, this); break; case 3: out = transformMat42(result || [-0, -0, -0], vector, this); break; default: throw new Error("Illegal vector"); } checkVector(out, vector.length); return out; } /** * Transforms any 2 or 3 element array as vector (w implicitly 0) * @param vector * @param result * @returns self */ transformAsVector(vector, result) { let out; switch (vector.length) { case 2: out = vec2_transformMat4AsVector(result || [-0, -0], vector, this); break; case 3: out = vec3_transformMat4AsVector(result || [-0, -0, -0], vector, this); break; default: throw new Error("Illegal vector"); } checkVector(out, vector.length); return out; } /** @deprecated */ transformPoint(vector, result) { return this.transformAsPoint(vector, result); } /** @deprecated */ transformVector(vector, result) { return this.transformAsPoint(vector, result); } /** @deprecated */ transformDirection(vector, result) { return this.transformAsVector(vector, result); } // three.js math API compatibility makeRotationX(radians) { return this.identity().rotateX(radians); } makeTranslation(x, y, z) { return this.identity().translate([x, y, z]); } }; var ZERO2; var IDENTITY; function getZeroMatrix() { if (!ZERO2) { ZERO2 = new Matrix4([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); Object.freeze(ZERO2); } return ZERO2; } function getIdentityMatrix() { if (!IDENTITY) { IDENTITY = new Matrix4(); Object.freeze(IDENTITY); } return IDENTITY; } function checkRadians(possiblyDegrees) { if (possiblyDegrees > Math.PI * 2) { throw Error("expected radians"); } } function computeInfinitePerspectiveOffCenter(result, left, right, bottom, top, near) { const column0Row0 = 2 * near / (right - left); const column1Row1 = 2 * near / (top - bottom); const column2Row0 = (right + left) / (right - left); const column2Row1 = (top + bottom) / (top - bottom); const column2Row2 = -1; const column2Row3 = -1; const column3Row2 = -2 * near; result[0] = column0Row0; result[1] = 0; result[2] = 0; result[3] = 0; result[4] = 0; result[5] = column1Row1; result[6] = 0; result[7] = 0; result[8] = column2Row0; result[9] = column2Row1; result[10] = column2Row2; result[11] = column2Row3; result[12] = 0; result[13] = 0; result[14] = column3Row2; result[15] = 0; return result; } // ../../node_modules/@math.gl/core/dist/gl-matrix/quat.js function create5() { const out = new ARRAY_TYPE(4); if (ARRAY_TYPE != Float32Array) { out[0] = 0; out[1] = 0; out[2] = 0; } out[3] = 1; return out; } function identity2(out) { out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1; return out; } function setAxisAngle(out, axis, rad) { rad = rad * 0.5; const s = Math.sin(rad); out[0] = s * axis[0]; out[1] = s * axis[1]; out[2] = s * axis[2]; out[3] = Math.cos(rad); return out; } function multiply2(out, a, b) { const ax = a[0]; const ay = a[1]; const az = a[2]; const aw = a[3]; const bx = b[0]; const by = b[1]; const bz = b[2]; const bw = b[3]; out[0] = ax * bw + aw * bx + ay * bz - az * by; out[1] = ay * bw + aw * by + az * bx - ax * bz; out[2] = az * bw + aw * bz + ax * by - ay * bx; out[3] = aw * bw - ax * bx - ay * by - az * bz; return out; } function rotateX2(out, a, rad) { rad *= 0.5; const ax = a[0]; const ay = a[1]; const az = a[2]; const aw = a[3]; const bx = Math.sin(rad); const bw = Math.cos(rad); out[0] = ax * bw + aw * bx; out[1] = ay * bw + az * bx; out[2] = az * bw - ay * bx; out[3] = aw * bw - ax * bx; return out; } function rotateY2(out, a, rad) { rad *= 0.5; const ax = a[0]; const ay = a[1]; const az = a[2]; const aw = a[3]; const by = Math.sin(rad); const bw = Math.cos(rad); out[0] = ax * bw - az * by; out[1] = ay * bw + aw * by; out[2] = az * bw + ax * by; out[3] = aw * bw - ay * by; return out; } function rotateZ2(out, a, rad) { rad *= 0.5; const ax = a[0]; const ay = a[1]; const az = a[2]; const aw = a[3]; const bz = Math.sin(rad); const bw = Math.cos(rad); out[0] = ax * bw + ay * bz; out[1] = ay * bw - ax * bz; out[2] = az * bw + aw * bz; out[3] = aw * bw - az * bz; return out; } function calculateW(out, a) { const x = a[0]; const y = a[1]; const z = a[2]; out[0] = x; out[1] = y; out[2] = z; out[3] = Math.sqrt(Math.abs(1 - x * x - y * y - z * z)); return out; } function slerp(out, a, b, t) { const ax = a[0]; const ay = a[1]; const az = a[2]; const aw = a[3]; let bx = b[0]; let by = b[1]; let bz = b[2]; let bw = b[3]; let cosom; let omega; let scale0; let scale1; let sinom; cosom = ax * bx + ay * by + az * bz + aw * bw; if (cosom < 0) { cosom = -cosom; bx = -bx; by = -by; bz = -bz; bw = -bw; } if (1 - cosom > EPSILON) { omega = Math.acos(cosom); sinom = Math.sin(omega); scale0 = Math.sin((1 - t) * omega) / sinom; scale1 = Math.sin(t * omega) / sinom; } else { scale0 = 1 - t; scale1 = t; } out[0] = scale0 * ax + scale1 * bx; out[1] = scale0 * ay + scale1 * by; out[2] = scale0 * az + scale1 * bz; out[3] = scale0 * aw + scale1 * bw; return out; } function invert2(out, a) { const a0 = a[0]; const a1 = a[1]; const a2 = a[2]; const a3 = a[3]; const dot4 = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3; const invDot = dot4 ? 1 / dot4 : 0; out[0] = -a0 * invDot; out[1] = -a1 * invDot; out[2] = -a2 * invDot; out[3] = a3 * invDot; return out; } function conjugate(out, a) { out[0] = -a[0]; out[1] = -a[1]; out[2] = -a[2]; out[3] = a[3]; return out; } function fromMat3(out, m) { const fTrace = m[0] + m[4] + m[8]; let fRoot; if (fTrace > 0) { fRoot = Math.sqrt(fTrace + 1); out[3] = 0.5 * fRoot; fRoot = 0.5 / fRoot; out[0] = (m[5] - m[7]) * fRoot; out[1] = (m[6] - m[2]) * fRoot; out[2] = (m[1] - m[3]) * fRoot; } else { let i = 0; if (m[4] > m[0]) i = 1; if (m[8] > m[i * 3 + i]) i = 2; const j = (i + 1) % 3; const k = (i + 2) % 3; fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1); out[i] = 0.5 * fRoot; fRoot = 0.5 / fRoot; out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot; out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot; out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot; } return out; } var add2 = add; var scale3 = scale2; var dot3 = dot2; var lerp2 = lerp; var length3 = length2; var squaredLength2 = squaredLength; var normalize3 = normalize2; var rotationTo = function() { const tmpvec3 = create2(); const xUnitVec3 = fromValues(1, 0, 0); const yUnitVec3 = fromValues(0, 1, 0); return function(out, a, b) { const dot4 = dot(a, b); if (dot4 < -0.999999) { cross(tmpvec3, xUnitVec3, a); if (len(tmpvec3) < 1e-6) cross(tmpvec3, yUnitVec3, a); normalize(tmpvec3, tmpvec3); setAxisAngle(out, tmpvec3, Math.PI); return out; } else if (dot4 > 0.999999) { out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 1; return out; } cross(tmpvec3, a, b); out[0] = tmpvec3[0]; out[1] = tmpvec3[1]; out[2] = tmpvec3[2]; out[3] = 1 + dot4; return normalize3(out, out); }; }(); var sqlerp = function() { const temp1 = create5(); const temp2 = create5(); return function(out, a, b, c, d, t) { slerp(temp1, a, d, t); slerp(temp2, b, c, t); slerp(out, temp1, temp2, 2 * t * (1 - t)); return out; }; }(); var setAxes = function() { const matr = create3(); return function(out, view, right, up) { matr[0] = right[0]; matr[3] = right[1]; matr[6] = right[2]; matr[1] = up[0]; matr[4] = up[1]; matr[7] = up[2]; matr[2] = -view[0]; matr[5] = -view[1]; matr[8] = -view[2]; return normalize3(out, fromMat3(out, matr)); }; }(); // ../../node_modules/@math.gl/core/dist/classes/quaternion.js var IDENTITY_QUATERNION = [0, 0, 0, 1]; var Quaternion = class extends MathArray { constructor(x = 0, y = 0, z = 0, w = 1) { super(-0, -0, -0, -0); if (Array.isArray(x) && arguments.length === 1) { this.copy(x); } else { this.set(x, y, z, w); } } copy(array) { this[0] = array[0]; this[1] = array[1]; this[2] = array[2]; this[3] = array[3]; return this.check(); } set(x, y, z, w) { this[0] = x; this[1] = y; this[2] = z; this[3] = w; return this.check(); } fromObject(object) { this[0] = object.x; this[1] = object.y; this[2] = object.z; this[3] = object.w; return this.check(); } /** * Creates a quaternion from the given 3x3 rotation matrix. * NOTE: The resultant quaternion is not normalized, so you should * be sure to renormalize the quaternion yourself where necessary. * @param m * @returns */ fromMatrix3(m) { fromMat3(this, m); return this.check(); } fromAxisRotation(axis, rad) { setAxisAngle(this, axis, rad); return this.check(); } /** Set a quat to the identity quaternion */ identity() { identity2(this); return this.check(); } // Set the components of a quat to the given values // set(i, j, k, l) { // quat_set(this, i, j, k, l); // return this.check(); // } // Sets a quat from the given angle and rotation axis, then returns it. setAxisAngle(axis, rad) { return this.fromAxisRotation(axis, rad); } // Getters/setters get ELEMENTS() { return 4; } get x() { return this[0]; } set x(value) { this[0] = checkNumber(value); } get y() { return this[1]; } set y(value) { this[1] = checkNumber(value); } get z() { return this[2]; } set z(value) { this[2] = checkNumber(value); } get w() { return this[3]; } set w(value) { this[3] = checkNumber(value); } // Calculates the length of a quat len() { return length3(this); } // Calculates the squared length of a quat lengthSquared() { return squaredLength2(this); } // Calculates the dot product of two quat's // @return {Number} dot(a) { return dot3(this, a); } // Gets the rotation axis and angle for a given quaternion. // If a quaternion is created with setAxisAngle, this method will // return the same values as providied in the original parameter // list OR functionally equivalent values. // Example: The quaternion formed by axis [0, 0, 1] and angle -90 // is the same as the quaternion formed by [0, 0, 1] and 270. // This method favors the latter. // @return {{[x,y,z], Number}} // getAxisAngle() { // const axis = []; // // const angle = quat_getAxisAngle(axis, this); // return {axis, angle}; // } // MODIFIERS // Sets a quaternion to represent the shortest rotation from one vector // to another. Both vectors are assumed to be unit length. rotationTo(vectorA, vectorB) { rotationTo(this, vectorA, vectorB); return this.check(); } // Sets the specified quaternion with values corresponding to the given axes. // Each axis is a vec3 and is expected to be unit length and perpendicular // to all other specified axes. // setAxes() { // Number // } // Performs a spherical linear interpolation with two control points // sqlerp() { // Number; // } // Adds two quat's add(a) { add2(this, this, a); return this.check(); } // Calculates the W component of a quat from the X, Y, and Z components. // Any existing W component will be ignored. calculateW() { calculateW(this, this); return this.check(); } // Calculates the conjugate of a quat If the quaternion is normalized, // this function is faster than quat_invert and produces the same result. conjugate() { conjugate(this, this); return this.check(); } // Calculates the inverse of a quat invert() { invert2(this, this); return this.check(); } // Performs a linear interpolation between two quat's lerp(a, b, t) { if (t === void 0) { return this.lerp(this, a, b); } lerp2(this, a, b, t); return this.check(); } // Multiplies two quat's multiplyRight(a) { multiply2(this, this, a); return this.check(); } multiplyLeft(a) { multiply2(this, a, this); return this.check(); } // Normalize a quat normalize() { const length4 = this.len(); const l = length4 > 0 ? 1 / length4 : 0; this[0] = this[0] * l; this[1] = this[1] * l; this[2] = this[2] * l; this[3] = this[3] * l; if (length4 === 0) { this[3] = 1; } return this.check(); } // Rotates a quaternion by the given angle about the X axis rotateX(rad) { rotateX2(this, this, rad); return this.check(); } // Rotates a quaternion by the given angle about the Y axis rotateY(rad) { rotateY2(this, this, rad); return this.check(); } // Rotates a quaternion by the given angle about the Z axis rotateZ(rad) { rotateZ2(this, this, rad); return this.check(); } // Scales a quat by a scalar number scale(b) { scale3(this, this, b); return this.check(); } // Performs a spherical linear interpolation between two quat slerp(arg0, arg1, arg2) { let start; let target; let ratio; switch (arguments.length) { case 1: ({ start = IDENTITY_QUATERNION, target, ratio } = arg0); break; case 2: start = this; target = arg0; ratio = arg1; break; default: start = arg0; target = arg1; ratio = arg2; } slerp(this, start, target, ratio); return this.check(); } transformVector4(vector, result = new Vector4()) { transformQuat2(result, vector, this); return checkVector(result, 4); } // THREE.js Math API compatibility lengthSq() { return this.lengthSquared(); } setFromAxisAngle(axis, rad) { return this.setAxisAngle(axis, rad); } premultiply(a) { return this.multiplyLeft(a); } multiply(a) { return this.multiplyRight(a); } }; // src/gltf/gltf-animator.ts var import_core2 = __toESM(require_core(), 1); var ATTRIBUTE_TYPE_TO_COMPONENTS = { SCALAR: 1, VEC2: 2, VEC3: 3, VEC4: 4, MAT2: 4, MAT3: 9, MAT4: 16 }; var ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY = { 5120: Int8Array, 5121: Uint8Array, 5122: Int16Array, 5123: Uint16Array, 5125: Uint32Array, 5126: Float32Array }; var GLTFAnimation = class { name; startTime = 0; playing = true; speed = 1; channels = []; constructor(props) { Object.assign(this, props); } animate(timeMs) { if (!this.playing) { return; } const absTime = timeMs / 1e3; const time = (absTime - this.startTime) * this.speed; this.channels.forEach(({ sampler, target, path }) => { interpolate(time, sampler, target, path); applyTranslationRotationScale(target, target._node); }); } }; var GLTFAnimator = class { animations; constructor(gltf) { this.animations = gltf.animations.map((animation, index) => { const name = animation.name || `Animation-${index}`; const samplers = animation.samplers.map(({ input, interpolation = "LINEAR", output }) => ({ input: accessorToJsArray(gltf.accessors[input]), interpolation, output: accessorToJsArray(gltf.accessors[output]) })); const channels = animation.channels.map(({ sampler, target }) => ({ sampler: samplers[sampler], target: gltf.nodes[target.node], path: target.path })); return new GLTFAnimation({ name, channels }); }); } /** @deprecated Use .setTime(). Will be removed (deck.gl is using this) */ animate(time) { this.setTime(time); } setTime(time) { this.animations.forEach((animation) => animation.animate(time)); } getAnimations() { return this.animations; } }; function accessorToJsArray(accessor) { if (!accessor._animation) { const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[accessor.componentType]; const components = ATTRIBUTE_TYPE_TO_COMPONENTS[accessor.type]; const length4 = components * accessor.count; const { buffer, byteOffset } = accessor.bufferView.data; const array = new ArrayType(buffer, byteOffset + (accessor.byteOffset || 0), length4); if (components === 1) { accessor._animation = Array.from(array); } else { const slicedArray = []; for (let i = 0; i < array.length; i += components) { slicedArray.push(Array.from(array.slice(i, i + components))); } accessor._animation = slicedArray; } } return accessor._animation; } var helperMatrix = new Matrix4(); function applyTranslationRotationScale(gltfNode, node) { node.matrix.identity(); if (gltfNode.translation) { node.matrix.translate(gltfNode.translation); } if (gltfNode.rotation) { const rotationMatrix = helperMatrix.fromQuaternion(gltfNode.rotation); node.matrix.multiplyRight(rotationMatrix); } if (gltfNode.scale) { node.matrix.scale(gltfNode.scale); } } var quaternion = new Quaternion(); function linearInterpolate(target, path, start, stop, ratio) { if (path === "rotation") { quaternion.slerp({ start, target: stop, ratio }); for (let i = 0; i < quaternion.length; i++) { target[path][i] = quaternion[i]; } } else { for (let i = 0; i < start.length; i++) { target[path][i] = ratio * stop[i] + (1 - ratio) * start[i]; } } } function cubicsplineInterpolate(target, path, { p0, outTangent0, inTangent1, p1, tDiff, ratio: t }) { for (let i = 0; i < target[path].length; i++) { const m0 = outTangent0[i] * tDiff; const m1 = inTangent1[i] * tDiff; target[path][i] = (2 * Math.pow(t, 3) - 3 * Math.pow(t, 2) + 1) * p0[i] + (Math.pow(t, 3) - 2 * Math.pow(t, 2) + t) * m0 + (-2 * Math.pow(t, 3) + 3 * Math.pow(t, 2)) * p1[i] + (Math.pow(t, 3) - Math.pow(t, 2)) * m1; } } function stepInterpolate(target, path, value) { for (let i = 0; i < value.length; i++) { target[path][i] = value[i]; } } function interpolate(time, { input, interpolation, output }, target, path) { const maxTime = input[input.length - 1]; const animationTime = time % maxTime; const nextIndex = input.findIndex((t) => t >= animationTime); const previousIndex = Math.max(0, nextIndex - 1); if (!Array.isArray(target[path])) { switch (path) { case "translation": target[path] = [0, 0, 0]; break; case "rotation": target[path] = [0, 0, 0, 1]; break; case "scale": target[path] = [1, 1, 1]; break; default: import_core2.log.warn(`Bad animation path ${path}`)(); } } (0, import_core2.assert)(target[path].length === output[previousIndex].length); const previousTime = input[previousIndex]; const nextTime = input[nextIndex]; switch (interpolation) { case "STEP": stepInterpolate(target, path, output[previousIndex]); break; case "LINEAR": if (nextTime > previousTime) { const ratio = (animationTime - previousTime) / (nextTime - previousTime); linearInterpolate(target, path, output[previousIndex], output[nextIndex], ratio); } break; case "CUBICSPLINE": if (nextTime > previousTime) { const ratio = (animationTime - previousTime) / (nextTime - previousTime); const tDiff = nextTime - previousTime; const p0 = output[3 * previousIndex + 1]; const outTangent0 = output[3 * previousIndex + 2]; const inTangent1 = output[3 * nextIndex + 0]; const p1 = output[3 * nextIndex + 1]; cubicsplineInterpolate(target, path, { p0, outTangent0, inTangent1, p1, tDiff, ratio }); } break; default: import_core2.log.warn(`Interpolation ${interpolation} not supported`)(); break; } } // src/gltf/create-gltf-model.ts var import_core4 = __toESM(require_core(), 1); // ../shadertools/src/lib/glsl-utils/highlight.ts var glsl = (x) => `${x}`; // ../shadertools/src/modules-webgl1/lighting/lights/lights-glsl.ts var lightingShader = glsl`\ #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX)) struct AmbientLight { vec3 color; }; struct PointLight { vec3 color; vec3 position; // Constant-Linear-Exponential vec3 attenuation; }; struct DirectionalLight { vec3 color; vec3 direction; }; uniform AmbientLight lighting_uAmbientLight; uniform PointLight lighting_uPointLight[MAX_LIGHTS]; uniform DirectionalLight lighting_uDirectionalLight[MAX_LIGHTS]; uniform int lighting_uPointLightCount; uniform int lighting_uDirectionalLightCount; uniform bool lighting_uEnabled; float getPointLightAttenuation(PointLight pointLight, float distance) { return pointLight.attenuation.x + pointLight.attenuation.y * distance + pointLight.attenuation.z * distance * distance; } #endif `; // ../shadertools/src/modules-webgl1/lighting/lights/lights.ts var INITIAL_MODULE_OPTIONS = { lightSources: {} }; function convertColor(colorDef = {}) { const { color = [0, 0, 0], intensity = 1 } = colorDef; return color.map((component) => component * intensity / 255); } function getLightSourceUniforms({ ambientLight, pointLights = [], directionalLights = [] }) { const lightSourceUniforms = {}; if (ambientLight) { lightSourceUniforms["lighting_uAmbientLight.color"] = convertColor(ambientLight); } else { lightSourceUniforms["lighting_uAmbientLight.color"] = [0, 0, 0]; } pointLights.forEach((pointLight, index) => { lightSourceUniforms[`lighting_uPointLight[${index}].color`] = convertColor(pointLight); lightSourceUniforms[`lighting_uPointLight[${index}].position`] = pointLight.position; lightSourceUniforms[`lighting_uPointLight[${index}].attenuation`] = pointLight.attenuation || [ 1, 0, 0 ]; }); lightSourceUniforms.lighting_uPointLightCount = pointLights.length; directionalLights.forEach((directionalLight, index) => { lightSourceUniforms[`lighting_uDirectionalLight[${index}].color`] = convertColor(directionalLight); lightSourceUniforms[`lighting_uDirectionalLight[${index}].direction`] = directionalLight.direction; }); lightSourceUniforms.lighting_uDirectionalLightCount = directionalLights.length; return lightSourceUniforms; } function getUniforms(opts = INITIAL_MODULE_OPTIONS) { if ("lightSources" in opts) { const { ambientLight, pointLights, directionalLights } = opts.lightSources || {}; const hasLights = ambientLight || pointLights && pointLights.length > 0 || directionalLights && directionalLights.length > 0; if (!hasLights) { return { lighting_uEnabled: false }; } return Object.assign( {}, getLightSourceUniforms({ ambientLight, pointLights, directionalLights }), { lighting_uEnabled: true } ); } if ("lights" in opts) { const lightSources = { pointLights: [], directionalLights: [] }; for (const light of opts.lights || []) { switch (light.type) { case "ambient": lightSources.ambientLight = light; break; case "directional": lightSources.directionalLights?.push(light); break; case "point": lightSources.pointLights?.push(light); break; default: } } return getUniforms({ lightSources }); } return {}; } var lights = { name: "lights", vs: lightingShader, fs: lightingShader, getUniforms, defines: { MAX_LIGHTS: 3 } }; // ../shadertools/src/modules-webgl1/lighting/pbr/pbr-vertex-glsl.ts var vs = glsl`\ uniform mat4 u_MVPMatrix; uniform mat4 u_ModelMatrix; uniform mat4 u_NormalMatrix; out vec3 pbr_vPosition; out vec2 pbr_vUV; #ifdef HAS_NORMALS # ifdef HAS_TANGENTS out mat3 pbr_vTBN; # else out vec3 pbr_vNormal; # endif #endif void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, vec2 uv) { vec4 pos = u_ModelMatrix * position; pbr_vPosition = vec3(pos.xyz) / pos.w; #ifdef HAS_NORMALS #ifdef HAS_TANGENTS vec3 normalW = normalize(vec3(u_NormalMatrix * vec4(normal.xyz, 0.0))); vec3 tangentW = normalize(vec3(u_ModelMatrix * vec4(tangent.xyz, 0.0))); vec3 bitangentW = cross(normalW, tangentW) * tangent.w; pbr_vTBN = mat3(tangentW, bitangentW, normalW); #else // HAS_TANGENTS != 1 pbr_vNormal = normalize(vec3(u_ModelMatrix * vec4(normal.xyz, 0.0))); #endif #endif #ifdef HAS_UV pbr_vUV = uv; #else pbr_vUV = vec2(0.,0.); #endif } `; // ../shadertools/src/modules-webgl1/lighting/pbr/pbr-fragment-glsl.ts var fs = glsl`\ precision highp float; uniform bool pbr_uUnlit; #ifdef USE_IBL uniform samplerCube u_DiffuseEnvSampler; uniform samplerCube u_SpecularEnvSampler; uniform sampler2D u_brdfLUT; uniform vec2 u_ScaleIBLAmbient; #endif #ifdef HAS_BASECOLORMAP uniform sampler2D u_BaseColorSampler; #endif #ifdef HAS_NORMALMAP uniform sampler2D u_NormalSampler; uniform float u_NormalScale; #endif #ifdef HAS_EMISSIVEMAP uniform sampler2D u_EmissiveSampler; uniform vec3 u_EmissiveFactor; #endif #ifdef HAS_METALROUGHNESSMAP uniform sampler2D u_MetallicRoughnessSampler; #endif #ifdef HAS_OCCLUSIONMAP uniform sampler2D u_OcclusionSampler; uniform float u_OcclusionStrength; #endif #ifdef ALPHA_CUTOFF uniform float u_AlphaCutoff; #endif uniform vec2 u_MetallicRoughnessValues; uniform vec4 u_BaseColorFactor; uniform vec3 u_Camera; // debugging flags used for shader output of intermediate PBR variables #ifdef PBR_DEBUG uniform vec4 u_ScaleDiffBaseMR; uniform vec4 u_ScaleFGDSpec; #endif in vec3 pbr_vPosition; in vec2 pbr_vUV; #ifdef HAS_NORMALS #ifdef HAS_TANGENTS in mat3 pbr_vTBN; #else in vec3 pbr_vNormal; #endif #endif // Encapsulate the various inputs used by the various functions in the shading equation // We store values in this struct to simplify the integration of alternative implementations // of the shading terms, outlined in the Readme.MD Appendix. struct PBRInfo { float NdotL; // cos angle between normal and light direction float NdotV; // cos angle between normal and view direction float NdotH; // cos angle between normal and half vector float LdotH; // cos angle between light direction and half vector float VdotH; // cos angle between view direction and half vector float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) float metalness; // metallic value at the surface vec3 reflectance0; // full reflectance color (normal incidence angle) vec3 reflectance90; // reflectance color at grazing angle float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) vec3 diffuseColor; // color contribution from diffuse lighting vec3 specularColor; // color contribution from specular lighting vec3 n; // normal at surface point vec3 v; // vector from surface point to camera }; const float M_PI = 3.141592653589793; const float c_MinRoughness = 0.04; vec4 SRGBtoLINEAR(vec4 srgbIn) { #ifdef MANUAL_SRGB #ifdef SRGB_FAST_APPROXIMATION vec3 linOut = pow(srgbIn.xyz,vec3(2.2)); #else //SRGB_FAST_APPROXIMATION vec3 bLess = step(vec3(0.04045),srgbIn.xyz); vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess ); #endif //SRGB_FAST_APPROXIMATION return vec4(linOut,srgbIn.w);; #else //MANUAL_SRGB return srgbIn; #endif //MANUAL_SRGB } // Find the normal for this fragment, pulling either from a predefined normal map // or from the interpolated mesh normal and tangent attributes. vec3 getNormal() { // Retrieve the tangent space matrix #ifndef HAS_TANGENTS vec3 pos_dx = dFdx(pbr_vPosition); vec3 pos_dy = dFdy(pbr_vPosition); vec3 tex_dx = dFdx(vec3(pbr_vUV, 0.0)); vec3 tex_dy = dFdy(vec3(pbr_vUV, 0.0)); vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t); #ifdef HAS_NORMALS vec3 ng = normalize(pbr_vNormal); #else vec3 ng = cross(pos_dx, pos_dy); #endif t = normalize(t - ng * dot(ng, t)); vec3 b = normalize(cross(ng, t)); mat3 tbn = mat3(t, b, ng); #else // HAS_TANGENTS mat3 tbn = pbr_vTBN; #endif #ifdef HAS_NORMALMAP vec3 n = texture(u_NormalSampler, pbr_vUV).rgb; n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_NormalScale, u_NormalScale, 1.0))); #else // The tbn matrix is linearly interpolated, so we need to re-normalize vec3 n = normalize(tbn[2].xyz); #endif return n; } // Calculation of the lighting contribution from an optional Image Based Light source. // Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1]. // See our README.md on Environment Maps [3] for additional discussion. #ifdef USE_IBL vec3 getIBLContribution(PBRInfo pbrInputs, vec3 n, vec3 reflection) { float mipCount = 9.0; // resolution of 512x512 float lod = (pbrInputs.perceptualRoughness * mipCount); // retrieve a scale and bias to F0. See [1], Figure 3 vec3 brdf = SRGBtoLINEAR(texture(u_brdfLUT, vec2(pbrInputs.NdotV, 1.0 - pbrInputs.perceptualRoughness))).rgb; vec3 diffuseLight = SRGBtoLINEAR(textureCube(u_DiffuseEnvSampler, n)).rgb; #ifdef USE_TEX_LOD vec3 specularLight = SRGBtoLINEAR(textureCubeLod(u_SpecularEnvSampler, reflection, lod)).rgb; #else vec3 specularLight = SRGBtoLINEAR(textureCube(u_SpecularEnvSampler, reflection)).rgb; #endif vec3 diffuse = diffuseLight * pbrInputs.diffuseColor; vec3 specular = specularLight * (pbrInputs.specularColor * brdf.x + brdf.y); // For presentation, this allows us to disable IBL terms diffuse *= u_ScaleIBLAmbient.x; specular *= u_ScaleIBLAmbient.y; return diffuse + specular; } #endif // Basic Lambertian diffuse // Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog // See also [1], Equation 1 vec3 diffuse(PBRInfo pbrInputs) { return pbrInputs.diffuseColor / M_PI; } // The following equation models the Fresnel reflectance term of the spec equation (aka F()) // Implementation of fresnel from [4], Equation 15 vec3 specularReflection(PBRInfo pbrInputs) { return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0); } // This calculates the specular geometric attenuation (aka G()), // where rougher material will reflect less light back to the viewer. // This implementation is based on [1] Equation 4, and we adopt their modifications to // alphaRoughness as input as originally proposed in [2]. float geometricOcclusion(PBRInfo pbrInputs) { float NdotL = pbrInputs.NdotL; float NdotV = pbrInputs.NdotV; float r = pbrInputs.alphaRoughness; float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); return attenuationL * attenuationV; } // The following equation(s) model the distribution of microfacet normals across // the area being drawn (aka D()) // Implementation from "Average Irregularity Representation of a Roughened Surface // for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz // Follows the distribution function recommended in the SIGGRAPH 2013 course notes // from EPIC Games [1], Equation 3. float microfacetDistribution(PBRInfo pbrInputs) { float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness; float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0; return roughnessSq / (M_PI * f * f); } void PBRInfo_setAmbientLight(inout PBRInfo pbrInputs) { pbrInputs.NdotL = 1.0; pbrInputs.NdotH = 0.0; pbrInputs.LdotH = 0.0; pbrInputs.VdotH = 1.0; } void PBRInfo_setDirectionalLight(inout PBRInfo pbrInputs, vec3 lightDirection) { vec3 n = pbrInputs.n; vec3 v = pbrInputs.v; vec3 l = normalize(lightDirection); // Vector from surface point to light vec3 h = normalize(l+v); // Half vector between both l and v pbrInputs.NdotL = clamp(dot(n, l), 0.001, 1.0); pbrInputs.NdotH = clamp(dot(n, h), 0.0, 1.0); pbrInputs.LdotH = clamp(dot(l, h), 0.0, 1.0); pbrInputs.VdotH = clamp(dot(v, h), 0.0, 1.0); } void PBRInfo_setPointLight(inout PBRInfo pbrInputs, PointLight pointLight) { vec3 light_direction = normalize(pointLight.position - pbr_vPosition); PBRInfo_setDirectionalLight(pbrInputs, light_direction); } vec3 calculateFinalColor(PBRInfo pbrInputs, vec3 lightColor) { // Calculate the shading terms for the microfacet specular shading model vec3 F = specularReflection(pbrInputs); float G = geometricOcclusion(pbrInputs); float D = microfacetDistribution(pbrInputs); // Calculation of analytical lighting contribution vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs); vec3 specContrib = F * G * D / (4.0 * pbrInputs.NdotL * pbrInputs.NdotV); // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law) return pbrInputs.NdotL * lightColor * (diffuseContrib + specContrib); } vec4 pbr_filterColor(vec4 colorUnused) { // The albedo may be defined from a base texture or a flat color #ifdef HAS_BASECOLORMAP vec4 baseColor = SRGBtoLINEAR(texture(u_BaseColorSampler, pbr_vUV)) * u_BaseColorFactor; #else vec4 baseColor = u_BaseColorFactor; #endif #ifdef ALPHA_CUTOFF if (baseColor.a < u_AlphaCutoff) { discard; } #endif vec3 color = vec3(0, 0, 0); if(pbr_uUnlit){ color.rgb = baseColor.rgb; } else{ // Metallic and Roughness material properties are packed together // In glTF, these factors can be specified by fixed scalar values // or from a metallic-roughness map float perceptualRoughness = u_MetallicRoughnessValues.y; float metallic = u_MetallicRoughnessValues.x; #ifdef HAS_METALROUGHNESSMAP // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel. // This layout intentionally reserves the 'r' channel for (optional) occlusion map data vec4 mrSample = texture(u_MetallicRoughnessSampler, pbr_vUV); perceptualRoughness = mrSample.g * perceptualRoughness; metallic = mrSample.b * metallic; #endif perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0); metallic = clamp(metallic, 0.0, 1.0); // Roughness is authored as perceptual roughness; as is convention, // convert to material roughness by squaring the perceptual roughness [2]. float alphaRoughness = perceptualRoughness * perceptualRoughness; vec3 f0 = vec3(0.04); vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0); diffuseColor *= 1.0 - metallic; vec3 specularColor = mix(f0, baseColor.rgb, metallic); // Compute reflectance. float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); // For typical incident reflectance range (between 4% to 100%) set the grazing // reflectance to 100% for typical fresnel effect. // For very low reflectance range on highly diffuse objects (below 4%), // incrementally reduce grazing reflecance to 0%. float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); vec3 specularEnvironmentR0 = specularColor.rgb; vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90; vec3 n = getNormal(); // normal at surface point vec3 v = normalize(u_Camera - pbr_vPosition); // Vector from surface point to camera float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); vec3 reflection = -normalize(reflect(v, n)); PBRInfo pbrInputs = PBRInfo( 0.0, // NdotL NdotV, 0.0, // NdotH 0.0, // LdotH 0.0, // VdotH perceptualRoughness, metallic, specularEnvironmentR0, specularEnvironmentR90, alphaRoughness, diffuseColor, specularColor, n, v ); #ifdef USE_LIGHTS // Apply ambient light PBRInfo_setAmbientLight(pbrInputs); color += calculateFinalColor(pbrInputs, lighting_uAmbientLight.color); // Apply directional light for(int i = 0; i < lighting_uDirectionalLightCount; i++) { if (i < lighting_uDirectionalLightCount) { PBRInfo_setDirectionalLight(pbrInputs, lighting_uDirectionalLight[i].direction); color += calculateFinalColor(pbrInputs, lighting_uDirectionalLight[i].color); } } // Apply point light for(int i = 0; i < lighting_uPointLightCount; i++) { if (i < lighting_uPointLightCount) { PBRInfo_setPointLight(pbrInputs, lighting_uPointLight[i]); float attenuation = getPointLightAttenuation(lighting_uPointLight[i], distance(lighting_uPointLight[i].position, pbr_vPosition)); color += calculateFinalColor(pbrInputs, lighting_uPointLight[i].color / attenuation); } } #endif // Calculate lighting contribution from image based lighting source (IBL) #ifdef USE_IBL color += getIBLContribution(pbrInputs, n, reflection); #endif // Apply optional PBR terms for additional (optional) shading #ifdef HAS_OCCLUSIONMAP float ao = texture(u_OcclusionSampler, pbr_vUV).r; color = mix(color, color * ao, u_OcclusionStrength); #endif #ifdef HAS_EMISSIVEMAP vec3 emissive = SRGBtoLINEAR(texture(u_EmissiveSampler, pbr_vUV)).rgb * u_EmissiveFactor; color += emissive; #endif // This section uses mix to override final color for reference app visualization // of various parameters in the lighting equation. #ifdef PBR_DEBUG // TODO: Figure out how to debug multiple lights // color = mix(color, F, u_ScaleFGDSpec.x); // color = mix(color, vec3(G), u_ScaleFGDSpec.y); // color = mix(color, vec3(D), u_ScaleFGDSpec.z); // color = mix(color, specContrib, u_ScaleFGDSpec.w); // color = mix(color, diffuseContrib, u_ScaleDiffBaseMR.x); color = mix(color, baseColor.rgb, u_ScaleDiffBaseMR.y); color = mix(color, vec3(metallic), u_ScaleDiffBaseMR.z); color = mix(color, vec3(perceptualRoughness), u_ScaleDiffBaseMR.w); #endif } return vec4(pow(color,vec3(1.0/2.2)), baseColor.a); } `; // ../shadertools/src/modules-webgl1/lighting/pbr/pbr.ts var pbr = { name: "pbr", vs, fs, defines: { LIGHTING_FRAGMENT: 1 }, dependencies: [lights] }; // src/gltf/create-gltf-model.ts var import_engine = __toESM(require_engine(), 1); var vs2 = ` #pragma vscode_glsllint_stage: vert #if (__VERSION__ < 300) #define _attr attribute #else #define _attr in #endif // _attr vec4 POSITION; _attr vec4 positions; #ifdef HAS_NORMALS // _attr vec4 NORMAL; _attr vec4 normals; #endif #ifdef HAS_TANGENTS _attr vec4 TANGENT; #endif #ifdef HAS_UV // _attr vec2 TEXCOORD_0; _attr vec2 texCoords; #endif void main(void) { vec4 _NORMAL = vec4(0.); vec4 _TANGENT = vec4(0.); vec2 _TEXCOORD_0 = vec2(0.); #ifdef HAS_NORMALS _NORMAL = normals; #endif #ifdef HAS_TANGENTS _TANGENT = TANGENT; #endif #ifdef HAS_UV _TEXCOORD_0 = texCoords; #endif pbr_setPositionNormalTangentUV(positions, _NORMAL, _TANGENT, _TEXCOORD_0); gl_Position = u_MVPMatrix * positions; } `; var fs2 = ` #pragma vscode_glsllint_stage: frag #if (__VERSION__ < 300) #define fragmentColor gl_FragColor #else out vec4 fragmentColor; #endif void main(void) { vec3 pos = pbr_vPosition; fragmentColor = pbr_filterColor(vec4(1.0)); } `; function createGLTFModel(device, options) { const { id, geometry, material, vertexCount, materialOptions, modelOptions } = options; const parsedMaterial = parsePBRMaterial(device, material, geometry.attributes, materialOptions); import_core4.log.info(4, "createGLTFModel defines: ", parsedMaterial.defines)(); const managedResources = []; const parameters = { depthWriteEnabled: true, depthCompare: "less", depthFormat: "depth24plus", cullMode: "back" }; const modelProps = { id, geometry, topology: geometry.topology, vertexCount, modules: [pbr], vs: addVersionToShader(device, vs2), fs: addVersionToShader(device, fs2), ...modelOptions, bindings: { ...parsedMaterial.bindings, ...modelOptions.bindings }, defines: { ...parsedMaterial.defines, ...modelOptions.defines }, parameters: { ...parameters, ...parsedMaterial.parameters, ...modelOptions.parameters }, uniforms: { ...parsedMaterial.uniforms, ...modelOptions.uniforms } }; const model = new import_engine.Model(device, modelProps); return new import_engine.ModelNode({ managedResources, model }); } function addVersionToShader(device, source) { return `#version 300 es ${source}`; } // src/gltf/gltf-instantiator.ts var DEFAULT_OPTIONS = { modelOptions: {}, pbrDebug: false, imageBasedLightingEnvironment: null, lights: true, useTangents: false }; var GLTFInstantiator = class { device; options; gltf; constructor(device, options = {}) { this.device = device; this.options = { ...DEFAULT_OPTIONS, ...options }; } instantiate(gltf) { this.gltf = gltf; const scenes = (gltf.scenes || []).map((scene) => this.createScene(scene)); return scenes; } createAnimator() { if (Array.isArray(this.gltf.animations)) { return new GLTFAnimator(this.gltf); } return null; } createScene(gltfScene) { const gltfNodes = gltfScene.nodes || []; const nodes = gltfNodes.map((node) => this.createNode(node)); const scene = new import_engine2.GroupNode({ id: gltfScene.name || gltfScene.id, children: nodes }); return scene; } createNode(gltfNode) { if (!gltfNode._node) { const gltfChildren = gltfNode.children || []; const children = gltfChildren.map((child) => this.createNode(child)); if (gltfNode.mesh) { children.push(this.createMesh(gltfNode.mesh)); } const node = new import_engine2.GroupNode({ id: gltfNode.name || gltfNode.id, children }); if (gltfNode.matrix) { node.setMatrix(gltfNode.matrix); } else { node.matrix.identity(); if (gltfNode.translation) { node.matrix.translate(gltfNode.translation); } if (gltfNode.rotation) { const rotationMatrix = new Matrix4().fromQuaternion(gltfNode.rotation); node.matrix.multiplyRight(rotationMatrix); } if (gltfNode.scale) { node.matrix.scale(gltfNode.scale); } } gltfNode._node = node; } return gltfNode._node; } createMesh(gltfMesh) { if (!gltfMesh._mesh) { const gltfPrimitives = gltfMesh.primitives || []; const primitives = gltfPrimitives.map( (gltfPrimitive, i) => this.createPrimitive(gltfPrimitive, i, gltfMesh) ); const mesh = new import_engine2.GroupNode({ id: gltfMesh.name || gltfMesh.id, children: primitives }); gltfMesh._mesh = mesh; } return gltfMesh._mesh; } createPrimitive(gltfPrimitive, i, gltfMesh) { const id = gltfPrimitive.name || `${gltfMesh.name || gltfMesh.id}-primitive-${i}`; const topology = convertGLDrawModeToTopology(gltfPrimitive.mode || 4); const vertexCount = gltfPrimitive.indices ? gltfPrimitive.indices.count : this.getVertexCount(gltfPrimitive.attributes); const modelNode = createGLTFModel(this.device, { id, geometry: this.createGeometry(id, gltfPrimitive, topology), material: gltfPrimitive.material, materialOptions: this.options, modelOptions: this.options.modelOptions, vertexCount }); modelNode.bounds = [ gltfPrimitive.attributes.POSITION.min, gltfPrimitive.attributes.POSITION.max ]; return modelNode; } getVertexCount(attributes) { throw new Error("getVertexCount not implemented"); } createGeometry(id, gltfPrimitive, topology) { const attributes = {}; for (const [attributeName, attribute] of Object.entries(gltfPrimitive.attributes)) { const { components, size, value } = attribute; attributes[attributeName] = { size: size ?? components, value }; } return new import_engine2.Geometry({ id, topology, indices: gltfPrimitive.indices.value, attributes }); } createBuffer(attribute, usage) { if (!attribute.bufferView) { attribute.bufferView = {}; } const { bufferView } = attribute; if (!bufferView.lumaBuffers) { bufferView.lumaBuffers = {}; } if (!bufferView.lumaBuffers[usage]) { bufferView.lumaBuffers[usage] = this.device.createBuffer({ id: `from-${bufferView.id}`, // Draco decoded files have attribute.value data: bufferView.data || attribute.value }); } return bufferView.lumaBuffers[usage]; } // TODO - create sampler in WebGL2 createSampler(gltfSampler) { return gltfSampler; } // Helper methods (move to GLTFLoader.resolve...?) needsPOT() { return false; } }; function convertGLDrawModeToTopology(drawMode) { switch (drawMode) { case 0 /* POINTS */: return "point-list"; case 1 /* LINES */: return "line-list"; case 3 /* LINE_STRIP */: return "line-strip"; case 2 /* LINE_LOOP */: return "line-loop-webgl"; case 4 /* TRIANGLES */: return "triangle-list"; case 5 /* TRIANGLE_STRIP */: return "triangle-strip"; case 6 /* TRIANGLE_FAN */: return "triangle-fan-webgl"; default: throw new Error(drawMode); } } // src/gltf/create-gltf-objects.ts function createScenegraphsFromGLTF(device, gltf, options) { const instantiator = new GLTFInstantiator(device, options); const scenes = instantiator.instantiate(gltf); const animator = instantiator.createAnimator(); return { scenes, animator }; } return __toCommonJS(bundle_exports); })(); return __exports__; });