@luma.gl/gltf 9.3.0-alpha.2 → 9.3.0-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/dist.dev.js +403 -220
  2. package/dist/dist.min.js +98 -46
  3. package/dist/gltf/animations/animations.d.ts +16 -4
  4. package/dist/gltf/animations/animations.d.ts.map +1 -1
  5. package/dist/gltf/animations/interpolate.d.ts +4 -3
  6. package/dist/gltf/animations/interpolate.d.ts.map +1 -1
  7. package/dist/gltf/animations/interpolate.js +27 -36
  8. package/dist/gltf/animations/interpolate.js.map +1 -1
  9. package/dist/gltf/create-gltf-model.d.ts +6 -0
  10. package/dist/gltf/create-gltf-model.d.ts.map +1 -1
  11. package/dist/gltf/create-gltf-model.js +96 -44
  12. package/dist/gltf/create-gltf-model.js.map +1 -1
  13. package/dist/gltf/create-scenegraph-from-gltf.d.ts +15 -1
  14. package/dist/gltf/create-scenegraph-from-gltf.d.ts.map +1 -1
  15. package/dist/gltf/create-scenegraph-from-gltf.js +12 -6
  16. package/dist/gltf/create-scenegraph-from-gltf.js.map +1 -1
  17. package/dist/gltf/gltf-animator.d.ts +26 -0
  18. package/dist/gltf/gltf-animator.d.ts.map +1 -1
  19. package/dist/gltf/gltf-animator.js +22 -19
  20. package/dist/gltf/gltf-animator.js.map +1 -1
  21. package/dist/index.cjs +384 -210
  22. package/dist/index.cjs.map +4 -4
  23. package/dist/index.d.ts +1 -2
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/parsers/parse-gltf-animations.d.ts +1 -0
  27. package/dist/parsers/parse-gltf-animations.d.ts.map +1 -1
  28. package/dist/parsers/parse-gltf-animations.js +46 -23
  29. package/dist/parsers/parse-gltf-animations.js.map +1 -1
  30. package/dist/parsers/parse-gltf-lights.d.ts.map +1 -1
  31. package/dist/parsers/parse-gltf-lights.js +40 -12
  32. package/dist/parsers/parse-gltf-lights.js.map +1 -1
  33. package/dist/parsers/parse-gltf.d.ts +16 -1
  34. package/dist/parsers/parse-gltf.d.ts.map +1 -1
  35. package/dist/parsers/parse-gltf.js +65 -57
  36. package/dist/parsers/parse-gltf.js.map +1 -1
  37. package/dist/parsers/parse-pbr-material.d.ts +46 -1
  38. package/dist/parsers/parse-pbr-material.d.ts.map +1 -1
  39. package/dist/parsers/parse-pbr-material.js +142 -13
  40. package/dist/parsers/parse-pbr-material.js.map +1 -1
  41. package/dist/pbr/pbr-environment.d.ts +6 -0
  42. package/dist/pbr/pbr-environment.d.ts.map +1 -1
  43. package/dist/pbr/pbr-environment.js +1 -0
  44. package/dist/pbr/pbr-environment.js.map +1 -1
  45. package/dist/pbr/pbr-material.d.ts +5 -0
  46. package/dist/pbr/pbr-material.d.ts.map +1 -1
  47. package/dist/webgl-to-webgpu/convert-webgl-attribute.d.ts +12 -1
  48. package/dist/webgl-to-webgpu/convert-webgl-attribute.d.ts.map +1 -1
  49. package/dist/webgl-to-webgpu/convert-webgl-attribute.js +3 -0
  50. package/dist/webgl-to-webgpu/convert-webgl-attribute.js.map +1 -1
  51. package/dist/webgl-to-webgpu/convert-webgl-sampler.d.ts +6 -0
  52. package/dist/webgl-to-webgpu/convert-webgl-sampler.d.ts.map +1 -1
  53. package/dist/webgl-to-webgpu/convert-webgl-sampler.js +4 -0
  54. package/dist/webgl-to-webgpu/convert-webgl-sampler.js.map +1 -1
  55. package/dist/webgl-to-webgpu/convert-webgl-topology.d.ts +2 -0
  56. package/dist/webgl-to-webgpu/convert-webgl-topology.d.ts.map +1 -1
  57. package/dist/webgl-to-webgpu/convert-webgl-topology.js +2 -0
  58. package/dist/webgl-to-webgpu/convert-webgl-topology.js.map +1 -1
  59. package/package.json +5 -5
  60. package/src/gltf/animations/animations.ts +17 -5
  61. package/src/gltf/animations/interpolate.ts +49 -68
  62. package/src/gltf/create-gltf-model.ts +101 -43
  63. package/src/gltf/create-scenegraph-from-gltf.ts +39 -11
  64. package/src/gltf/gltf-animator.ts +34 -25
  65. package/src/index.ts +1 -2
  66. package/src/parsers/parse-gltf-animations.ts +63 -26
  67. package/src/parsers/parse-gltf-lights.ts +51 -13
  68. package/src/parsers/parse-gltf.ts +90 -77
  69. package/src/parsers/parse-pbr-material.ts +210 -15
  70. package/src/pbr/pbr-environment.ts +10 -0
  71. package/src/pbr/pbr-material.ts +5 -0
  72. package/src/webgl-to-webgpu/convert-webgl-attribute.ts +12 -1
  73. package/src/webgl-to-webgpu/convert-webgl-sampler.ts +9 -0
  74. package/src/webgl-to-webgpu/convert-webgl-topology.ts +2 -0
  75. package/dist/utils/deep-copy.d.ts +0 -3
  76. package/dist/utils/deep-copy.d.ts.map +0 -1
  77. package/dist/utils/deep-copy.js +0 -21
  78. package/dist/utils/deep-copy.js.map +0 -1
  79. package/src/utils/deep-copy.ts +0 -22
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.ts", "../src/pbr/pbr-environment.ts", "../src/parsers/parse-pbr-material.ts", "../src/webgl-to-webgpu/convert-webgl-sampler.ts", "../src/parsers/parse-gltf-lights.ts", "../src/parsers/parse-gltf.ts", "../src/webgl-to-webgpu/convert-webgl-topology.ts", "../src/gltf/create-gltf-model.ts", "../src/gltf/gltf-animator.ts", "../src/gltf/animations/interpolate.ts", "../src/webgl-to-webgpu/convert-webgl-attribute.ts", "../src/parsers/parse-gltf-animations.ts", "../src/utils/deep-copy.ts", "../src/gltf/create-scenegraph-from-gltf.ts"],
4
- "sourcesContent": ["// luma.gl, MIT license\n\nexport {loadPBREnvironment, type PBREnvironment} from './pbr/pbr-environment';\nexport {type ParsedPBRMaterial} from './pbr/pbr-material';\nexport {parsePBRMaterial, type ParsePBRMaterialOptions} from './parsers/parse-pbr-material';\nexport {} from './pbr/pbr-environment';\nexport {parseGLTFLights} from './parsers/parse-gltf-lights';\n\n// glTF Scenegraph Instantiator\nexport {createScenegraphsFromGLTF} from './gltf/create-scenegraph-from-gltf';\nexport {GLTFAnimator} from './gltf/gltf-animator';\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {Device, SamplerProps} from '@luma.gl/core';\nimport {DynamicTexture} from '@luma.gl/engine';\nimport {loadImageTexture} from '@loaders.gl/textures';\n\n/** Environment textures for PBR module */\nexport type PBREnvironment = {\n /** Bi-directional Reflectance Distribution Function (BRDF) lookup table */\n brdfLutTexture: DynamicTexture;\n diffuseEnvSampler: DynamicTexture;\n specularEnvSampler: DynamicTexture;\n};\n\nexport type PBREnvironmentProps = {\n brdfLutUrl: string;\n getTexUrl: (name: string, dir: number, level: number) => string;\n specularMipLevels?: number;\n};\n\n/** Loads textures for PBR environment */\nexport function loadPBREnvironment(device: Device, props: PBREnvironmentProps): PBREnvironment {\n const brdfLutTexture = new DynamicTexture(device, {\n id: 'brdfLUT',\n sampler: {\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n minFilter: 'linear',\n magFilter: 'linear'\n } as const satisfies SamplerProps,\n // Texture accepts a promise that returns an image as data (Async Textures)\n data: loadImageTexture(props.brdfLutUrl)\n });\n\n const diffuseEnvSampler = makeCube(device, {\n id: 'DiffuseEnvSampler',\n getTextureForFace: dir => loadImageTexture(props.getTexUrl('diffuse', dir, 0)),\n sampler: {\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n minFilter: 'linear',\n magFilter: 'linear'\n } as const satisfies SamplerProps\n });\n\n const specularEnvSampler = makeCube(device, {\n id: 'SpecularEnvSampler',\n getTextureForFace: (dir: number) => {\n const imageArray: Promise<any>[] = [];\n // @ts-ignore\n for (let lod = 0; lod <= props.specularMipLevels - 1; lod++) {\n imageArray.push(loadImageTexture(props.getTexUrl('specular', dir, lod)));\n }\n return imageArray;\n },\n sampler: {\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n minFilter: 'linear', // [GL.TEXTURE_MIN_FILTER]: GL.LINEAR_MIPMAP_LINEAR,\n magFilter: 'linear'\n } as const satisfies SamplerProps\n });\n\n return {\n brdfLutTexture,\n diffuseEnvSampler,\n specularEnvSampler\n };\n}\n\n// TODO put somewhere common\nconst FACES = [0, 1, 2, 3, 4, 5];\n\nfunction makeCube(\n device: Device,\n {\n id,\n getTextureForFace,\n sampler\n }: {\n id: string;\n getTextureForFace: (dir: number) => Promise<any> | Promise<any>[];\n sampler: SamplerProps;\n }\n): DynamicTexture {\n const data = {};\n FACES.forEach(face => {\n // @ts-ignore TODO\n data[String(face)] = getTextureForFace(face);\n });\n return new DynamicTexture(device, {\n id,\n dimension: 'cube',\n mipmaps: false,\n sampler,\n // @ts-expect-error\n data\n });\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {Device, Texture} from '@luma.gl/core';\nimport {GL} from '@luma.gl/constants';\n\nimport {log} from '@luma.gl/core';\nimport {type ParsedPBRMaterial} from '../pbr/pbr-material';\nimport {type PBREnvironment} from '../pbr/pbr-environment';\nimport {type PBRMaterialBindings} from '@luma.gl/shadertools';\nimport {convertSampler} from '../webgl-to-webgpu/convert-webgl-sampler';\n\n// TODO - synchronize the GLTF... types with loaders.gl\n// TODO - remove the glParameters, use only parameters\n\n/* eslint-disable camelcase */\n\ntype GLTFTexture = {\n id: string;\n texture: {source: {image: any}; sampler: {parameters: any}};\n uniformName?: string;\n // is this on all textures?\n scale?: number;\n // is this on all textures?\n strength?: number;\n};\n\ntype GLTFPBRMetallicRoughness = {\n baseColorTexture?: GLTFTexture;\n baseColorFactor?: [number, number, number, number];\n metallicRoughnessTexture?: GLTFTexture;\n metallicFactor?: number;\n roughnessFactor?: number;\n};\n\ntype GLTFPBRMaterial = {\n unlit?: boolean;\n pbrMetallicRoughness?: GLTFPBRMetallicRoughness;\n normalTexture?: GLTFTexture;\n occlusionTexture?: GLTFTexture;\n emissiveTexture?: GLTFTexture;\n emissiveFactor?: [number, number, number];\n alphaMode?: 'MASK' | 'BLEND';\n alphaCutoff?: number;\n};\n\nexport type ParsePBRMaterialOptions = {\n /** Debug PBR shader */\n pbrDebug?: boolean;\n /** Enable lights */\n lights?: any;\n /** Use tangents */\n useTangents?: boolean;\n /** provide an image based (texture cube) lighting environment */\n imageBasedLightingEnvironment?: PBREnvironment;\n};\n\n/**\n * Parses a GLTF material definition into uniforms and parameters for the PBR shader module\n */\nexport function parsePBRMaterial(\n device: Device,\n material: GLTFPBRMaterial,\n attributes: Record<string, any>,\n options: ParsePBRMaterialOptions\n): ParsedPBRMaterial {\n const parsedMaterial: ParsedPBRMaterial = {\n defines: {\n // TODO: Use EXT_sRGB if available (Standard in WebGL 2.0)\n MANUAL_SRGB: true,\n SRGB_FAST_APPROXIMATION: true\n },\n bindings: {},\n uniforms: {\n // TODO: find better values?\n camera: [0, 0, 0], // Model should override\n\n metallicRoughnessValues: [1, 1] // Default is 1 and 1\n },\n parameters: {},\n glParameters: {},\n generatedTextures: []\n };\n\n // TODO - always available\n parsedMaterial.defines['USE_TEX_LOD'] = true;\n\n const {imageBasedLightingEnvironment} = options;\n if (imageBasedLightingEnvironment) {\n parsedMaterial.bindings.pbr_diffuseEnvSampler =\n imageBasedLightingEnvironment.diffuseEnvSampler.texture;\n parsedMaterial.bindings.pbr_specularEnvSampler =\n imageBasedLightingEnvironment.specularEnvSampler.texture;\n parsedMaterial.bindings.pbr_BrdfLUT = imageBasedLightingEnvironment.brdfLutTexture.texture;\n parsedMaterial.uniforms.scaleIBLAmbient = [1, 1];\n }\n\n if (options?.pbrDebug) {\n parsedMaterial.defines['PBR_DEBUG'] = true;\n // Override final color for reference app visualization of various parameters in the lighting equation.\n parsedMaterial.uniforms.scaleDiffBaseMR = [0, 0, 0, 0];\n parsedMaterial.uniforms.scaleFGDSpec = [0, 0, 0, 0];\n }\n\n if (attributes['NORMAL']) parsedMaterial.defines['HAS_NORMALS'] = true;\n if (attributes['TANGENT'] && options?.useTangents) parsedMaterial.defines['HAS_TANGENTS'] = true;\n if (attributes['TEXCOORD_0']) parsedMaterial.defines['HAS_UV'] = true;\n\n if (options?.imageBasedLightingEnvironment) parsedMaterial.defines['USE_IBL'] = true;\n if (options?.lights) parsedMaterial.defines['USE_LIGHTS'] = true;\n\n if (material) {\n parseMaterial(device, material, parsedMaterial);\n }\n\n return parsedMaterial;\n}\n\n/** Parse GLTF material record */\nfunction parseMaterial(\n device: Device,\n material: GLTFPBRMaterial,\n parsedMaterial: ParsedPBRMaterial\n): void {\n parsedMaterial.uniforms.unlit = Boolean(material.unlit);\n\n if (material.pbrMetallicRoughness) {\n parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial);\n }\n if (material.normalTexture) {\n addTexture(\n device,\n material.normalTexture,\n 'pbr_normalSampler',\n 'HAS_NORMALMAP',\n parsedMaterial\n );\n\n const {scale = 1} = material.normalTexture;\n parsedMaterial.uniforms.normalScale = scale;\n }\n if (material.occlusionTexture) {\n addTexture(\n device,\n material.occlusionTexture,\n 'pbr_occlusionSampler',\n 'HAS_OCCLUSIONMAP',\n parsedMaterial\n );\n\n const {strength = 1} = material.occlusionTexture;\n parsedMaterial.uniforms.occlusionStrength = strength;\n }\n if (material.emissiveTexture) {\n addTexture(\n device,\n material.emissiveTexture,\n 'pbr_emissiveSampler',\n 'HAS_EMISSIVEMAP',\n parsedMaterial\n );\n parsedMaterial.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];\n }\n\n switch (material.alphaMode || 'MASK') {\n case 'MASK':\n const {alphaCutoff = 0.5} = material;\n parsedMaterial.defines['ALPHA_CUTOFF'] = true;\n parsedMaterial.uniforms.alphaCutoff = alphaCutoff;\n break;\n case 'BLEND':\n log.warn('glTF BLEND alphaMode might not work well because it requires mesh sorting')();\n\n // WebGPU style parameters\n parsedMaterial.parameters.blend = true;\n\n parsedMaterial.parameters.blendColorOperation = 'add';\n parsedMaterial.parameters.blendColorSrcFactor = 'src-alpha';\n parsedMaterial.parameters.blendColorDstFactor = 'one-minus-src-alpha';\n\n parsedMaterial.parameters.blendAlphaOperation = 'add';\n parsedMaterial.parameters.blendAlphaSrcFactor = 'one';\n parsedMaterial.parameters.blendAlphaDstFactor = 'one-minus-src-alpha';\n\n // GL parameters\n // TODO - remove in favor of parameters\n parsedMaterial.glParameters['blend'] = true;\n parsedMaterial.glParameters['blendEquation'] = GL.FUNC_ADD;\n parsedMaterial.glParameters['blendFunc'] = [\n GL.SRC_ALPHA,\n GL.ONE_MINUS_SRC_ALPHA,\n GL.ONE,\n GL.ONE_MINUS_SRC_ALPHA\n ];\n\n break;\n }\n}\n\n/** Parse GLTF material sub record */\nfunction parsePbrMetallicRoughness(\n device: Device,\n pbrMetallicRoughness: GLTFPBRMetallicRoughness,\n parsedMaterial: ParsedPBRMaterial\n): void {\n if (pbrMetallicRoughness.baseColorTexture) {\n addTexture(\n device,\n pbrMetallicRoughness.baseColorTexture,\n 'pbr_baseColorSampler',\n 'HAS_BASECOLORMAP',\n parsedMaterial\n );\n }\n parsedMaterial.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];\n\n if (pbrMetallicRoughness.metallicRoughnessTexture) {\n addTexture(\n device,\n pbrMetallicRoughness.metallicRoughnessTexture,\n 'pbr_metallicRoughnessSampler',\n 'HAS_METALROUGHNESSMAP',\n parsedMaterial\n );\n }\n const {metallicFactor = 1, roughnessFactor = 1} = pbrMetallicRoughness;\n parsedMaterial.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];\n}\n\n/** Create a texture from a glTF texture/sampler/image combo and add it to bindings */\nfunction addTexture(\n device: Device,\n gltfTexture: GLTFTexture,\n uniformName: keyof PBRMaterialBindings,\n define: string,\n parsedMaterial: ParsedPBRMaterial\n): void {\n const image = gltfTexture.texture.source.image;\n let textureOptions;\n\n if (image.compressed) {\n textureOptions = image;\n } else {\n // Texture2D accepts a promise that returns an image as data (Async Textures)\n textureOptions = {data: image};\n }\n\n const gltfSampler = {\n wrapS: 10497, // default REPEAT S (U) wrapping mode.\n wrapT: 10497, // default REPEAT T (V) wrapping mode.\n ...gltfTexture?.texture?.sampler\n } as any;\n\n const texture: Texture = device.createTexture({\n id: gltfTexture.uniformName || gltfTexture.id,\n sampler: convertSampler(gltfSampler),\n ...textureOptions\n });\n\n parsedMaterial.bindings[uniformName] = texture;\n if (define) parsedMaterial.defines[define] = true;\n parsedMaterial.generatedTextures.push(texture);\n}\n\n/*\n/**\n * Parses a GLTF material definition into uniforms and parameters for the PBR shader module\n *\nexport class PBRMaterialParser {\n readonly device: Device;\n\n readonly defines: Record<string, boolean>;\n readonly bindings: Record<string, Binding>;\n readonly uniforms: Record<string, any>;\n readonly parameters: Record<string, any>;\n\n /** Hold on to generated textures, we destroy them in the destroy method *\n readonly generatedTextures: Texture[];\n\n constructor(device: Device, props: PBRMaterialParserProps) {\n const {attributes, material, pbrDebug, imageBasedLightingEnvironment, lights, useTangents} =\n props;\n this.device = device;\n\n this.defines = {\n // TODO: Use EXT_sRGB if available (Standard in WebGL 2.0)\n MANUAL_SRGB: true,\n SRGB_FAST_APPROXIMATION: true\n };\n\n if (this.device.features.has('glsl-texture-lod')) {\n this.defines.USE_TEX_LOD = true;\n }\n\n this.uniforms = {\n // TODO: find better values?\n camera: [0, 0, 0], // Model should override\n\n metallicRoughnessValues: [1, 1] // Default is 1 and 1\n };\n\n this.bindings = {};\n\n this.parameters = {};\n this.generatedTextures = [];\n\n if (imageBasedLightingEnvironment) {\n this.bindings.pbr_diffuseEnvSampler = imageBasedLightingEnvironment.getDiffuseEnvSampler();\n this.bindings.pbr_specularEnvSampler = imageBasedLightingEnvironment.getSpecularEnvSampler();\n this.bindings.pbr_BrdfLUT = imageBasedLightingEnvironment.getBrdfTexture();\n this.uniforms.scaleIBLAmbient = [1, 1];\n }\n\n if (pbrDebug) {\n // Override final color for reference app visualization\n // of various parameters in the lighting equation.\n this.uniforms.scaleDiffBaseMR = [0, 0, 0, 0];\n this.uniforms.scaleFGDSpec = [0, 0, 0, 0];\n }\n\n this.defineIfPresent(attributes.NORMAL, 'HAS_NORMALS');\n this.defineIfPresent(attributes.TANGENT && useTangents, 'HAS_TANGENTS');\n this.defineIfPresent(attributes.TEXCOORD_0, 'HAS_UV');\n\n this.defineIfPresent(imageBasedLightingEnvironment, 'USE_IBL');\n this.defineIfPresent(lights, 'USE_LIGHTS');\n this.defineIfPresent(pbrDebug, 'PBR_DEBUG');\n\n if (material) {\n this.parseMaterial(material);\n }\n }\n\n /**\n * Destroy all generated resources to release memory.\n *\n destroy(): void {\n this.generatedTextures.forEach(texture => texture.destroy());\n }\n\n /** Add a define if the the value is non-nullish *\n defineIfPresent(value: unknown, name: string): void {\n if (value) {\n this.defines[name] = 1;\n }\n }\n\n /** Parse GLTF material record *\n parseMaterial(material) {\n this.uniforms.unlit = Boolean(material.unlit);\n\n if (material.pbrMetallicRoughness) {\n this.parsePbrMetallicRoughness(material.pbrMetallicRoughness);\n }\n if (material.normalTexture) {\n this.addTexture(material.normalTexture, 'pbr_normalSampler', 'HAS_NORMALMAP');\n\n const {scale = 1} = material.normalTexture;\n this.uniforms.normalScale = scale;\n }\n if (material.occlusionTexture) {\n this.addTexture(material.occlusionTexture, 'pbr_occlusionSampler', 'HAS_OCCLUSIONMAP');\n\n const {strength = 1} = material.occlusionTexture;\n this.uniforms.occlusionStrength = strength;\n }\n if (material.emissiveTexture) {\n this.addTexture(material.emissiveTexture, 'pbr_emissiveSampler', 'HAS_EMISSIVEMAP');\n this.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];\n }\n if (material.alphaMode === 'MASK') {\n const {alphaCutoff = 0.5} = material;\n this.defines.ALPHA_CUTOFF = true;\n this.uniforms.u_AlphaCutoff = alphaCutoff;\n } else if (material.alphaMode === 'BLEND') {\n log.warn('BLEND alphaMode might not work well because it requires mesh sorting')();\n Object.assign(this.parameters, {\n blend: true,\n blendEquation: GL.FUNC_ADD,\n blendFunc: [GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA, GL.ONE, GL.ONE_MINUS_SRC_ALPHA]\n });\n }\n }\n\n /** Parse GLTF material sub record *\n parsePbrMetallicRoughness(pbrMetallicRoughness) {\n if (pbrMetallicRoughness.baseColorTexture) {\n this.addTexture(\n pbrMetallicRoughness.baseColorTexture,\n 'pbr_baseColorSampler',\n 'HAS_BASECOLORMAP'\n );\n }\n this.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];\n\n if (pbrMetallicRoughness.metallicRoughnessTexture) {\n this.addTexture(\n pbrMetallicRoughness.metallicRoughnessTexture,\n 'pbr_metallicRoughnessSampler',\n 'HAS_METALROUGHNESSMAP'\n );\n }\n const {metallicFactor = 1, roughnessFactor = 1} = pbrMetallicRoughness;\n this.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];\n }\n\n /** Create a texture from a glTF texture/sampler/image combo and add it to bindings *\n addTexture(gltfTexture, name, define = null) {\n const parameters = gltfTexture?.texture?.sampler?.parameters || {};\n\n const image = gltfTexture.texture.source.image;\n let textureOptions;\n let specialTextureParameters = {};\n if (image.compressed) {\n textureOptions = image;\n specialTextureParameters = {\n [GL.TEXTURE_MIN_FILTER]: image.data.length > 1 ? GL.LINEAR_MIPMAP_NEAREST : GL.LINEAR\n };\n } else {\n // Texture2D accepts a promise that returns an image as data (Async Textures)\n textureOptions = {data: image};\n }\n\n const texture: Texture = this.device.createTexture({\n id: gltfTexture.name || gltfTexture.id,\n parameters: {\n ...parameters,\n ...specialTextureParameters\n },\n pixelStore: {\n [GL.UNPACK_FLIP_Y_WEBGL]: false\n },\n ...textureOptions\n });\n this.bindings[name] = texture;\n this.defineIfPresent(define, define);\n this.generatedTextures.push(texture);\n }\n}\n*/\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\n// TODO: convert in loaders.gl?\n\nimport type {SamplerProps} from '@luma.gl/core';\nimport {GL} from '@luma.gl/constants';\n\ntype GLTFSampler = {\n wrapS?: GL.CLAMP_TO_EDGE | GL.REPEAT | GL.MIRRORED_REPEAT;\n wrapT?: GL.CLAMP_TO_EDGE | GL.REPEAT | GL.MIRRORED_REPEAT;\n magFilter?: GL.NEAREST | GL.LINEAR;\n minFilter?:\n | GL.NEAREST\n | GL.LINEAR\n | GL.NEAREST_MIPMAP_NEAREST\n | GL.LINEAR_MIPMAP_NEAREST\n | GL.NEAREST_MIPMAP_LINEAR\n | GL.LINEAR_MIPMAP_LINEAR;\n};\n\nexport function convertSampler(gltfSampler: GLTFSampler): SamplerProps {\n return {\n addressModeU: convertSamplerWrapMode(gltfSampler.wrapS),\n addressModeV: convertSamplerWrapMode(gltfSampler.wrapT),\n magFilter: convertSamplerMagFilter(gltfSampler.magFilter),\n ...convertSamplerMinFilter(gltfSampler.minFilter)\n };\n}\n\nfunction convertSamplerWrapMode(\n mode: GL.CLAMP_TO_EDGE | GL.REPEAT | GL.MIRRORED_REPEAT | undefined\n): 'clamp-to-edge' | 'repeat' | 'mirror-repeat' | undefined {\n switch (mode) {\n case GL.CLAMP_TO_EDGE:\n return 'clamp-to-edge';\n case GL.REPEAT:\n return 'repeat';\n case GL.MIRRORED_REPEAT:\n return 'mirror-repeat';\n default:\n return undefined;\n }\n}\n\nfunction convertSamplerMagFilter(\n mode: GL.NEAREST | GL.LINEAR | undefined\n): 'nearest' | 'linear' | undefined {\n switch (mode) {\n case GL.NEAREST:\n return 'nearest';\n case GL.LINEAR:\n return 'linear';\n default:\n return undefined;\n }\n}\n\nfunction convertSamplerMinFilter(\n mode:\n | GL.NEAREST\n | GL.LINEAR\n | GL.NEAREST_MIPMAP_NEAREST\n | GL.LINEAR_MIPMAP_NEAREST\n | GL.NEAREST_MIPMAP_LINEAR\n | GL.LINEAR_MIPMAP_LINEAR\n | undefined\n): {minFilter?: 'nearest' | 'linear'; mipmapFilter?: 'nearest' | 'linear'} {\n switch (mode) {\n case GL.NEAREST:\n return {minFilter: 'nearest'};\n case GL.LINEAR:\n return {minFilter: 'linear'};\n case GL.NEAREST_MIPMAP_NEAREST:\n return {minFilter: 'nearest', mipmapFilter: 'nearest'};\n case GL.LINEAR_MIPMAP_NEAREST:\n return {minFilter: 'linear', mipmapFilter: 'nearest'};\n case GL.NEAREST_MIPMAP_LINEAR:\n return {minFilter: 'nearest', mipmapFilter: 'linear'};\n case GL.LINEAR_MIPMAP_LINEAR:\n return {minFilter: 'linear', mipmapFilter: 'linear'};\n default:\n return {};\n }\n}\n", "import {Matrix4} from '@math.gl/core';\nimport type {GLTFNodePostprocessed, GLTFPostprocessed} from '@loaders.gl/gltf';\nimport type {DirectionalLight, Light, PointLight} from '@luma.gl/shadertools';\n\n/** Parse KHR_lights_punctual extension into luma.gl light definitions */\nexport function parseGLTFLights(gltf: GLTFPostprocessed): Light[] {\n const lightDefs = gltf.extensions?.['KHR_lights_punctual']?.['lights'];\n if (!lightDefs || !Array.isArray(lightDefs) || lightDefs.length === 0) {\n return [];\n }\n\n const lights: Light[] = [];\n\n for (const node of gltf.nodes || []) {\n const nodeLight = node.extensions?.KHR_lights_punctual;\n if (!nodeLight || typeof nodeLight.light !== 'number') {\n // eslint-disable-next-line no-continue\n continue;\n }\n const gltfLight = lightDefs[nodeLight.light];\n if (!gltfLight) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n const color = (gltfLight.color || [1, 1, 1]) as [number, number, number];\n const intensity = gltfLight.intensity ?? 1;\n const range = gltfLight.range;\n\n switch (gltfLight.type) {\n case 'directional':\n lights.push(parseDirectionalLight(node, color, intensity));\n break;\n case 'point':\n lights.push(parsePointLight(node, color, intensity, range));\n break;\n case 'spot':\n lights.push(parsePointLight(node, color, intensity, range));\n break;\n default:\n // Unsupported light type\n break;\n }\n }\n\n return lights;\n}\n\nfunction parsePointLight(\n node: GLTFNodePostprocessed,\n color: [number, number, number],\n intensity: number,\n range?: number\n): PointLight {\n const position: Readonly<[number, number, number]> = node.translation\n ? ([...node.translation] as [number, number, number])\n : ([0, 0, 0] as [number, number, number]);\n\n let attenuation: Readonly<[number, number, number]> = [1, 0, 0];\n if (range !== undefined && range > 0) {\n attenuation = [1, 0, 1 / (range * range)] as [number, number, number];\n }\n\n return {\n type: 'point',\n position,\n color,\n intensity,\n attenuation\n };\n}\n\nfunction parseDirectionalLight(\n node: GLTFNodePostprocessed,\n color: [number, number, number],\n intensity: number\n): DirectionalLight {\n let direction: [number, number, number] = [0, 0, -1];\n\n if (node.rotation) {\n const orientation = new Matrix4().fromQuaternion(node.rotation);\n direction = orientation.transformDirection([0, 0, -1]) as [number, number, number];\n }\n\n return {\n type: 'directional',\n direction,\n color,\n intensity\n };\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {Device, type PrimitiveTopology} from '@luma.gl/core';\nimport {Geometry, GeometryAttribute, GroupNode, ModelNode, type ModelProps} from '@luma.gl/engine';\nimport {Matrix4} from '@math.gl/core';\nimport {\n type GLTFMeshPostprocessed,\n type GLTFNodePostprocessed,\n type GLTFPostprocessed\n} from '@loaders.gl/gltf';\nimport {type GLTFScenePostprocessed} from '@loaders.gl/gltf/dist/lib/types/gltf-postprocessed-schema';\n\nimport {type PBREnvironment} from '../pbr/pbr-environment';\nimport {convertGLDrawModeToTopology} from '../webgl-to-webgpu/convert-webgl-topology';\nimport {createGLTFModel} from '../gltf/create-gltf-model';\n\nimport {parsePBRMaterial} from './parse-pbr-material';\n\nexport type ParseGLTFOptions = {\n modelOptions?: Partial<ModelProps>;\n pbrDebug?: boolean;\n imageBasedLightingEnvironment?: PBREnvironment;\n lights?: boolean;\n useTangents?: boolean;\n};\n\nconst defaultOptions: Required<ParseGLTFOptions> = {\n modelOptions: {},\n pbrDebug: false,\n imageBasedLightingEnvironment: undefined!,\n lights: true,\n useTangents: false\n};\n\n/**\n * GLTF instantiator for luma.gl\n * Walks the parsed and resolved glTF structure and builds a luma.gl scenegraph\n */\nexport function parseGLTF(\n device: Device,\n gltf: GLTFPostprocessed,\n options_: ParseGLTFOptions = {}\n): GroupNode[] {\n const options = {...defaultOptions, ...options_};\n const sceneNodes = gltf.scenes.map(gltfScene =>\n createScene(device, gltfScene, gltf.nodes, options)\n );\n return sceneNodes;\n}\n\nfunction createScene(\n device: Device,\n gltfScene: GLTFScenePostprocessed,\n gltfNodes: GLTFNodePostprocessed[],\n options: Required<ParseGLTFOptions>\n): GroupNode {\n const gltfSceneNodes = gltfScene.nodes || [];\n const nodes = gltfSceneNodes.map(node => createNode(device, node, gltfNodes, options));\n const sceneNode = new GroupNode({\n id: gltfScene.name || gltfScene.id,\n children: nodes\n });\n return sceneNode;\n}\n\nfunction createNode(\n device: Device,\n gltfNode: GLTFNodePostprocessed & {_node?: GroupNode},\n gltfNodes: GLTFNodePostprocessed[],\n options: Required<ParseGLTFOptions>\n): GroupNode {\n if (!gltfNode._node) {\n const gltfChildren = gltfNode.children || [];\n const children = gltfChildren.map(child => createNode(device, child, gltfNodes, options));\n\n // Node can have children nodes and meshes at the same time\n if (gltfNode.mesh) {\n children.push(createMesh(device, gltfNode.mesh, options));\n }\n\n const node = new GroupNode({\n id: gltfNode.name || gltfNode.id,\n children\n });\n\n if (gltfNode.matrix) {\n node.setMatrix(gltfNode.matrix);\n } else {\n node.matrix.identity();\n\n if (gltfNode.translation) {\n node.matrix.translate(gltfNode.translation);\n }\n\n if (gltfNode.rotation) {\n const rotationMatrix = new Matrix4().fromQuaternion(gltfNode.rotation);\n node.matrix.multiplyRight(rotationMatrix);\n }\n\n if (gltfNode.scale) {\n node.matrix.scale(gltfNode.scale);\n }\n }\n gltfNode._node = node;\n }\n\n // Copy _node so that gltf-animator can access\n const topLevelNode = gltfNodes.find(node => node.id === gltfNode.id) as any;\n topLevelNode._node = gltfNode._node;\n\n return gltfNode._node;\n}\n\nfunction createMesh(\n device: Device,\n gltfMesh: GLTFMeshPostprocessed & {_mesh?: GroupNode},\n options: Required<ParseGLTFOptions>\n): GroupNode {\n // TODO: avoid changing the gltf\n if (!gltfMesh._mesh) {\n const gltfPrimitives = gltfMesh.primitives || [];\n const primitives = gltfPrimitives.map((gltfPrimitive, i) =>\n createPrimitive(device, gltfPrimitive, i, gltfMesh, options)\n );\n const mesh = new GroupNode({\n id: gltfMesh.name || gltfMesh.id,\n children: primitives\n });\n gltfMesh._mesh = mesh;\n }\n\n return gltfMesh._mesh;\n}\n\nfunction createPrimitive(\n device: Device,\n gltfPrimitive: any,\n i: number,\n gltfMesh: GLTFMeshPostprocessed,\n options: Required<ParseGLTFOptions>\n): ModelNode {\n const id = gltfPrimitive.name || `${gltfMesh.name || gltfMesh.id}-primitive-${i}`;\n const topology = convertGLDrawModeToTopology(gltfPrimitive.mode || 4);\n const vertexCount = gltfPrimitive.indices\n ? gltfPrimitive.indices.count\n : getVertexCount(gltfPrimitive.attributes);\n\n const geometry = createGeometry(id, gltfPrimitive, topology);\n\n const parsedPPBRMaterial = parsePBRMaterial(\n device,\n gltfPrimitive.material,\n geometry.attributes,\n options\n );\n\n const modelNode = createGLTFModel(device, {\n id,\n geometry: createGeometry(id, gltfPrimitive, topology),\n parsedPPBRMaterial,\n modelOptions: options.modelOptions,\n vertexCount\n });\n\n modelNode.bounds = [gltfPrimitive.attributes.POSITION.min, gltfPrimitive.attributes.POSITION.max];\n // TODO this holds on to all the CPU side texture and attribute data\n // modelNode.material = gltfPrimitive.material;\n\n return modelNode;\n}\n\nfunction getVertexCount(attributes: any) {\n throw new Error('getVertexCount not implemented');\n}\n\nfunction createGeometry(id: string, gltfPrimitive: any, topology: PrimitiveTopology): Geometry {\n const attributes: Record<string, GeometryAttribute> = {};\n for (const [attributeName, attribute] of Object.entries(gltfPrimitive.attributes)) {\n const {components, size, value} = attribute as GeometryAttribute;\n\n attributes[attributeName] = {size: size ?? components, value};\n }\n\n return new Geometry({\n id,\n topology,\n indices: gltfPrimitive.indices.value,\n attributes\n });\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {PrimitiveTopology} from '@luma.gl/core';\n\n// NOTE: Modules other than `@luma.gl/webgl` should not import `GL` from\n// `@luma.gl/constants`. Locally we use `GLEnum` instead of `GL` to avoid\n// conflicts with the `babel-plugin-inline-webgl-constants` plugin.\n// eslint-disable-next-line no-shadow\nexport enum GLEnum {\n POINTS = 0x0,\n LINES = 0x1,\n LINE_LOOP = 0x2,\n LINE_STRIP = 0x3,\n TRIANGLES = 0x4,\n TRIANGLE_STRIP = 0x5,\n TRIANGLE_FAN = 0x6\n}\n\nexport function convertGLDrawModeToTopology(\n drawMode:\n | GLEnum.POINTS\n | GLEnum.LINES\n | GLEnum.LINE_STRIP\n | GLEnum.LINE_LOOP\n | GLEnum.TRIANGLES\n | GLEnum.TRIANGLE_STRIP\n | GLEnum.TRIANGLE_FAN\n): PrimitiveTopology {\n // prettier-ignore\n switch (drawMode) {\n case GLEnum.POINTS: return 'point-list';\n case GLEnum.LINES: return 'line-list';\n case GLEnum.LINE_STRIP: return 'line-strip';\n case GLEnum.TRIANGLES: return 'triangle-list';\n case GLEnum.TRIANGLE_STRIP: return 'triangle-strip';\n default: throw new Error(String(drawMode));\n }\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {Device, type RenderPipelineParameters, log} from '@luma.gl/core';\nimport {pbrMaterial, ShaderModule} from '@luma.gl/shadertools';\nimport {Geometry, Model, ModelNode, type ModelProps} from '@luma.gl/engine';\nimport {type ParsedPBRMaterial} from '../pbr/pbr-material';\n\nconst SHADER = /* WGSL */ `\nlayout(0) positions: vec4; // in vec4 POSITION;\n\n #ifdef HAS_NORMALS\n in vec4 normals; // in vec4 NORMAL;\n #endif\n\n #ifdef HAS_TANGENTS\n in vec4 TANGENT;\n #endif\n\n #ifdef HAS_UV\n // in vec2 TEXCOORD_0;\n in vec2 texCoords;\n #endif\n\n@vertex\n void main(void) {\n vec4 _NORMAL = vec4(0.);\n vec4 _TANGENT = vec4(0.);\n vec2 _TEXCOORD_0 = vec2(0.);\n\n #ifdef HAS_NORMALS\n _NORMAL = normals;\n #endif\n\n #ifdef HAS_TANGENTS\n _TANGENT = TANGENT;\n #endif\n\n #ifdef HAS_UV\n _TEXCOORD_0 = texCoords;\n #endif\n\n pbr_setPositionNormalTangentUV(positions, _NORMAL, _TANGENT, _TEXCOORD_0);\n gl_Position = u_MVPMatrix * positions;\n }\n\n@fragment\n out vec4 fragmentColor;\n\n void main(void) {\n vec3 pos = pbr_vPosition;\n fragmentColor = pbr_filterColor(vec4(1.0));\n }\n`;\n\n// TODO rename attributes to POSITION/NORMAL etc\n// See gpu-geometry.ts: getAttributeBuffersFromGeometry()\nconst vs = /* glsl */ `\\\n#version 300 es\n\n // in vec4 POSITION;\n in vec4 positions;\n\n #ifdef HAS_NORMALS\n // in vec4 NORMAL;\n in vec4 normals;\n #endif\n\n #ifdef HAS_TANGENTS\n in vec4 TANGENT;\n #endif\n\n #ifdef HAS_UV\n // in vec2 TEXCOORD_0;\n in vec2 texCoords;\n #endif\n\n void main(void) {\n vec4 _NORMAL = vec4(0.);\n vec4 _TANGENT = vec4(0.);\n vec2 _TEXCOORD_0 = vec2(0.);\n\n #ifdef HAS_NORMALS\n _NORMAL = normals;\n #endif\n\n #ifdef HAS_TANGENTS\n _TANGENT = TANGENT;\n #endif\n\n #ifdef HAS_UV\n _TEXCOORD_0 = texCoords;\n #endif\n\n pbr_setPositionNormalTangentUV(positions, _NORMAL, _TANGENT, _TEXCOORD_0);\n gl_Position = pbrProjection.modelViewProjectionMatrix * positions;\n }\n`;\n\nconst fs = /* glsl */ `\\\n#version 300 es\n out vec4 fragmentColor;\n\n void main(void) {\n vec3 pos = pbr_vPosition;\n fragmentColor = pbr_filterColor(vec4(1.0));\n }\n`;\n\nexport type CreateGLTFModelOptions = {\n id?: string;\n vertexCount?: number;\n geometry: Geometry;\n parsedPPBRMaterial: ParsedPBRMaterial;\n modelOptions?: Partial<ModelProps>;\n};\n\n/** Creates a luma.gl Model from GLTF data*/\nexport function createGLTFModel(device: Device, options: CreateGLTFModelOptions): ModelNode {\n const {id, geometry, parsedPPBRMaterial, vertexCount, modelOptions = {}} = options;\n\n log.info(4, 'createGLTFModel defines: ', parsedPPBRMaterial.defines)();\n\n // Calculate managedResources\n // TODO: Implement resource management logic that will\n // not deallocate resources/textures/buffers that are shared\n const managedResources: any[] = [];\n // managedResources.push(...parsedMaterial.generatedTextures);\n // managedResources.push(...Object.values(attributes).map((attribute) => attribute.buffer));\n\n const parameters: RenderPipelineParameters = {\n depthWriteEnabled: true,\n depthCompare: 'less',\n depthFormat: 'depth24plus',\n cullMode: 'back'\n };\n\n const modelProps: ModelProps = {\n id,\n source: SHADER,\n vs,\n fs,\n geometry,\n topology: geometry.topology,\n vertexCount,\n modules: [pbrMaterial as unknown as ShaderModule],\n ...modelOptions,\n\n defines: {...parsedPPBRMaterial.defines, ...modelOptions.defines},\n parameters: {...parameters, ...parsedPPBRMaterial.parameters, ...modelOptions.parameters}\n };\n\n const model = new Model(device, modelProps);\n\n const {camera, ...pbrMaterialProps} = {\n ...parsedPPBRMaterial.uniforms,\n ...modelOptions.uniforms,\n ...parsedPPBRMaterial.bindings,\n ...modelOptions.bindings\n };\n\n model.shaderInputs.setProps({pbrMaterial: pbrMaterialProps, pbrProjection: {camera}});\n return new ModelNode({managedResources, model});\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {GLTFNodePostprocessed} from '@loaders.gl/gltf';\nimport {log} from '@luma.gl/core';\nimport {GroupNode} from '@luma.gl/engine';\nimport {Matrix4} from '@math.gl/core';\nimport {GLTFAnimation} from './animations/animations';\nimport {interpolate} from './animations/interpolate';\n\ntype GLTFSingleAnimatorProps = {\n animation: GLTFAnimation;\n startTime?: number;\n playing?: boolean;\n speed?: number;\n};\n\nclass GLTFSingleAnimator {\n animation: GLTFAnimation;\n startTime: number = 0;\n playing: boolean = true;\n speed: number = 1;\n\n constructor(props: GLTFSingleAnimatorProps) {\n this.animation = props.animation;\n this.animation.name ||= 'unnamed';\n Object.assign(this, props);\n }\n\n setTime(timeMs: number) {\n if (!this.playing) {\n return;\n }\n\n const absTime = timeMs / 1000;\n const time = (absTime - this.startTime) * this.speed;\n\n this.animation.channels.forEach(({sampler, target, path}) => {\n interpolate(time, sampler, target, path);\n applyTranslationRotationScale(target, (target as any)._node as GroupNode);\n });\n }\n}\n\nexport type GLTFAnimatorProps = {\n animations: GLTFAnimation[];\n};\n\nexport class GLTFAnimator {\n animations: GLTFSingleAnimator[];\n\n constructor(props: GLTFAnimatorProps) {\n this.animations = props.animations.map((animation, index) => {\n const name = animation.name || `Animation-${index}`;\n return new GLTFSingleAnimator({\n animation: {name, channels: animation.channels}\n });\n });\n }\n\n /** @deprecated Use .setTime(). Will be removed (deck.gl is using this) */\n animate(time: number): void {\n log.warn('GLTFAnimator#animate is deprecated. Use GLTFAnimator#setTime instead')();\n this.setTime(time);\n }\n\n setTime(time: number): void {\n this.animations.forEach(animation => animation.setTime(time));\n }\n\n getAnimations() {\n return this.animations;\n }\n}\n\n// TODO: share with GLTFInstantiator\nconst scratchMatrix = new Matrix4();\n\nfunction applyTranslationRotationScale(gltfNode: GLTFNodePostprocessed, node: GroupNode) {\n node.matrix.identity();\n\n if (gltfNode.translation) {\n node.matrix.translate(gltfNode.translation);\n }\n\n if (gltfNode.rotation) {\n const rotationMatrix = scratchMatrix.fromQuaternion(gltfNode.rotation);\n node.matrix.multiplyRight(rotationMatrix);\n }\n\n if (gltfNode.scale) {\n node.matrix.scale(gltfNode.scale);\n }\n}\n", "import {GLTFNodePostprocessed} from '@loaders.gl/gltf';\nimport {log} from '@luma.gl/core';\nimport {Quaternion} from '@math.gl/core';\nimport {GLTFAnimationChannel, GLTFAnimationSampler} from './animations';\n\nconst scratchQuaternion = new Quaternion();\n\nexport function interpolate(\n time: number,\n {input, interpolation, output}: GLTFAnimationSampler,\n target: GLTFNodePostprocessed,\n path: GLTFAnimationChannel['path']\n) {\n const maxTime = input[input.length - 1];\n const animationTime = time % maxTime;\n\n const nextIndex = input.findIndex(t => t >= animationTime);\n const previousIndex = Math.max(0, nextIndex - 1);\n\n if (!Array.isArray(target[path])) {\n switch (path) {\n case 'translation':\n target[path] = [0, 0, 0];\n break;\n\n case 'rotation':\n target[path] = [0, 0, 0, 1];\n break;\n\n case 'scale':\n target[path] = [1, 1, 1];\n break;\n\n default:\n log.warn(`Bad animation path ${path}`)();\n }\n }\n\n // assert(target[path].length === output[previousIndex].length);\n const previousTime = input[previousIndex];\n const nextTime = input[nextIndex];\n\n switch (interpolation) {\n case 'STEP':\n stepInterpolate(target, path, output[previousIndex] as number[]);\n break;\n\n case 'LINEAR':\n if (nextTime > previousTime) {\n const ratio = (animationTime - previousTime) / (nextTime - previousTime);\n linearInterpolate(\n target,\n path,\n output[previousIndex] as number[],\n output[nextIndex] as number[],\n ratio\n );\n }\n break;\n\n case 'CUBICSPLINE':\n if (nextTime > previousTime) {\n const ratio = (animationTime - previousTime) / (nextTime - previousTime);\n const tDiff = nextTime - previousTime;\n\n const p0 = output[3 * previousIndex + 1] as number[];\n const outTangent0 = output[3 * previousIndex + 2] as number[];\n const inTangent1 = output[3 * nextIndex + 0] as number[];\n const p1 = output[3 * nextIndex + 1] as number[];\n\n cubicsplineInterpolate(target, path, {p0, outTangent0, inTangent1, p1, tDiff, ratio});\n }\n break;\n\n default:\n log.warn(`Interpolation ${interpolation} not supported`)();\n break;\n }\n}\n\nfunction linearInterpolate(\n target: GLTFNodePostprocessed,\n path: GLTFAnimationChannel['path'],\n start: number[],\n stop: number[],\n ratio: number\n) {\n if (!target[path]) {\n throw new Error();\n }\n\n if (path === 'rotation') {\n // SLERP when path is rotation\n scratchQuaternion.slerp({start, target: stop, ratio});\n for (let i = 0; i < scratchQuaternion.length; i++) {\n target[path][i] = scratchQuaternion[i];\n }\n } else {\n // regular interpolation\n for (let i = 0; i < start.length; i++) {\n target[path][i] = ratio * stop[i] + (1 - ratio) * start[i];\n }\n }\n}\n\nfunction cubicsplineInterpolate(\n target: GLTFNodePostprocessed,\n path: GLTFAnimationChannel['path'],\n {\n p0,\n outTangent0,\n inTangent1,\n p1,\n tDiff,\n ratio: t\n }: {\n p0: number[];\n outTangent0: number[];\n inTangent1: number[];\n p1: number[];\n tDiff: number;\n ratio: number;\n }\n) {\n if (!target[path]) {\n throw new Error();\n }\n\n // TODO: Quaternion might need normalization\n for (let i = 0; i < target[path].length; i++) {\n const m0 = outTangent0[i] * tDiff;\n const m1 = inTangent1[i] * tDiff;\n target[path][i] =\n (2 * Math.pow(t, 3) - 3 * Math.pow(t, 2) + 1) * p0[i] +\n (Math.pow(t, 3) - 2 * Math.pow(t, 2) + t) * m0 +\n (-2 * Math.pow(t, 3) + 3 * Math.pow(t, 2)) * p1[i] +\n (Math.pow(t, 3) - Math.pow(t, 2)) * m1;\n }\n}\n\nfunction stepInterpolate(\n target: GLTFNodePostprocessed,\n path: GLTFAnimationChannel['path'],\n value: number[]\n) {\n if (!target[path]) {\n throw new Error();\n }\n\n for (let i = 0; i < value.length; i++) {\n target[path][i] = value[i];\n }\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\n// TODO: convert in loaders.gl?\nimport type {TypedArray} from '@math.gl/types';\n\nexport const ATTRIBUTE_TYPE_TO_COMPONENTS: Record<string, number> = {\n SCALAR: 1,\n VEC2: 2,\n VEC3: 3,\n VEC4: 4,\n MAT2: 4,\n MAT3: 9,\n MAT4: 16\n};\n\nexport const ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY: Record<number, any> = {\n 5120: Int8Array,\n 5121: Uint8Array,\n 5122: Int16Array,\n 5123: Uint16Array,\n 5125: Uint32Array,\n 5126: Float32Array\n};\n\ntype GLTFAccessor = {\n componentType: number;\n type: string;\n count: number;\n bufferView?: {data: {buffer: ArrayBuffer; byteOffset?: number}};\n byteOffset?: number;\n};\n\nexport function accessorToTypedArray(accessor: GLTFAccessor): {\n typedArray: TypedArray;\n components: number;\n} {\n const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[accessor.componentType];\n const components = ATTRIBUTE_TYPE_TO_COMPONENTS[accessor.type];\n const length = components * accessor.count;\n const {buffer, byteOffset = 0} = accessor.bufferView?.data ?? {};\n\n const typedArray = new ArrayType(buffer, byteOffset + (accessor.byteOffset || 0), length);\n\n return {typedArray, components};\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {type GLTFAccessorPostprocessed, type GLTFPostprocessed} from '@loaders.gl/gltf';\nimport {\n type GLTFAnimation,\n type GLTFAnimationChannel,\n type GLTFAnimationSampler\n} from '../gltf/animations/animations';\n\nimport {accessorToTypedArray} from '..//webgl-to-webgpu/convert-webgl-attribute';\n\nexport function parseGLTFAnimations(gltf: GLTFPostprocessed): GLTFAnimation[] {\n const gltfAnimations = gltf.animations || [];\n return gltfAnimations.map((animation, index) => {\n const name = animation.name || `Animation-${index}`;\n const samplers: GLTFAnimationSampler[] = animation.samplers.map(\n ({input, interpolation = 'LINEAR', output}) => ({\n input: accessorToJsArray(gltf.accessors[input]) as number[],\n interpolation,\n output: accessorToJsArray(gltf.accessors[output])\n })\n );\n const channels: GLTFAnimationChannel[] = animation.channels.map(({sampler, target}) => ({\n sampler: samplers[sampler],\n target: gltf.nodes[target.node ?? 0],\n path: target.path as GLTFAnimationChannel['path']\n }));\n return {name, channels};\n });\n}\n\n//\n\nfunction accessorToJsArray(\n accessor: GLTFAccessorPostprocessed & {_animation?: number[] | number[][]}\n): number[] | number[][] {\n if (!accessor._animation) {\n const {typedArray: array, components} = accessorToTypedArray(accessor);\n\n if (components === 1) {\n accessor._animation = Array.from(array);\n } else {\n // Slice array\n const slicedArray: number[][] = [];\n for (let i = 0; i < array.length; i += components) {\n slicedArray.push(Array.from(array.slice(i, i + components)));\n }\n accessor._animation = slicedArray;\n }\n }\n\n return accessor._animation;\n}\n", "/** Deeply copies a JS data structure */\nexport function deepCopy(object: any): any {\n // don't copy binary data\n if (\n ArrayBuffer.isView(object) ||\n object instanceof ArrayBuffer ||\n object instanceof ImageBitmap\n ) {\n return object;\n }\n if (Array.isArray(object)) {\n return object.map(deepCopy);\n }\n if (object && typeof object === 'object') {\n const result: typeof object = {};\n for (const key in object) {\n result[key] = deepCopy(object[key]);\n }\n return result;\n }\n return object;\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {Device} from '@luma.gl/core';\nimport {GroupNode} from '@luma.gl/engine';\nimport {GLTFPostprocessed} from '@loaders.gl/gltf';\nimport {Light} from '@luma.gl/shadertools';\nimport {parseGLTF, type ParseGLTFOptions} from '../parsers/parse-gltf';\nimport {parseGLTFLights} from '../parsers/parse-gltf-lights';\nimport {GLTFAnimator} from './gltf-animator';\nimport {parseGLTFAnimations} from '../parsers/parse-gltf-animations';\nimport {deepCopy} from '../utils/deep-copy';\n\nexport function createScenegraphsFromGLTF(\n device: Device,\n gltf: GLTFPostprocessed,\n options?: ParseGLTFOptions\n): {\n scenes: GroupNode[];\n animator: GLTFAnimator;\n lights: Light[];\n} {\n gltf = deepCopy(gltf);\n const scenes = parseGLTF(device, gltf, options);\n // Note: There is a nasty dependency on injected nodes in the glTF\n const animations = parseGLTFAnimations(gltf);\n const animator = new GLTFAnimator({animations});\n const lights = parseGLTFLights(gltf);\n return {scenes, animator, lights};\n}\n"],
5
- "mappings": "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",
6
- "names": ["import_constants", "import_core", "import_engine", "import_core", "GLEnum", "import_core", "import_engine", "import_core", "import_core"]
3
+ "sources": ["../src/index.ts", "../src/pbr/pbr-environment.ts", "../src/parsers/parse-pbr-material.ts", "../src/webgl-to-webgpu/convert-webgl-sampler.ts", "../src/parsers/parse-gltf-lights.ts", "../src/parsers/parse-gltf.ts", "../src/webgl-to-webgpu/convert-webgl-topology.ts", "../src/gltf/create-gltf-model.ts", "../src/gltf/gltf-animator.ts", "../src/gltf/animations/interpolate.ts", "../src/webgl-to-webgpu/convert-webgl-attribute.ts", "../src/parsers/parse-gltf-animations.ts", "../src/gltf/create-scenegraph-from-gltf.ts"],
4
+ "sourcesContent": ["// luma.gl, MIT license\n\nexport {loadPBREnvironment, type PBREnvironment} from './pbr/pbr-environment';\nexport {type ParsedPBRMaterial} from './pbr/pbr-material';\nexport {parsePBRMaterial, type ParsePBRMaterialOptions} from './parsers/parse-pbr-material';\nexport {parseGLTFLights} from './parsers/parse-gltf-lights';\n\n// glTF Scenegraph Instantiator\nexport {createScenegraphsFromGLTF, type GLTFScenegraphs} from './gltf/create-scenegraph-from-gltf';\nexport {GLTFAnimator} from './gltf/gltf-animator';\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {Device, SamplerProps} from '@luma.gl/core';\nimport {DynamicTexture} from '@luma.gl/engine';\nimport {loadImageTexture} from '@loaders.gl/textures';\n\n/** Environment textures for PBR module */\nexport type PBREnvironment = {\n /** Bi-directional Reflectance Distribution Function (BRDF) lookup table */\n brdfLutTexture: DynamicTexture;\n /** Diffuse irradiance cubemap. */\n diffuseEnvSampler: DynamicTexture;\n /** Specular reflection cubemap with mip chain. */\n specularEnvSampler: DynamicTexture;\n};\n\n/** Configuration used to load an image-based lighting environment. */\nexport type PBREnvironmentProps = {\n /** URL of the BRDF lookup texture. */\n brdfLutUrl: string;\n /** Callback that returns the URL for a diffuse or specular cubemap face and mip level. */\n getTexUrl: (name: string, dir: number, level: number) => string;\n /** Number of mip levels in the specular environment map. */\n specularMipLevels?: number;\n};\n\n/** Loads textures for PBR environment */\nexport function loadPBREnvironment(device: Device, props: PBREnvironmentProps): PBREnvironment {\n const brdfLutTexture = new DynamicTexture(device, {\n id: 'brdfLUT',\n sampler: {\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n minFilter: 'linear',\n magFilter: 'linear'\n } as const satisfies SamplerProps,\n // Texture accepts a promise that returns an image as data (Async Textures)\n data: loadImageTexture(props.brdfLutUrl)\n });\n\n const diffuseEnvSampler = makeCube(device, {\n id: 'DiffuseEnvSampler',\n getTextureForFace: dir => loadImageTexture(props.getTexUrl('diffuse', dir, 0)),\n sampler: {\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n minFilter: 'linear',\n magFilter: 'linear'\n } as const satisfies SamplerProps\n });\n\n const specularEnvSampler = makeCube(device, {\n id: 'SpecularEnvSampler',\n getTextureForFace: (dir: number) => {\n const imageArray: Promise<any>[] = [];\n // @ts-ignore\n for (let lod = 0; lod <= props.specularMipLevels - 1; lod++) {\n imageArray.push(loadImageTexture(props.getTexUrl('specular', dir, lod)));\n }\n return imageArray;\n },\n sampler: {\n addressModeU: 'clamp-to-edge',\n addressModeV: 'clamp-to-edge',\n minFilter: 'linear', // [GL.TEXTURE_MIN_FILTER]: GL.LINEAR_MIPMAP_LINEAR,\n magFilter: 'linear'\n } as const satisfies SamplerProps\n });\n\n return {\n brdfLutTexture,\n diffuseEnvSampler,\n specularEnvSampler\n };\n}\n\n// TODO put somewhere common\nconst FACES = [0, 1, 2, 3, 4, 5];\n\n/** Construction props for an asynchronously loaded cubemap. */\nfunction makeCube(\n device: Device,\n {\n id,\n getTextureForFace,\n sampler\n }: {\n /** Debug id assigned to the created texture. */\n id: string;\n /** Returns the image promise or mip-array promises for one cubemap face. */\n getTextureForFace: (dir: number) => Promise<any> | Promise<any>[];\n /** Sampler configuration shared across faces. */\n sampler: SamplerProps;\n }\n): DynamicTexture {\n const data = {};\n FACES.forEach(face => {\n // @ts-ignore TODO\n data[String(face)] = getTextureForFace(face);\n });\n return new DynamicTexture(device, {\n id,\n dimension: 'cube',\n mipmaps: false,\n sampler,\n // @ts-expect-error\n data\n });\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport type {Device, SamplerProps, TextureFormat, TypedArray} from '@luma.gl/core';\nimport {Texture, log, textureFormatDecoder} from '@luma.gl/core';\nimport type {GLTFSampler} from '@loaders.gl/gltf';\nimport {GL} from '@luma.gl/constants';\n\nimport {type ParsedPBRMaterial} from '../pbr/pbr-material';\nimport {type PBREnvironment} from '../pbr/pbr-environment';\nimport {type PBRMaterialBindings} from '@luma.gl/shadertools';\nimport {convertSampler} from '../webgl-to-webgpu/convert-webgl-sampler';\n\n// TODO - synchronize the GLTF... types with loaders.gl\n// TODO - remove the glParameters, use only parameters\n\n/* eslint-disable camelcase */\n\ntype GLTFTexture = {\n id: string;\n texture: {source: {image: any}; sampler: {parameters: any}};\n uniformName?: string;\n // is this on all textures?\n scale?: number;\n // is this on all textures?\n strength?: number;\n};\n\ntype GLTFPBRMetallicRoughness = {\n baseColorTexture?: GLTFTexture;\n baseColorFactor?: [number, number, number, number];\n metallicRoughnessTexture?: GLTFTexture;\n metallicFactor?: number;\n roughnessFactor?: number;\n};\n\ntype GLTFPBRMaterial = {\n unlit?: boolean;\n pbrMetallicRoughness?: GLTFPBRMetallicRoughness;\n normalTexture?: GLTFTexture;\n occlusionTexture?: GLTFTexture;\n emissiveTexture?: GLTFTexture;\n emissiveFactor?: [number, number, number];\n alphaMode?: 'MASK' | 'BLEND';\n alphaCutoff?: number;\n};\n\nexport type ParsePBRMaterialOptions = {\n /** Debug PBR shader */\n pbrDebug?: boolean;\n /** Enable lights */\n lights?: any;\n /** Use tangents */\n useTangents?: boolean;\n /** provide an image based (texture cube) lighting environment */\n imageBasedLightingEnvironment?: PBREnvironment;\n};\n\n/**\n * Parses a GLTF material definition into uniforms and parameters for the PBR shader module\n */\nexport function parsePBRMaterial(\n device: Device,\n material: GLTFPBRMaterial,\n attributes: Record<string, any>,\n options: ParsePBRMaterialOptions\n): ParsedPBRMaterial {\n const parsedMaterial: ParsedPBRMaterial = {\n defines: {\n // TODO: Use EXT_sRGB if available (Standard in WebGL 2.0)\n MANUAL_SRGB: true,\n SRGB_FAST_APPROXIMATION: true\n },\n bindings: {},\n uniforms: {\n // TODO: find better values?\n camera: [0, 0, 0], // Model should override\n\n metallicRoughnessValues: [1, 1] // Default is 1 and 1\n },\n parameters: {},\n glParameters: {},\n generatedTextures: []\n };\n\n // TODO - always available\n parsedMaterial.defines['USE_TEX_LOD'] = true;\n\n const {imageBasedLightingEnvironment} = options;\n if (imageBasedLightingEnvironment) {\n parsedMaterial.bindings.pbr_diffuseEnvSampler =\n imageBasedLightingEnvironment.diffuseEnvSampler.texture;\n parsedMaterial.bindings.pbr_specularEnvSampler =\n imageBasedLightingEnvironment.specularEnvSampler.texture;\n parsedMaterial.bindings.pbr_BrdfLUT = imageBasedLightingEnvironment.brdfLutTexture.texture;\n parsedMaterial.uniforms.scaleIBLAmbient = [1, 1];\n }\n\n if (options?.pbrDebug) {\n parsedMaterial.defines['PBR_DEBUG'] = true;\n // Override final color for reference app visualization of various parameters in the lighting equation.\n parsedMaterial.uniforms.scaleDiffBaseMR = [0, 0, 0, 0];\n parsedMaterial.uniforms.scaleFGDSpec = [0, 0, 0, 0];\n }\n\n if (attributes['NORMAL']) parsedMaterial.defines['HAS_NORMALS'] = true;\n if (attributes['TANGENT'] && options?.useTangents) parsedMaterial.defines['HAS_TANGENTS'] = true;\n if (attributes['TEXCOORD_0']) parsedMaterial.defines['HAS_UV'] = true;\n if (attributes['JOINTS_0'] && attributes['WEIGHTS_0']) parsedMaterial.defines['HAS_SKIN'] = true;\n if (attributes['COLOR_0']) parsedMaterial.defines['HAS_COLORS'] = true;\n\n if (options?.imageBasedLightingEnvironment) parsedMaterial.defines['USE_IBL'] = true;\n if (options?.lights) parsedMaterial.defines['USE_LIGHTS'] = true;\n\n if (material) {\n parseMaterial(device, material, parsedMaterial);\n }\n\n return parsedMaterial;\n}\n\n/** Parse GLTF material record */\nfunction parseMaterial(\n device: Device,\n material: GLTFPBRMaterial,\n parsedMaterial: ParsedPBRMaterial\n): void {\n parsedMaterial.uniforms.unlit = Boolean(material.unlit);\n\n if (material.pbrMetallicRoughness) {\n parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial);\n }\n if (material.normalTexture) {\n addTexture(\n device,\n material.normalTexture,\n 'pbr_normalSampler',\n 'HAS_NORMALMAP',\n parsedMaterial\n );\n\n const {scale = 1} = material.normalTexture;\n parsedMaterial.uniforms.normalScale = scale;\n }\n if (material.occlusionTexture) {\n addTexture(\n device,\n material.occlusionTexture,\n 'pbr_occlusionSampler',\n 'HAS_OCCLUSIONMAP',\n parsedMaterial\n );\n\n const {strength = 1} = material.occlusionTexture;\n parsedMaterial.uniforms.occlusionStrength = strength;\n }\n if (material.emissiveTexture) {\n addTexture(\n device,\n material.emissiveTexture,\n 'pbr_emissiveSampler',\n 'HAS_EMISSIVEMAP',\n parsedMaterial\n );\n parsedMaterial.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];\n }\n\n switch (material.alphaMode || 'MASK') {\n case 'MASK':\n const {alphaCutoff = 0.5} = material;\n parsedMaterial.defines['ALPHA_CUTOFF'] = true;\n parsedMaterial.uniforms.alphaCutoff = alphaCutoff;\n break;\n case 'BLEND':\n log.warn('glTF BLEND alphaMode might not work well because it requires mesh sorting')();\n\n // WebGPU style parameters\n parsedMaterial.parameters.blend = true;\n\n parsedMaterial.parameters.blendColorOperation = 'add';\n parsedMaterial.parameters.blendColorSrcFactor = 'src-alpha';\n parsedMaterial.parameters.blendColorDstFactor = 'one-minus-src-alpha';\n\n parsedMaterial.parameters.blendAlphaOperation = 'add';\n parsedMaterial.parameters.blendAlphaSrcFactor = 'one';\n parsedMaterial.parameters.blendAlphaDstFactor = 'one-minus-src-alpha';\n\n // GL parameters\n // TODO - remove in favor of parameters\n parsedMaterial.glParameters['blend'] = true;\n parsedMaterial.glParameters['blendEquation'] = GL.FUNC_ADD;\n parsedMaterial.glParameters['blendFunc'] = [\n GL.SRC_ALPHA,\n GL.ONE_MINUS_SRC_ALPHA,\n GL.ONE,\n GL.ONE_MINUS_SRC_ALPHA\n ];\n\n break;\n }\n}\n\n/** Parse GLTF material sub record */\nfunction parsePbrMetallicRoughness(\n device: Device,\n pbrMetallicRoughness: GLTFPBRMetallicRoughness,\n parsedMaterial: ParsedPBRMaterial\n): void {\n if (pbrMetallicRoughness.baseColorTexture) {\n addTexture(\n device,\n pbrMetallicRoughness.baseColorTexture,\n 'pbr_baseColorSampler',\n 'HAS_BASECOLORMAP',\n parsedMaterial\n );\n }\n parsedMaterial.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];\n\n if (pbrMetallicRoughness.metallicRoughnessTexture) {\n addTexture(\n device,\n pbrMetallicRoughness.metallicRoughnessTexture,\n 'pbr_metallicRoughnessSampler',\n 'HAS_METALROUGHNESSMAP',\n parsedMaterial\n );\n }\n const {metallicFactor = 1, roughnessFactor = 1} = pbrMetallicRoughness;\n parsedMaterial.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];\n}\n\n/** Create a texture from a glTF texture/sampler/image combo and add it to bindings */\nfunction addTexture(\n device: Device,\n gltfTexture: GLTFTexture,\n uniformName: keyof PBRMaterialBindings,\n define: string,\n parsedMaterial: ParsedPBRMaterial\n): void {\n const image = gltfTexture.texture.source.image;\n\n const gltfSampler = {\n wrapS: 10497, // default REPEAT S (U) wrapping mode.\n wrapT: 10497, // default REPEAT T (V) wrapping mode.\n minFilter: 9729, // default LINEAR filtering\n magFilter: 9729, // default LINEAR filtering\n ...gltfTexture?.texture?.sampler\n } as GLTFSampler;\n\n const baseOptions = {\n id: gltfTexture.uniformName || gltfTexture.id,\n sampler: convertSampler(gltfSampler)\n };\n\n let texture: Texture;\n\n if (image.compressed) {\n texture = createCompressedTexture(device, image, baseOptions);\n } else {\n const {width, height} = device.getExternalImageSize(image);\n texture = device.createTexture({\n ...baseOptions,\n width,\n height,\n data: image\n });\n }\n\n parsedMaterial.bindings[uniformName] = texture;\n if (define) parsedMaterial.defines[define] = true;\n parsedMaterial.generatedTextures.push(texture);\n}\n\n/** One mip level as produced by loaders.gl compressed texture parsers */\nexport type CompressedMipLevel = {\n data: TypedArray;\n width: number;\n height: number;\n textureFormat?: TextureFormat;\n};\n\n/**\n * Compressed image from current loaders.gl releases.\n * - `mipmaps` is a boolean (true), NOT an array\n * - `data` is an Array of TextureLevel-like objects\n * - Per-level `textureFormat` is already a luma.gl TextureFormat\n * - Top-level `width`/`height` may be undefined\n */\nexport type CompressedImageDataArray = {\n compressed: true;\n mipmaps?: boolean;\n width?: number;\n height?: number;\n data: CompressedMipLevel[];\n};\n\n/**\n * Hypothetical future format where `mipmaps` is an actual array.\n * Kept for forward compatibility.\n */\nexport type CompressedImageMipmapArray = {\n compressed: true;\n width?: number;\n height?: number;\n mipmaps: CompressedMipLevel[];\n};\n\n/** Union of all known loaders.gl compressed image shapes */\nexport type CompressedImage = CompressedImageDataArray | CompressedImageMipmapArray;\n\nfunction createCompressedTextureFallback(\n device: Device,\n baseOptions: {id: string; sampler: SamplerProps}\n): Texture {\n return device.createTexture({\n ...baseOptions,\n format: 'rgba8unorm',\n width: 1,\n height: 1,\n mipLevels: 1\n });\n}\n\nfunction resolveCompressedTextureFormat(level: CompressedMipLevel): TextureFormat | undefined {\n return level.textureFormat;\n}\n\n/**\n * Maximum mip levels that can be filled for a compressed texture.\n * texStorage2D allocates level i at (baseW >> i) \u00D7 (baseH >> i).\n * Compressed formats can't upload data for levels smaller than one block,\n * so we stop before either dimension drops below the block size.\n */\nfunction getMaxCompressedMipLevels(\n baseWidth: number,\n baseHeight: number,\n format: TextureFormat\n): number {\n const {blockWidth = 1, blockHeight = 1} = textureFormatDecoder.getInfo(format);\n let count = 1;\n for (let i = 1; ; i++) {\n const w = Math.max(1, baseWidth >> i);\n const h = Math.max(1, baseHeight >> i);\n if (w < blockWidth || h < blockHeight) break;\n count++;\n }\n return count;\n}\n\n/**\n * Create a texture from compressed image data produced by loaders.gl.\n * Handles current loaders.gl compressed image layouts:\n *\n * current: {compressed, mipmaps: true, data: [{data, width, height, textureFormat}, ...]}\n * forward: {compressed, mipmaps: [{data, width, height, textureFormat}, ...]}\n */\nexport function createCompressedTexture(\n device: Device,\n image: CompressedImage,\n baseOptions: {id: string; sampler: SamplerProps}\n): Texture {\n // Normalize mip levels from all known loaders.gl formats\n let levels: CompressedMipLevel[];\n\n if (Array.isArray((image as any).data) && (image as any).data[0]?.data) {\n // loaders.gl current format: image.data is Array of mip-level objects\n levels = (image as CompressedImageDataArray).data;\n } else if ('mipmaps' in image && Array.isArray((image as CompressedImageMipmapArray).mipmaps)) {\n // Hypothetical future format: image.mipmaps is an Array\n levels = (image as CompressedImageMipmapArray).mipmaps;\n } else {\n levels = [];\n }\n\n if (levels.length === 0 || !levels[0]?.data) {\n log.warn(\n 'createCompressedTexture: compressed image has no valid mip levels, creating fallback'\n )();\n return createCompressedTextureFallback(device, baseOptions);\n }\n\n const baseLevel = levels[0];\n const baseWidth = baseLevel.width ?? (image as any).width ?? 0;\n const baseHeight = baseLevel.height ?? (image as any).height ?? 0;\n\n if (baseWidth <= 0 || baseHeight <= 0) {\n log.warn('createCompressedTexture: base level has invalid dimensions, creating fallback')();\n return createCompressedTextureFallback(device, baseOptions);\n }\n\n const format = resolveCompressedTextureFormat(baseLevel);\n\n if (!format) {\n log.warn('createCompressedTexture: compressed image has no textureFormat, creating fallback')();\n return createCompressedTextureFallback(device, baseOptions);\n }\n\n // Validate mip levels: truncate chain at first invalid level.\n // Levels must be contiguous, so we stop at the first level that has\n // a format mismatch, missing data, non-positive dimensions, or\n // dimensions that don't match what texStorage2D will allocate.\n //\n // For block-compressed formats (ASTC, BC, ETC2), texStorage2D allocates\n // mip levels down to 1\u00D71 texels, but compressed data can't be smaller\n // than one block (e.g. 4\u00D74 for ASTC-4x4). Cap the chain so we never\n // try to upload data whose block-aligned size exceeds the allocated level.\n const maxMipLevels = getMaxCompressedMipLevels(baseWidth, baseHeight, format);\n const levelLimit = Math.min(levels.length, maxMipLevels);\n\n let validLevelCount = 1;\n for (let i = 1; i < levelLimit; i++) {\n const level = levels[i];\n if (!level.data || level.width <= 0 || level.height <= 0) {\n log.warn(`createCompressedTexture: mip level ${i} has invalid data/dimensions, truncating`)();\n break;\n }\n const levelFormat = resolveCompressedTextureFormat(level);\n if (levelFormat && levelFormat !== format) {\n log.warn(\n `createCompressedTexture: mip level ${i} format '${levelFormat}' differs from base '${format}', truncating`\n )();\n break;\n }\n const expectedW = Math.max(1, baseWidth >> i);\n const expectedH = Math.max(1, baseHeight >> i);\n if (level.width !== expectedW || level.height !== expectedH) {\n log.warn(\n `createCompressedTexture: mip level ${i} dimensions ${level.width}x${level.height} ` +\n `don't match expected ${expectedW}x${expectedH}, truncating`\n )();\n break;\n }\n validLevelCount++;\n }\n\n const texture = device.createTexture({\n ...baseOptions,\n format,\n usage: Texture.TEXTURE | Texture.COPY_DST,\n width: baseWidth,\n height: baseHeight,\n mipLevels: validLevelCount,\n data: baseLevel.data\n });\n\n // Upload additional validated mip levels\n for (let i = 1; i < validLevelCount; i++) {\n texture.writeData(levels[i].data, {\n width: levels[i].width,\n height: levels[i].height,\n mipLevel: i\n });\n }\n\n return texture;\n}\n\n/*\n/**\n * Parses a GLTF material definition into uniforms and parameters for the PBR shader module\n *\nexport class PBRMaterialParser {\n readonly device: Device;\n\n readonly defines: Record<string, boolean>;\n readonly bindings: Record<string, Binding>;\n readonly uniforms: Record<string, any>;\n readonly parameters: Record<string, any>;\n\n /** Hold on to generated textures, we destroy them in the destroy method *\n readonly generatedTextures: Texture[];\n\n constructor(device: Device, props: PBRMaterialParserProps) {\n const {attributes, material, pbrDebug, imageBasedLightingEnvironment, lights, useTangents} =\n props;\n this.device = device;\n\n this.defines = {\n // TODO: Use EXT_sRGB if available (Standard in WebGL 2.0)\n MANUAL_SRGB: true,\n SRGB_FAST_APPROXIMATION: true\n };\n\n if (this.device.features.has('glsl-texture-lod')) {\n this.defines.USE_TEX_LOD = true;\n }\n\n this.uniforms = {\n // TODO: find better values?\n camera: [0, 0, 0], // Model should override\n\n metallicRoughnessValues: [1, 1] // Default is 1 and 1\n };\n\n this.bindings = {};\n\n this.parameters = {};\n this.generatedTextures = [];\n\n if (imageBasedLightingEnvironment) {\n this.bindings.pbr_diffuseEnvSampler = imageBasedLightingEnvironment.getDiffuseEnvSampler();\n this.bindings.pbr_specularEnvSampler = imageBasedLightingEnvironment.getSpecularEnvSampler();\n this.bindings.pbr_BrdfLUT = imageBasedLightingEnvironment.getBrdfTexture();\n this.uniforms.scaleIBLAmbient = [1, 1];\n }\n\n if (pbrDebug) {\n // Override final color for reference app visualization\n // of various parameters in the lighting equation.\n this.uniforms.scaleDiffBaseMR = [0, 0, 0, 0];\n this.uniforms.scaleFGDSpec = [0, 0, 0, 0];\n }\n\n this.defineIfPresent(attributes.NORMAL, 'HAS_NORMALS');\n this.defineIfPresent(attributes.TANGENT && useTangents, 'HAS_TANGENTS');\n this.defineIfPresent(attributes.TEXCOORD_0, 'HAS_UV');\n this.defineIfPresent(attributes.COLOR_0, 'HAS_COLORS');\n\n this.defineIfPresent(imageBasedLightingEnvironment, 'USE_IBL');\n this.defineIfPresent(lights, 'USE_LIGHTS');\n this.defineIfPresent(pbrDebug, 'PBR_DEBUG');\n\n if (material) {\n this.parseMaterial(material);\n }\n }\n\n /**\n * Destroy all generated resources to release memory.\n *\n destroy(): void {\n this.generatedTextures.forEach(texture => texture.destroy());\n }\n\n /** Add a define if the the value is non-nullish *\n defineIfPresent(value: unknown, name: string): void {\n if (value) {\n this.defines[name] = 1;\n }\n }\n\n /** Parse GLTF material record *\n parseMaterial(material) {\n this.uniforms.unlit = Boolean(material.unlit);\n\n if (material.pbrMetallicRoughness) {\n this.parsePbrMetallicRoughness(material.pbrMetallicRoughness);\n }\n if (material.normalTexture) {\n this.addTexture(material.normalTexture, 'pbr_normalSampler', 'HAS_NORMALMAP');\n\n const {scale = 1} = material.normalTexture;\n this.uniforms.normalScale = scale;\n }\n if (material.occlusionTexture) {\n this.addTexture(material.occlusionTexture, 'pbr_occlusionSampler', 'HAS_OCCLUSIONMAP');\n\n const {strength = 1} = material.occlusionTexture;\n this.uniforms.occlusionStrength = strength;\n }\n if (material.emissiveTexture) {\n this.addTexture(material.emissiveTexture, 'pbr_emissiveSampler', 'HAS_EMISSIVEMAP');\n this.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];\n }\n if (material.alphaMode === 'MASK') {\n const {alphaCutoff = 0.5} = material;\n this.defines.ALPHA_CUTOFF = true;\n this.uniforms.u_AlphaCutoff = alphaCutoff;\n } else if (material.alphaMode === 'BLEND') {\n log.warn('BLEND alphaMode might not work well because it requires mesh sorting')();\n Object.assign(this.parameters, {\n blend: true,\n blendEquation: GL.FUNC_ADD,\n blendFunc: [GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA, GL.ONE, GL.ONE_MINUS_SRC_ALPHA]\n });\n }\n }\n\n /** Parse GLTF material sub record *\n parsePbrMetallicRoughness(pbrMetallicRoughness) {\n if (pbrMetallicRoughness.baseColorTexture) {\n this.addTexture(\n pbrMetallicRoughness.baseColorTexture,\n 'pbr_baseColorSampler',\n 'HAS_BASECOLORMAP'\n );\n }\n this.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];\n\n if (pbrMetallicRoughness.metallicRoughnessTexture) {\n this.addTexture(\n pbrMetallicRoughness.metallicRoughnessTexture,\n 'pbr_metallicRoughnessSampler',\n 'HAS_METALROUGHNESSMAP'\n );\n }\n const {metallicFactor = 1, roughnessFactor = 1} = pbrMetallicRoughness;\n this.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];\n }\n\n /** Create a texture from a glTF texture/sampler/image combo and add it to bindings *\n addTexture(gltfTexture, name, define = null) {\n const parameters = gltfTexture?.texture?.sampler?.parameters || {};\n\n const image = gltfTexture.texture.source.image;\n let textureOptions;\n let specialTextureParameters = {};\n if (image.compressed) {\n textureOptions = image;\n specialTextureParameters = {\n [GL.TEXTURE_MIN_FILTER]: image.data.length > 1 ? GL.LINEAR_MIPMAP_NEAREST : GL.LINEAR\n };\n } else {\n // Texture2D accepts a promise that returns an image as data (Async Textures)\n textureOptions = {data: image};\n }\n\n const texture: Texture = this.device.createTexture({\n id: gltfTexture.name || gltfTexture.id,\n parameters: {\n ...parameters,\n ...specialTextureParameters\n },\n pixelStore: {\n [GL.UNPACK_FLIP_Y_WEBGL]: false\n },\n ...textureOptions\n });\n this.bindings[name] = texture;\n this.defineIfPresent(define, define);\n this.generatedTextures.push(texture);\n }\n}\n*/\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\n// TODO: convert in loaders.gl?\n\nimport type {SamplerProps} from '@luma.gl/core';\nimport {GL} from '@luma.gl/constants';\n\n/** Minimal glTF sampler representation used during conversion. */\ntype GLTFSampler = {\n /** Horizontal wrap mode. */\n wrapS?: GL.CLAMP_TO_EDGE | GL.REPEAT | GL.MIRRORED_REPEAT;\n /** Vertical wrap mode. */\n wrapT?: GL.CLAMP_TO_EDGE | GL.REPEAT | GL.MIRRORED_REPEAT;\n /** Magnification filter. */\n magFilter?: GL.NEAREST | GL.LINEAR;\n /** Minification and mip filter combination. */\n minFilter?:\n | GL.NEAREST\n | GL.LINEAR\n | GL.NEAREST_MIPMAP_NEAREST\n | GL.LINEAR_MIPMAP_NEAREST\n | GL.NEAREST_MIPMAP_LINEAR\n | GL.LINEAR_MIPMAP_LINEAR;\n};\n\n/** Converts a glTF sampler into luma.gl sampler props. */\nexport function convertSampler(gltfSampler: GLTFSampler): SamplerProps {\n return {\n addressModeU: convertSamplerWrapMode(gltfSampler.wrapS),\n addressModeV: convertSamplerWrapMode(gltfSampler.wrapT),\n magFilter: convertSamplerMagFilter(gltfSampler.magFilter),\n ...convertSamplerMinFilter(gltfSampler.minFilter)\n };\n}\n\n/** Converts a glTF wrap enum into a luma.gl address mode. */\nfunction convertSamplerWrapMode(\n mode: GL.CLAMP_TO_EDGE | GL.REPEAT | GL.MIRRORED_REPEAT | undefined\n): 'clamp-to-edge' | 'repeat' | 'mirror-repeat' | undefined {\n switch (mode) {\n case GL.CLAMP_TO_EDGE:\n return 'clamp-to-edge';\n case GL.REPEAT:\n return 'repeat';\n case GL.MIRRORED_REPEAT:\n return 'mirror-repeat';\n default:\n return undefined;\n }\n}\n\n/** Converts a glTF mag filter enum into a luma.gl mag filter. */\nfunction convertSamplerMagFilter(\n mode: GL.NEAREST | GL.LINEAR | undefined\n): 'nearest' | 'linear' | undefined {\n switch (mode) {\n case GL.NEAREST:\n return 'nearest';\n case GL.LINEAR:\n return 'linear';\n default:\n return undefined;\n }\n}\n\n/** Converts a glTF min filter enum into luma.gl minification and mipmap filters. */\nfunction convertSamplerMinFilter(\n mode:\n | GL.NEAREST\n | GL.LINEAR\n | GL.NEAREST_MIPMAP_NEAREST\n | GL.LINEAR_MIPMAP_NEAREST\n | GL.NEAREST_MIPMAP_LINEAR\n | GL.LINEAR_MIPMAP_LINEAR\n | undefined\n): {minFilter?: 'nearest' | 'linear'; mipmapFilter?: 'nearest' | 'linear'} {\n switch (mode) {\n case GL.NEAREST:\n return {minFilter: 'nearest'};\n case GL.LINEAR:\n return {minFilter: 'linear'};\n case GL.NEAREST_MIPMAP_NEAREST:\n return {minFilter: 'nearest', mipmapFilter: 'nearest'};\n case GL.LINEAR_MIPMAP_NEAREST:\n return {minFilter: 'linear', mipmapFilter: 'nearest'};\n case GL.NEAREST_MIPMAP_LINEAR:\n return {minFilter: 'nearest', mipmapFilter: 'linear'};\n case GL.LINEAR_MIPMAP_LINEAR:\n return {minFilter: 'linear', mipmapFilter: 'linear'};\n default:\n return {};\n }\n}\n", "import {Matrix4} from '@math.gl/core';\nimport type {GLTFNodePostprocessed, GLTFPostprocessed} from '@loaders.gl/gltf';\nimport type {DirectionalLight, Light, PointLight} from '@luma.gl/shadertools';\n\n/** Parse KHR_lights_punctual extension into luma.gl light definitions */\nexport function parseGLTFLights(gltf: GLTFPostprocessed): Light[] {\n const lightDefs =\n // `postProcessGLTF()` moves KHR_lights_punctual into `gltf.lights`.\n (gltf as GLTFPostprocessed & {lights?: any[]}).lights ||\n gltf.extensions?.['KHR_lights_punctual']?.['lights'];\n if (!lightDefs || !Array.isArray(lightDefs) || lightDefs.length === 0) {\n return [];\n }\n\n const lights: Light[] = [];\n\n for (const node of gltf.nodes || []) {\n const lightIndex =\n (node as GLTFNodePostprocessed & {light?: number}).light ??\n node.extensions?.KHR_lights_punctual?.light;\n if (typeof lightIndex !== 'number') {\n // eslint-disable-next-line no-continue\n continue;\n }\n const gltfLight = lightDefs[lightIndex];\n if (!gltfLight) {\n // eslint-disable-next-line no-continue\n continue;\n }\n\n const color = (gltfLight.color || [1, 1, 1]) as [number, number, number];\n const intensity = gltfLight.intensity ?? 1;\n const range = gltfLight.range;\n\n switch (gltfLight.type) {\n case 'directional':\n lights.push(parseDirectionalLight(node, color, intensity));\n break;\n case 'point':\n lights.push(parsePointLight(node, color, intensity, range));\n break;\n case 'spot':\n lights.push(parsePointLight(node, color, intensity, range));\n break;\n default:\n // Unsupported light type\n break;\n }\n }\n\n return lights;\n}\n\n/**\n * Converts a glTF punctual light attached to a node into a point light.\n */\nfunction parsePointLight(\n node: GLTFNodePostprocessed,\n color: [number, number, number],\n intensity: number,\n range?: number\n): PointLight {\n const position = getNodePosition(node);\n\n let attenuation: Readonly<[number, number, number]> = [1, 0, 0];\n if (range !== undefined && range > 0) {\n attenuation = [1, 0, 1 / (range * range)] as [number, number, number];\n }\n\n return {\n type: 'point',\n position,\n color,\n intensity,\n attenuation\n };\n}\n\n/**\n * Converts a glTF punctual light attached to a node into a directional light.\n */\nfunction parseDirectionalLight(\n node: GLTFNodePostprocessed,\n color: [number, number, number],\n intensity: number\n): DirectionalLight {\n const direction = getNodeDirection(node);\n\n return {\n type: 'directional',\n direction,\n color,\n intensity\n };\n}\n\n/**\n * Resolves the world-space position of a glTF node from its matrix or translation.\n */\nfunction getNodePosition(node: GLTFNodePostprocessed): [number, number, number] {\n if (node.matrix) {\n return new Matrix4(node.matrix).transformAsPoint([0, 0, 0]) as [number, number, number];\n }\n\n if (node.translation) {\n return [...node.translation] as [number, number, number];\n }\n\n return [0, 0, 0];\n}\n\n/**\n * Resolves the forward direction of a glTF node from its matrix or rotation.\n */\nfunction getNodeDirection(node: GLTFNodePostprocessed): [number, number, number] {\n if (node.matrix) {\n return new Matrix4(node.matrix).transformDirection([0, 0, -1]) as [number, number, number];\n }\n\n if (node.rotation) {\n return new Matrix4().fromQuaternion(node.rotation).transformDirection([0, 0, -1]) as [\n number,\n number,\n number\n ];\n }\n\n return [0, 0, -1];\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {Device, type PrimitiveTopology} from '@luma.gl/core';\nimport {Geometry, GeometryAttribute, GroupNode, ModelNode, type ModelProps} from '@luma.gl/engine';\nimport {\n type GLTFMeshPostprocessed,\n type GLTFNodePostprocessed,\n type GLTFPostprocessed\n} from '@loaders.gl/gltf';\n\nimport {type PBREnvironment} from '../pbr/pbr-environment';\nimport {convertGLDrawModeToTopology} from '../webgl-to-webgpu/convert-webgl-topology';\nimport {createGLTFModel} from '../gltf/create-gltf-model';\n\nimport {parsePBRMaterial} from './parse-pbr-material';\n\n/** Options that influence how a post-processed glTF is turned into a luma.gl scenegraph. */\nexport type ParseGLTFOptions = {\n /** Additional model props applied to each generated primitive model. */\n modelOptions?: Partial<ModelProps>;\n /** Enables shader-level PBR debug output. */\n pbrDebug?: boolean;\n /** Optional image-based lighting environment. */\n imageBasedLightingEnvironment?: PBREnvironment;\n /** Enables punctual light extraction. */\n lights?: boolean;\n /** Enables tangent usage when available. */\n useTangents?: boolean;\n};\n\nconst defaultOptions: Required<ParseGLTFOptions> = {\n modelOptions: {},\n pbrDebug: false,\n imageBasedLightingEnvironment: undefined!,\n lights: true,\n useTangents: false\n};\n\n/**\n * GLTF instantiator for luma.gl\n * Walks the parsed and resolved glTF structure and builds a luma.gl scenegraph\n */\nexport function parseGLTF(\n device: Device,\n gltf: GLTFPostprocessed,\n options: ParseGLTFOptions = {}\n): {\n /** Scene roots generated from `gltf.scenes`. */\n scenes: GroupNode[];\n /** Map from glTF mesh ids to generated mesh group nodes. */\n gltfMeshIdToNodeMap: Map<string, GroupNode>;\n /** Map from glTF node indices to generated scenegraph nodes. */\n gltfNodeIndexToNodeMap: Map<number, GroupNode>;\n /** Map from glTF node ids to generated scenegraph nodes. */\n gltfNodeIdToNodeMap: Map<string, GroupNode>;\n} {\n const combinedOptions = {...defaultOptions, ...options};\n\n const gltfMeshIdToNodeMap = new Map<string, GroupNode>();\n gltf.meshes.forEach((gltfMesh, idx) => {\n const newMesh = createNodeForGLTFMesh(device, gltfMesh, combinedOptions);\n gltfMeshIdToNodeMap.set(gltfMesh.id, newMesh);\n });\n\n const gltfNodeIndexToNodeMap = new Map<number, GroupNode>();\n const gltfNodeIdToNodeMap = new Map<string, GroupNode>();\n // Step 1/2: Generate a GroupNode for each gltf node. (1:1 mapping).\n gltf.nodes.forEach((gltfNode, idx) => {\n const newNode = createNodeForGLTFNode(device, gltfNode, combinedOptions);\n gltfNodeIndexToNodeMap.set(idx, newNode);\n gltfNodeIdToNodeMap.set(gltfNode.id, newNode);\n });\n\n // Step 2/2: Go though each gltf node and attach the children.\n // This guarantees that each gltf node will have exactly one luma GroupNode.\n gltf.nodes.forEach((gltfNode, idx) => {\n gltfNodeIndexToNodeMap.get(idx)!.add(\n (gltfNode.children ?? []).map(({id}) => {\n const child = gltfNodeIdToNodeMap.get(id);\n if (!child) throw new Error(`Cannot find child ${id} of node ${idx}`);\n return child;\n })\n );\n\n // Nodes can have children nodes and one optional child mesh at the same time.\n if (gltfNode.mesh) {\n const mesh = gltfMeshIdToNodeMap.get(gltfNode.mesh.id);\n if (!mesh) {\n throw new Error(`Cannot find mesh child ${gltfNode.mesh.id} of node ${idx}`);\n }\n gltfNodeIndexToNodeMap.get(idx)!.add(mesh);\n }\n });\n\n const scenes = gltf.scenes.map(gltfScene => {\n const children = (gltfScene.nodes || []).map(({id}) => {\n const child = gltfNodeIdToNodeMap.get(id);\n if (!child)\n throw new Error(`Cannot find child ${id} of scene ${gltfScene.name || gltfScene.id}`);\n return child;\n });\n return new GroupNode({\n id: gltfScene.name || gltfScene.id,\n children\n });\n });\n\n return {scenes, gltfMeshIdToNodeMap, gltfNodeIdToNodeMap, gltfNodeIndexToNodeMap};\n}\n\n/** Creates a `GroupNode` for one glTF node transform. */\nfunction createNodeForGLTFNode(\n device: Device,\n gltfNode: GLTFNodePostprocessed,\n options: Required<ParseGLTFOptions>\n): GroupNode {\n return new GroupNode({\n id: gltfNode.name || gltfNode.id,\n children: [],\n matrix: gltfNode.matrix,\n position: gltfNode.translation,\n rotation: gltfNode.rotation,\n scale: gltfNode.scale\n });\n}\n\n/** Creates a mesh group node containing one model node per glTF primitive. */\nfunction createNodeForGLTFMesh(\n device: Device,\n gltfMesh: GLTFMeshPostprocessed,\n options: Required<ParseGLTFOptions>\n): GroupNode {\n const gltfPrimitives = gltfMesh.primitives || [];\n const primitives = gltfPrimitives.map((gltfPrimitive, i) =>\n createNodeForGLTFPrimitive(device, gltfPrimitive, i, gltfMesh, options)\n );\n const mesh = new GroupNode({\n id: gltfMesh.name || gltfMesh.id,\n children: primitives\n });\n\n return mesh;\n}\n\n/** Creates a renderable model node for one glTF primitive. */\nfunction createNodeForGLTFPrimitive(\n device: Device,\n gltfPrimitive: any,\n i: number,\n gltfMesh: GLTFMeshPostprocessed,\n options: Required<ParseGLTFOptions>\n): ModelNode {\n const id = gltfPrimitive.name || `${gltfMesh.name || gltfMesh.id}-primitive-${i}`;\n const topology = convertGLDrawModeToTopology(gltfPrimitive.mode || 4);\n const vertexCount = gltfPrimitive.indices\n ? gltfPrimitive.indices.count\n : getVertexCount(gltfPrimitive.attributes);\n\n const geometry = createGeometry(id, gltfPrimitive, topology);\n\n const parsedPPBRMaterial = parsePBRMaterial(\n device,\n gltfPrimitive.material,\n geometry.attributes,\n options\n );\n\n const modelNode = createGLTFModel(device, {\n id,\n geometry: createGeometry(id, gltfPrimitive, topology),\n parsedPPBRMaterial,\n modelOptions: options.modelOptions,\n vertexCount\n });\n\n modelNode.bounds = [gltfPrimitive.attributes.POSITION.min, gltfPrimitive.attributes.POSITION.max];\n // TODO this holds on to all the CPU side texture and attribute data\n // modelNode.material = gltfPrimitive.material;\n\n return modelNode;\n}\n\n/** Computes the vertex count for a primitive without indices. */\nfunction getVertexCount(attributes: any) {\n throw new Error('getVertexCount not implemented');\n}\n\n/** Converts glTF primitive attributes and indices into a luma.gl `Geometry`. */\nfunction createGeometry(id: string, gltfPrimitive: any, topology: PrimitiveTopology): Geometry {\n const attributes: Record<string, GeometryAttribute> = {};\n for (const [attributeName, attribute] of Object.entries(gltfPrimitive.attributes)) {\n const {components, size, value} = attribute as GeometryAttribute;\n\n attributes[attributeName] = {size: size ?? components, value};\n }\n\n return new Geometry({\n id,\n topology,\n indices: gltfPrimitive.indices.value,\n attributes\n });\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {PrimitiveTopology} from '@luma.gl/core';\n\n// NOTE: Modules other than `@luma.gl/webgl` should not import `GL` from\n// `@luma.gl/constants`. Locally we use `GLEnum` instead of `GL` to avoid\n// conflicts with the `babel-plugin-inline-webgl-constants` plugin.\n// eslint-disable-next-line no-shadow\n/** Minimal WebGL draw-mode enum subset used by the glTF converter. */\nexport enum GLEnum {\n POINTS = 0x0,\n LINES = 0x1,\n LINE_LOOP = 0x2,\n LINE_STRIP = 0x3,\n TRIANGLES = 0x4,\n TRIANGLE_STRIP = 0x5,\n TRIANGLE_FAN = 0x6\n}\n\n/** Converts a WebGL draw mode into a luma.gl primitive topology string. */\nexport function convertGLDrawModeToTopology(\n drawMode:\n | GLEnum.POINTS\n | GLEnum.LINES\n | GLEnum.LINE_STRIP\n | GLEnum.LINE_LOOP\n | GLEnum.TRIANGLES\n | GLEnum.TRIANGLE_STRIP\n | GLEnum.TRIANGLE_FAN\n): PrimitiveTopology {\n // prettier-ignore\n switch (drawMode) {\n case GLEnum.POINTS: return 'point-list';\n case GLEnum.LINES: return 'line-list';\n case GLEnum.LINE_STRIP: return 'line-strip';\n case GLEnum.TRIANGLES: return 'triangle-list';\n case GLEnum.TRIANGLE_STRIP: return 'triangle-strip';\n default: throw new Error(String(drawMode));\n }\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {Device, type RenderPipelineParameters, log} from '@luma.gl/core';\nimport {pbrMaterial, skin} from '@luma.gl/shadertools';\nimport {Geometry, Model, ModelNode, type ModelProps} from '@luma.gl/engine';\nimport {type ParsedPBRMaterial} from '../pbr/pbr-material';\n\nconst SHADER = /* WGSL */ `\nstruct VertexInputs {\n @location(0) positions: vec3f,\n#ifdef HAS_NORMALS\n @location(1) normals: vec3f,\n#endif\n#ifdef HAS_TANGENTS\n @location(2) TANGENT: vec4f,\n#endif\n#ifdef HAS_UV\n @location(3) texCoords: vec2f,\n#endif\n#ifdef HAS_SKIN\n @location(4) JOINTS_0: vec4u,\n @location(5) WEIGHTS_0: vec4f,\n#endif\n};\n\nstruct FragmentInputs {\n @builtin(position) position: vec4f,\n @location(0) pbrPosition: vec3f,\n @location(1) pbrUV: vec2f,\n @location(2) pbrNormal: vec3f,\n#ifdef HAS_TANGENTS\n @location(3) pbrTangent: vec4f,\n#endif\n};\n\n@vertex\nfn vertexMain(inputs: VertexInputs) -> FragmentInputs {\n var outputs: FragmentInputs;\n var position = vec4f(inputs.positions, 1.0);\n var normal = vec3f(0.0, 0.0, 1.0);\n var tangent = vec4f(1.0, 0.0, 0.0, 1.0);\n var uv = vec2f(0.0, 0.0);\n\n#ifdef HAS_NORMALS\n normal = inputs.normals;\n#endif\n#ifdef HAS_UV\n uv = inputs.texCoords;\n#endif\n#ifdef HAS_TANGENTS\n tangent = inputs.TANGENT;\n#endif\n#ifdef HAS_SKIN\n let skinMatrix = getSkinMatrix(inputs.WEIGHTS_0, inputs.JOINTS_0);\n position = skinMatrix * position;\n normal = normalize((skinMatrix * vec4f(normal, 0.0)).xyz);\n#ifdef HAS_TANGENTS\n tangent = vec4f(normalize((skinMatrix * vec4f(tangent.xyz, 0.0)).xyz), tangent.w);\n#endif\n#endif\n\n let worldPosition = pbrProjection.modelMatrix * position;\n\n#ifdef HAS_NORMALS\n normal = normalize((pbrProjection.normalMatrix * vec4f(normal, 0.0)).xyz);\n#endif\n#ifdef HAS_TANGENTS\n let worldTangent = normalize((pbrProjection.modelMatrix * vec4f(tangent.xyz, 0.0)).xyz);\n outputs.pbrTangent = vec4f(worldTangent, tangent.w);\n#endif\n\n outputs.position = pbrProjection.modelViewProjectionMatrix * position;\n outputs.pbrPosition = worldPosition.xyz / worldPosition.w;\n outputs.pbrUV = uv;\n outputs.pbrNormal = normal;\n return outputs;\n}\n\n@fragment\nfn fragmentMain(inputs: FragmentInputs) -> @location(0) vec4f {\n fragmentInputs.pbr_vPosition = inputs.pbrPosition;\n fragmentInputs.pbr_vUV = inputs.pbrUV;\n fragmentInputs.pbr_vNormal = inputs.pbrNormal;\n#ifdef HAS_TANGENTS\n let tangent = normalize(inputs.pbrTangent.xyz);\n let bitangent = normalize(cross(inputs.pbrNormal, tangent)) * inputs.pbrTangent.w;\n fragmentInputs.pbr_vTBN = mat3x3f(tangent, bitangent, inputs.pbrNormal);\n#endif\n return pbr_filterColor(vec4f(1.0));\n}\n`;\n\n// TODO rename attributes to POSITION/NORMAL etc\n// See gpu-geometry.ts: getAttributeBuffersFromGeometry()\nconst vs = /* glsl */ `\\\n#version 300 es\n\n // in vec4 POSITION;\n in vec4 positions;\n\n #ifdef HAS_NORMALS\n // in vec4 NORMAL;\n in vec4 normals;\n #endif\n\n #ifdef HAS_TANGENTS\n in vec4 TANGENT;\n #endif\n\n #ifdef HAS_UV\n // in vec2 TEXCOORD_0;\n in vec2 texCoords;\n #endif\n\n #ifdef HAS_SKIN\n in uvec4 JOINTS_0;\n in vec4 WEIGHTS_0;\n #endif\n\n void main(void) {\n vec4 _NORMAL = vec4(0.);\n vec4 _TANGENT = vec4(0.);\n vec2 _TEXCOORD_0 = vec2(0.);\n\n #ifdef HAS_NORMALS\n _NORMAL = normals;\n #endif\n\n #ifdef HAS_TANGENTS\n _TANGENT = TANGENT;\n #endif\n\n #ifdef HAS_UV\n _TEXCOORD_0 = texCoords;\n #endif\n\n vec4 pos = positions;\n\n #ifdef HAS_SKIN\n mat4 skinMat = getSkinMatrix(WEIGHTS_0, JOINTS_0);\n pos = skinMat * pos;\n _NORMAL = skinMat * _NORMAL;\n _TANGENT = vec4((skinMat * vec4(_TANGENT.xyz, 0.)).xyz, _TANGENT.w);\n #endif\n\n pbr_setPositionNormalTangentUV(pos, _NORMAL, _TANGENT, _TEXCOORD_0);\n gl_Position = pbrProjection.modelViewProjectionMatrix * pos;\n }\n`;\n\nconst fs = /* glsl */ `\\\n#version 300 es\n out vec4 fragmentColor;\n\n void main(void) {\n vec3 pos = pbr_vPosition;\n fragmentColor = pbr_filterColor(vec4(1.0));\n }\n`;\n\n/** Options used to instantiate a `ModelNode` for one glTF primitive. */\nexport type CreateGLTFModelOptions = {\n /** Optional id assigned to the generated model. */\n id?: string;\n /** Vertex count override for non-indexed primitives. */\n vertexCount?: number;\n /** Geometry converted from the glTF primitive. */\n geometry: Geometry;\n /** Parsed PBR material state for the primitive. */\n parsedPPBRMaterial: ParsedPBRMaterial;\n /** Additional model props merged into the generated model. */\n modelOptions?: Partial<ModelProps>;\n};\n\n/** Creates a luma.gl Model from GLTF data*/\nexport function createGLTFModel(device: Device, options: CreateGLTFModelOptions): ModelNode {\n const {id, geometry, parsedPPBRMaterial, vertexCount, modelOptions = {}} = options;\n\n log.info(4, 'createGLTFModel defines: ', parsedPPBRMaterial.defines)();\n\n // Calculate managedResources\n // TODO: Implement resource management logic that will\n // not deallocate resources/textures/buffers that are shared\n const managedResources: any[] = [];\n // managedResources.push(...parsedMaterial.generatedTextures);\n // managedResources.push(...Object.values(attributes).map((attribute) => attribute.buffer));\n\n const parameters: RenderPipelineParameters = {\n depthWriteEnabled: true,\n depthCompare: 'less',\n depthFormat: 'depth24plus',\n cullMode: 'back'\n };\n\n const modelProps: ModelProps = {\n id,\n source: SHADER,\n vs,\n fs,\n geometry,\n topology: geometry.topology,\n vertexCount,\n modules: [pbrMaterial, skin],\n ...modelOptions,\n\n defines: {...parsedPPBRMaterial.defines, ...modelOptions.defines},\n parameters: {...parameters, ...parsedPPBRMaterial.parameters, ...modelOptions.parameters}\n };\n\n const model = new Model(device, modelProps);\n\n const {camera, ...pbrMaterialProps} = {\n ...parsedPPBRMaterial.uniforms,\n ...modelOptions.uniforms,\n ...parsedPPBRMaterial.bindings,\n ...modelOptions.bindings\n };\n\n model.shaderInputs.setProps({pbrMaterial: pbrMaterialProps, pbrProjection: {camera}});\n return new ModelNode({managedResources, model});\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {log} from '@luma.gl/core';\nimport {GroupNode} from '@luma.gl/engine';\nimport {GLTFAnimation} from './animations/animations';\nimport {interpolate} from './animations/interpolate';\n\n/** Construction props for a single glTF animation controller. */\ntype GLTFSingleAnimatorProps = {\n /** Animation data to evaluate. */\n animation: GLTFAnimation;\n /** Mapping from glTF node ids to scenegraph nodes. */\n gltfNodeIdToNodeMap: Map<string, GroupNode>;\n /** Start time in seconds. */\n startTime?: number;\n /** Whether playback is active. */\n playing?: boolean;\n /** Playback speed multiplier. */\n speed?: number;\n};\n\n/** Evaluates one glTF animation against the generated scenegraph. */\nclass GLTFSingleAnimator {\n /** Animation definition being played. */\n animation: GLTFAnimation;\n /** Target scenegraph lookup table. */\n gltfNodeIdToNodeMap: Map<string, GroupNode>;\n /** Playback start time in seconds. */\n startTime: number = 0;\n /** Whether playback is currently enabled. */\n playing: boolean = true;\n /** Playback speed multiplier. */\n speed: number = 1;\n\n /** Creates a single-animation controller. */\n constructor(props: GLTFSingleAnimatorProps) {\n this.animation = props.animation;\n this.gltfNodeIdToNodeMap = props.gltfNodeIdToNodeMap;\n this.animation.name ||= 'unnamed';\n Object.assign(this, props);\n }\n\n /** Advances the animation to the supplied wall-clock time in milliseconds. */\n setTime(timeMs: number) {\n if (!this.playing) {\n return;\n }\n\n const absTime = timeMs / 1000;\n const time = (absTime - this.startTime) * this.speed;\n\n this.animation.channels.forEach(({sampler, targetNodeId, path}) => {\n const targetNode = this.gltfNodeIdToNodeMap.get(targetNodeId);\n if (!targetNode) {\n throw new Error(`Cannot find animation target node ${targetNodeId}`);\n }\n\n interpolate(time, sampler, targetNode, path);\n });\n }\n}\n\n/** Construction props for {@link GLTFAnimator}. */\nexport type GLTFAnimatorProps = {\n /** Parsed animations from the source glTF. */\n animations: GLTFAnimation[];\n /** Mapping from glTF node ids to scenegraph nodes. */\n gltfNodeIdToNodeMap: Map<string, GroupNode>;\n};\n\n/** Coordinates playback of every animation found in a glTF scene. */\nexport class GLTFAnimator {\n /** Individual animation controllers. */\n animations: GLTFSingleAnimator[];\n\n /** Creates an animator for the supplied glTF scenegraph. */\n constructor(props: GLTFAnimatorProps) {\n this.animations = props.animations.map((animation, index) => {\n const name = animation.name || `Animation-${index}`;\n return new GLTFSingleAnimator({\n gltfNodeIdToNodeMap: props.gltfNodeIdToNodeMap,\n animation: {name, channels: animation.channels}\n });\n });\n }\n\n /** @deprecated Use .setTime(). Will be removed (deck.gl is using this) */\n animate(time: number): void {\n log.warn('GLTFAnimator#animate is deprecated. Use GLTFAnimator#setTime instead')();\n this.setTime(time);\n }\n\n /** Advances every animation to the supplied wall-clock time in milliseconds. */\n setTime(time: number): void {\n this.animations.forEach(animation => animation.setTime(time));\n }\n\n /** Returns the per-animation controllers managed by this animator. */\n getAnimations() {\n return this.animations;\n }\n}\n", "import {log} from '@luma.gl/core';\nimport {Quaternion} from '@math.gl/core';\nimport {GLTFAnimationPath, GLTFAnimationSampler} from './animations';\nimport {GroupNode} from '@luma.gl/engine';\n\n/** Applies an evaluated animation value to a scenegraph node. */\nfunction updateTargetPath(\n target: GroupNode,\n path: GLTFAnimationPath,\n newValue: number[]\n): GroupNode | null {\n switch (path) {\n case 'translation':\n return target.setPosition(newValue).updateMatrix();\n\n case 'rotation':\n return target.setRotation(newValue).updateMatrix();\n\n case 'scale':\n return target.setScale(newValue).updateMatrix();\n\n default:\n log.warn(`Bad animation path ${path}`)();\n return null;\n }\n}\n\n/** Evaluates a glTF animation sampler at the supplied time and applies the result to a node. */\nexport function interpolate(\n time: number,\n {input, interpolation, output}: GLTFAnimationSampler,\n target: GroupNode,\n path: GLTFAnimationPath\n) {\n const maxTime = input[input.length - 1];\n const animationTime = time % maxTime;\n\n const nextIndex = input.findIndex(t => t >= animationTime);\n const previousIndex = Math.max(0, nextIndex - 1);\n\n const previousTime = input[previousIndex];\n const nextTime = input[nextIndex];\n\n switch (interpolation) {\n case 'STEP':\n stepInterpolate(target, path, output[previousIndex]);\n break;\n\n case 'LINEAR':\n if (nextTime > previousTime) {\n const ratio = (animationTime - previousTime) / (nextTime - previousTime);\n linearInterpolate(target, path, output[previousIndex], output[nextIndex], ratio);\n }\n break;\n\n case 'CUBICSPLINE':\n if (nextTime > previousTime) {\n const ratio = (animationTime - previousTime) / (nextTime - previousTime);\n const tDiff = nextTime - previousTime;\n\n const p0 = output[3 * previousIndex + 1];\n const outTangent0 = output[3 * previousIndex + 2];\n const inTangent1 = output[3 * nextIndex + 0];\n const p1 = output[3 * nextIndex + 1];\n\n cubicsplineInterpolate(target, path, {p0, outTangent0, inTangent1, p1, tDiff, ratio});\n }\n break;\n\n default:\n log.warn(`Interpolation ${interpolation} not supported`)();\n break;\n }\n}\n\n/** Applies linear interpolation between two keyframes. */\nfunction linearInterpolate(\n target: GroupNode,\n path: GLTFAnimationPath,\n start: number[],\n stop: number[],\n ratio: number\n) {\n if (path === 'rotation') {\n // SLERP when path is rotation\n updateTargetPath(target, path, new Quaternion().slerp({start, target: stop, ratio}));\n } else {\n // regular interpolation\n const newVal = [];\n for (let i = 0; i < start.length; i++) {\n newVal[i] = ratio * stop[i] + (1 - ratio) * start[i];\n }\n updateTargetPath(target, path, newVal);\n }\n}\n\n/** Applies glTF cubic spline interpolation between two keyframes. */\nfunction cubicsplineInterpolate(\n target: GroupNode,\n path: GLTFAnimationPath,\n {\n p0,\n outTangent0,\n inTangent1,\n p1,\n tDiff,\n ratio: t\n }: {\n p0: number[];\n outTangent0: number[];\n inTangent1: number[];\n p1: number[];\n tDiff: number;\n ratio: number;\n }\n) {\n // TODO: Quaternion might need normalization\n const newVal = [];\n for (let i = 0; i < p0.length; i++) {\n const m0 = outTangent0[i] * tDiff;\n const m1 = inTangent1[i] * tDiff;\n newVal[i] =\n (2 * Math.pow(t, 3) - 3 * Math.pow(t, 2) + 1) * p0[i] +\n (Math.pow(t, 3) - 2 * Math.pow(t, 2) + t) * m0 +\n (-2 * Math.pow(t, 3) + 3 * Math.pow(t, 2)) * p1[i] +\n (Math.pow(t, 3) - Math.pow(t, 2)) * m1;\n }\n updateTargetPath(target, path, newVal);\n}\n\n/** Applies step interpolation by copying the current keyframe value. */\nfunction stepInterpolate(target: GroupNode, path: GLTFAnimationPath, value: number[]) {\n updateTargetPath(target, path, value);\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\n// TODO: convert in loaders.gl?\nimport type {TypedArray} from '@math.gl/types';\n\n/** Maps glTF accessor type strings to their component counts. */\nexport const ATTRIBUTE_TYPE_TO_COMPONENTS: Record<string, number> = {\n SCALAR: 1,\n VEC2: 2,\n VEC3: 3,\n VEC4: 4,\n MAT2: 4,\n MAT3: 9,\n MAT4: 16\n};\n\n/** Maps glTF accessor component-type enums to typed-array constructors. */\nexport const ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY: Record<number, any> = {\n 5120: Int8Array,\n 5121: Uint8Array,\n 5122: Int16Array,\n 5123: Uint16Array,\n 5125: Uint32Array,\n 5126: Float32Array\n};\n\n/** Minimal accessor shape required to materialize a typed array. */\ntype GLTFAccessor = {\n /** Numeric component type enum. */\n componentType: number;\n /** Accessor type string such as `VEC3` or `SCALAR`. */\n type: string;\n /** Number of logical elements in the accessor. */\n count: number;\n /** Buffer view carrying the raw bytes. */\n bufferView?: {data: {buffer: ArrayBufferLike; byteOffset?: number}};\n /** Byte offset into the buffer view. */\n byteOffset?: number;\n};\n\n/** Converts a glTF accessor into a typed array plus its component count. */\nexport function accessorToTypedArray(accessor: GLTFAccessor): {\n /** Typed array view over the accessor data. */\n typedArray: TypedArray;\n /** Number of scalar components per element. */\n components: number;\n} {\n const ArrayType = ATTRIBUTE_COMPONENT_TYPE_TO_ARRAY[accessor.componentType];\n const components = ATTRIBUTE_TYPE_TO_COMPONENTS[accessor.type];\n const length = components * accessor.count;\n const {buffer, byteOffset = 0} = accessor.bufferView?.data ?? {};\n\n const typedArray = new ArrayType(buffer, byteOffset + (accessor.byteOffset || 0), length);\n\n return {typedArray, components};\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {type GLTFAccessorPostprocessed, type GLTFPostprocessed} from '@loaders.gl/gltf';\nimport {\n GLTFAnimationPath,\n type GLTFAnimation,\n type GLTFAnimationChannel,\n type GLTFAnimationSampler\n} from '../gltf/animations/animations';\n\nimport {accessorToTypedArray} from '..//webgl-to-webgpu/convert-webgl-attribute';\n\n/** Parses glTF animation records into the runtime animation model used by `GLTFAnimator`. */\nexport function parseGLTFAnimations(gltf: GLTFPostprocessed): GLTFAnimation[] {\n const gltfAnimations = gltf.animations || [];\n const accessorCache1D = new Map<GLTFAccessorPostprocessed, number[]>();\n const accessorCache2D = new Map<GLTFAccessorPostprocessed, number[][]>();\n\n return gltfAnimations.map((animation, index) => {\n const name = animation.name || `Animation-${index}`;\n const samplers: GLTFAnimationSampler[] = animation.samplers.map(\n ({input, interpolation = 'LINEAR', output}) => ({\n input: accessorToJsArray1D(gltf.accessors[input], accessorCache1D),\n interpolation,\n output: accessorToJsArray2D(gltf.accessors[output], accessorCache2D)\n })\n );\n\n const channels: GLTFAnimationChannel[] = animation.channels.map(({sampler, target}) => {\n const targetNode = gltf.nodes[target.node ?? 0];\n if (!targetNode) {\n throw new Error(`Cannot find animation target ${target.node}`);\n }\n return {\n sampler: samplers[sampler],\n targetNodeId: targetNode.id,\n path: target.path as GLTFAnimationPath\n };\n });\n\n return {name, channels};\n });\n}\n\n/** Converts a scalar accessor into a cached JavaScript number array. */\nfunction accessorToJsArray1D(\n accessor: GLTFAccessorPostprocessed,\n accessorCache: Map<GLTFAccessorPostprocessed, number[]>\n): number[] {\n if (accessorCache.has(accessor)) {\n return accessorCache.get(accessor)!;\n }\n\n const {typedArray: array, components} = accessorToTypedArray(accessor);\n assert(components === 1, 'accessorToJsArray1D must have exactly 1 component');\n const result = Array.from(array);\n\n accessorCache.set(accessor, result);\n return result;\n}\n\n/** Converts a vector or matrix accessor into a cached JavaScript array-of-arrays. */\nfunction accessorToJsArray2D(\n accessor: GLTFAccessorPostprocessed,\n accessorCache: Map<GLTFAccessorPostprocessed, number[][]>\n): number[][] {\n if (accessorCache.has(accessor)) {\n return accessorCache.get(accessor)!;\n }\n\n const {typedArray: array, components} = accessorToTypedArray(accessor);\n assert(components > 1, 'accessorToJsArray2D must have more than 1 component');\n\n const result = [];\n\n // Slice array\n for (let i = 0; i < array.length; i += components) {\n result.push(Array.from(array.slice(i, i + components)));\n }\n\n accessorCache.set(accessor, result);\n return result;\n}\n\n/** Throws when the supplied condition is false. */\nfunction assert(condition: boolean, message?: string): asserts condition {\n if (!condition) {\n throw new Error(message);\n }\n}\n", "// luma.gl\n// SPDX-License-Identifier: MIT\n// Copyright (c) vis.gl contributors\n\nimport {Device} from '@luma.gl/core';\nimport {GroupNode} from '@luma.gl/engine';\nimport {GLTFPostprocessed} from '@loaders.gl/gltf';\nimport {Light} from '@luma.gl/shadertools';\nimport {parseGLTF, type ParseGLTFOptions} from '../parsers/parse-gltf';\nimport {parseGLTFLights} from '../parsers/parse-gltf-lights';\nimport {GLTFAnimator} from './gltf-animator';\nimport {parseGLTFAnimations} from '../parsers/parse-gltf-animations';\n\n/** Scenegraph bundle returned from a parsed glTF asset. */\nexport type GLTFScenegraphs = {\n /** Scene roots produced from the glTF scenes array. */\n scenes: GroupNode[];\n /** Animation controller for glTF animations. */\n animator: GLTFAnimator;\n /** Parsed punctual lights from the asset. */\n lights: Light[];\n\n /** Map from glTF mesh ids to generated mesh group nodes. */\n gltfMeshIdToNodeMap: Map<string, GroupNode>;\n /** Map from glTF node indices to generated scenegraph nodes. */\n gltfNodeIndexToNodeMap: Map<number, GroupNode>;\n /** Map from glTF node ids to generated scenegraph nodes. */\n gltfNodeIdToNodeMap: Map<string, GroupNode>;\n\n /** Original post-processed glTF document. */\n gltf: GLTFPostprocessed;\n};\n\n/** Converts a post-processed glTF asset into luma.gl scenegraph nodes and animation helpers. */\nexport function createScenegraphsFromGLTF(\n device: Device,\n gltf: GLTFPostprocessed,\n options?: ParseGLTFOptions\n): GLTFScenegraphs {\n const {scenes, gltfMeshIdToNodeMap, gltfNodeIdToNodeMap, gltfNodeIndexToNodeMap} = parseGLTF(\n device,\n gltf,\n options\n );\n\n const animations = parseGLTFAnimations(gltf);\n const animator = new GLTFAnimator({animations, gltfNodeIdToNodeMap});\n const lights = parseGLTFLights(gltf);\n\n return {\n scenes,\n animator,\n lights,\n gltfMeshIdToNodeMap,\n gltfNodeIdToNodeMap,\n gltfNodeIndexToNodeMap,\n gltf\n };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_constants", "import_core", "import_engine", "GLEnum", "import_core", "import_engine", "import_core", "import_core"]
7
7
  }
package/dist/index.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  export { loadPBREnvironment, type PBREnvironment } from "./pbr/pbr-environment.js";
2
2
  export { type ParsedPBRMaterial } from "./pbr/pbr-material.js";
3
3
  export { parsePBRMaterial, type ParsePBRMaterialOptions } from "./parsers/parse-pbr-material.js";
4
- export {} from "./pbr/pbr-environment.js";
5
4
  export { parseGLTFLights } from "./parsers/parse-gltf-lights.js";
6
- export { createScenegraphsFromGLTF } from "./gltf/create-scenegraph-from-gltf.js";
5
+ export { createScenegraphsFromGLTF, type GLTFScenegraphs } from "./gltf/create-scenegraph-from-gltf.js";
7
6
  export { GLTFAnimator } from "./gltf/gltf-animator.js";
8
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,kBAAkB,EAAE,KAAK,cAAc,EAAC,iCAA8B;AAC9E,OAAO,EAAC,KAAK,iBAAiB,EAAC,8BAA2B;AAC1D,OAAO,EAAC,gBAAgB,EAAE,KAAK,uBAAuB,EAAC,wCAAqC;AAC5F,OAAO,EAAE,iCAA8B;AACvC,OAAO,EAAC,eAAe,EAAC,uCAAoC;AAG5D,OAAO,EAAC,yBAAyB,EAAC,8CAA2C;AAC7E,OAAO,EAAC,YAAY,EAAC,gCAA6B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,kBAAkB,EAAE,KAAK,cAAc,EAAC,iCAA8B;AAC9E,OAAO,EAAC,KAAK,iBAAiB,EAAC,8BAA2B;AAC1D,OAAO,EAAC,gBAAgB,EAAE,KAAK,uBAAuB,EAAC,wCAAqC;AAC5F,OAAO,EAAC,eAAe,EAAC,uCAAoC;AAG5D,OAAO,EAAC,yBAAyB,EAAE,KAAK,eAAe,EAAC,8CAA2C;AACnG,OAAO,EAAC,YAAY,EAAC,gCAA6B"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uBAAuB;AAEvB,OAAO,EAAC,kBAAkB,EAAsB,iCAA8B;AAE9E,OAAO,EAAC,gBAAgB,EAA+B,wCAAqC;AAE5F,OAAO,EAAC,eAAe,EAAC,uCAAoC;AAE5D,+BAA+B;AAC/B,OAAO,EAAC,yBAAyB,EAAC,8CAA2C;AAC7E,OAAO,EAAC,YAAY,EAAC,gCAA6B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uBAAuB;AAEvB,OAAO,EAAC,kBAAkB,EAAsB,iCAA8B;AAE9E,OAAO,EAAC,gBAAgB,EAA+B,wCAAqC;AAC5F,OAAO,EAAC,eAAe,EAAC,uCAAoC;AAE5D,+BAA+B;AAC/B,OAAO,EAAC,yBAAyB,EAAuB,8CAA2C;AACnG,OAAO,EAAC,YAAY,EAAC,gCAA6B"}
@@ -1,4 +1,5 @@
1
1
  import { type GLTFPostprocessed } from '@loaders.gl/gltf';
2
2
  import { type GLTFAnimation } from "../gltf/animations/animations.js";
3
+ /** Parses glTF animation records into the runtime animation model used by `GLTFAnimator`. */
3
4
  export declare function parseGLTFAnimations(gltf: GLTFPostprocessed): GLTFAnimation[];
4
5
  //# sourceMappingURL=parse-gltf-animations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-gltf-animations.d.ts","sourceRoot":"","sources":["../../src/parsers/parse-gltf-animations.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiC,KAAK,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AACxF,OAAO,EACL,KAAK,aAAa,EAGnB,yCAAsC;AAIvC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,EAAE,CAkB5E"}
1
+ {"version":3,"file":"parse-gltf-animations.d.ts","sourceRoot":"","sources":["../../src/parsers/parse-gltf-animations.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiC,KAAK,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AACxF,OAAO,EAEL,KAAK,aAAa,EAGnB,yCAAsC;AAIvC,6FAA6F;AAC7F,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,EAAE,CA6B5E"}
@@ -2,39 +2,62 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  // Copyright (c) vis.gl contributors
4
4
  import { accessorToTypedArray } from "..//webgl-to-webgpu/convert-webgl-attribute.js";
5
+ /** Parses glTF animation records into the runtime animation model used by `GLTFAnimator`. */
5
6
  export function parseGLTFAnimations(gltf) {
6
7
  const gltfAnimations = gltf.animations || [];
8
+ const accessorCache1D = new Map();
9
+ const accessorCache2D = new Map();
7
10
  return gltfAnimations.map((animation, index) => {
8
11
  const name = animation.name || `Animation-${index}`;
9
12
  const samplers = animation.samplers.map(({ input, interpolation = 'LINEAR', output }) => ({
10
- input: accessorToJsArray(gltf.accessors[input]),
13
+ input: accessorToJsArray1D(gltf.accessors[input], accessorCache1D),
11
14
  interpolation,
12
- output: accessorToJsArray(gltf.accessors[output])
13
- }));
14
- const channels = animation.channels.map(({ sampler, target }) => ({
15
- sampler: samplers[sampler],
16
- target: gltf.nodes[target.node ?? 0],
17
- path: target.path
15
+ output: accessorToJsArray2D(gltf.accessors[output], accessorCache2D)
18
16
  }));
17
+ const channels = animation.channels.map(({ sampler, target }) => {
18
+ const targetNode = gltf.nodes[target.node ?? 0];
19
+ if (!targetNode) {
20
+ throw new Error(`Cannot find animation target ${target.node}`);
21
+ }
22
+ return {
23
+ sampler: samplers[sampler],
24
+ targetNodeId: targetNode.id,
25
+ path: target.path
26
+ };
27
+ });
19
28
  return { name, channels };
20
29
  });
21
30
  }
22
- //
23
- function accessorToJsArray(accessor) {
24
- if (!accessor._animation) {
25
- const { typedArray: array, components } = accessorToTypedArray(accessor);
26
- if (components === 1) {
27
- accessor._animation = Array.from(array);
28
- }
29
- else {
30
- // Slice array
31
- const slicedArray = [];
32
- for (let i = 0; i < array.length; i += components) {
33
- slicedArray.push(Array.from(array.slice(i, i + components)));
34
- }
35
- accessor._animation = slicedArray;
36
- }
31
+ /** Converts a scalar accessor into a cached JavaScript number array. */
32
+ function accessorToJsArray1D(accessor, accessorCache) {
33
+ if (accessorCache.has(accessor)) {
34
+ return accessorCache.get(accessor);
35
+ }
36
+ const { typedArray: array, components } = accessorToTypedArray(accessor);
37
+ assert(components === 1, 'accessorToJsArray1D must have exactly 1 component');
38
+ const result = Array.from(array);
39
+ accessorCache.set(accessor, result);
40
+ return result;
41
+ }
42
+ /** Converts a vector or matrix accessor into a cached JavaScript array-of-arrays. */
43
+ function accessorToJsArray2D(accessor, accessorCache) {
44
+ if (accessorCache.has(accessor)) {
45
+ return accessorCache.get(accessor);
46
+ }
47
+ const { typedArray: array, components } = accessorToTypedArray(accessor);
48
+ assert(components > 1, 'accessorToJsArray2D must have more than 1 component');
49
+ const result = [];
50
+ // Slice array
51
+ for (let i = 0; i < array.length; i += components) {
52
+ result.push(Array.from(array.slice(i, i + components)));
53
+ }
54
+ accessorCache.set(accessor, result);
55
+ return result;
56
+ }
57
+ /** Throws when the supplied condition is false. */
58
+ function assert(condition, message) {
59
+ if (!condition) {
60
+ throw new Error(message);
37
61
  }
38
- return accessor._animation;
39
62
  }
40
63
  //# sourceMappingURL=parse-gltf-animations.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-gltf-animations.js","sourceRoot":"","sources":["../../src/parsers/parse-gltf-animations.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,+BAA+B;AAC/B,oCAAoC;AASpC,OAAO,EAAC,oBAAoB,EAAC,uDAAoD;AAEjF,MAAM,UAAU,mBAAmB,CAAC,IAAuB;IACzD,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;IAC7C,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE;QAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,IAAI,aAAa,KAAK,EAAE,CAAC;QACpD,MAAM,QAAQ,GAA2B,SAAS,CAAC,QAAQ,CAAC,GAAG,CAC7D,CAAC,EAAC,KAAK,EAAE,aAAa,GAAG,QAAQ,EAAE,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;YAC9C,KAAK,EAAE,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAa;YAC3D,aAAa;YACb,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;SAClD,CAAC,CACH,CAAC;QACF,MAAM,QAAQ,GAA2B,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAC,OAAO,EAAE,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;YACtF,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC;YAC1B,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;YACpC,IAAI,EAAE,MAAM,CAAC,IAAoC;SAClD,CAAC,CAAC,CAAC;QACJ,OAAO,EAAC,IAAI,EAAE,QAAQ,EAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,EAAE;AAEF,SAAS,iBAAiB,CACxB,QAA0E;IAE1E,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;QACzB,MAAM,EAAC,UAAU,EAAE,KAAK,EAAE,UAAU,EAAC,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAEvE,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;YACrB,QAAQ,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,cAAc;YACd,MAAM,WAAW,GAAe,EAAE,CAAC;YACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC;gBAClD,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;YAC/D,CAAC;YACD,QAAQ,CAAC,UAAU,GAAG,WAAW,CAAC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,UAAU,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"parse-gltf-animations.js","sourceRoot":"","sources":["../../src/parsers/parse-gltf-animations.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,+BAA+B;AAC/B,oCAAoC;AAUpC,OAAO,EAAC,oBAAoB,EAAC,uDAAoD;AAEjF,6FAA6F;AAC7F,MAAM,UAAU,mBAAmB,CAAC,IAAuB;IACzD,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;IAC7C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAuC,CAAC;IACvE,MAAM,eAAe,GAAG,IAAI,GAAG,EAAyC,CAAC;IAEzE,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE;QAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,IAAI,aAAa,KAAK,EAAE,CAAC;QACpD,MAAM,QAAQ,GAA2B,SAAS,CAAC,QAAQ,CAAC,GAAG,CAC7D,CAAC,EAAC,KAAK,EAAE,aAAa,GAAG,QAAQ,EAAE,MAAM,EAAC,EAAE,EAAE,CAAC,CAAC;YAC9C,KAAK,EAAE,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC;YAClE,aAAa;YACb,MAAM,EAAE,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;SACrE,CAAC,CACH,CAAC;QAEF,MAAM,QAAQ,GAA2B,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAC,OAAO,EAAE,MAAM,EAAC,EAAE,EAAE;YACpF,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;YAChD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,gCAAgC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACjE,CAAC;YACD,OAAO;gBACL,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC;gBAC1B,YAAY,EAAE,UAAU,CAAC,EAAE;gBAC3B,IAAI,EAAE,MAAM,CAAC,IAAyB;aACvC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,EAAC,IAAI,EAAE,QAAQ,EAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,wEAAwE;AACxE,SAAS,mBAAmB,CAC1B,QAAmC,EACnC,aAAuD;IAEvD,IAAI,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChC,OAAO,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;IACtC,CAAC;IAED,MAAM,EAAC,UAAU,EAAE,KAAK,EAAE,UAAU,EAAC,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACvE,MAAM,CAAC,UAAU,KAAK,CAAC,EAAE,mDAAmD,CAAC,CAAC;IAC9E,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEjC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,qFAAqF;AACrF,SAAS,mBAAmB,CAC1B,QAAmC,EACnC,aAAyD;IAEzD,IAAI,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChC,OAAO,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;IACtC,CAAC;IAED,MAAM,EAAC,UAAU,EAAE,KAAK,EAAE,UAAU,EAAC,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACvE,MAAM,CAAC,UAAU,GAAG,CAAC,EAAE,qDAAqD,CAAC,CAAC;IAE9E,MAAM,MAAM,GAAG,EAAE,CAAC;IAElB,cAAc;IACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC;QAClD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mDAAmD;AACnD,SAAS,MAAM,CAAC,SAAkB,EAAE,OAAgB;IAClD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"parse-gltf-lights.d.ts","sourceRoot":"","sources":["../../src/parsers/parse-gltf-lights.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAwB,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAC/E,OAAO,KAAK,EAAmB,KAAK,EAAa,MAAM,sBAAsB,CAAC;AAE9E,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,KAAK,EAAE,CAyChE"}
1
+ {"version":3,"file":"parse-gltf-lights.d.ts","sourceRoot":"","sources":["../../src/parsers/parse-gltf-lights.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAwB,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAC/E,OAAO,KAAK,EAAmB,KAAK,EAAa,MAAM,sBAAsB,CAAC;AAE9E,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,IAAI,EAAE,iBAAiB,GAAG,KAAK,EAAE,CA8ChE"}
@@ -1,18 +1,22 @@
1
1
  import { Matrix4 } from '@math.gl/core';
2
2
  /** Parse KHR_lights_punctual extension into luma.gl light definitions */
3
3
  export function parseGLTFLights(gltf) {
4
- const lightDefs = gltf.extensions?.['KHR_lights_punctual']?.['lights'];
4
+ const lightDefs =
5
+ // `postProcessGLTF()` moves KHR_lights_punctual into `gltf.lights`.
6
+ gltf.lights ||
7
+ gltf.extensions?.['KHR_lights_punctual']?.['lights'];
5
8
  if (!lightDefs || !Array.isArray(lightDefs) || lightDefs.length === 0) {
6
9
  return [];
7
10
  }
8
11
  const lights = [];
9
12
  for (const node of gltf.nodes || []) {
10
- const nodeLight = node.extensions?.KHR_lights_punctual;
11
- if (!nodeLight || typeof nodeLight.light !== 'number') {
13
+ const lightIndex = node.light ??
14
+ node.extensions?.KHR_lights_punctual?.light;
15
+ if (typeof lightIndex !== 'number') {
12
16
  // eslint-disable-next-line no-continue
13
17
  continue;
14
18
  }
15
- const gltfLight = lightDefs[nodeLight.light];
19
+ const gltfLight = lightDefs[lightIndex];
16
20
  if (!gltfLight) {
17
21
  // eslint-disable-next-line no-continue
18
22
  continue;
@@ -37,10 +41,11 @@ export function parseGLTFLights(gltf) {
37
41
  }
38
42
  return lights;
39
43
  }
44
+ /**
45
+ * Converts a glTF punctual light attached to a node into a point light.
46
+ */
40
47
  function parsePointLight(node, color, intensity, range) {
41
- const position = node.translation
42
- ? [...node.translation]
43
- : [0, 0, 0];
48
+ const position = getNodePosition(node);
44
49
  let attenuation = [1, 0, 0];
45
50
  if (range !== undefined && range > 0) {
46
51
  attenuation = [1, 0, 1 / (range * range)];
@@ -53,12 +58,11 @@ function parsePointLight(node, color, intensity, range) {
53
58
  attenuation
54
59
  };
55
60
  }
61
+ /**
62
+ * Converts a glTF punctual light attached to a node into a directional light.
63
+ */
56
64
  function parseDirectionalLight(node, color, intensity) {
57
- let direction = [0, 0, -1];
58
- if (node.rotation) {
59
- const orientation = new Matrix4().fromQuaternion(node.rotation);
60
- direction = orientation.transformDirection([0, 0, -1]);
61
- }
65
+ const direction = getNodeDirection(node);
62
66
  return {
63
67
  type: 'directional',
64
68
  direction,
@@ -66,4 +70,28 @@ function parseDirectionalLight(node, color, intensity) {
66
70
  intensity
67
71
  };
68
72
  }
73
+ /**
74
+ * Resolves the world-space position of a glTF node from its matrix or translation.
75
+ */
76
+ function getNodePosition(node) {
77
+ if (node.matrix) {
78
+ return new Matrix4(node.matrix).transformAsPoint([0, 0, 0]);
79
+ }
80
+ if (node.translation) {
81
+ return [...node.translation];
82
+ }
83
+ return [0, 0, 0];
84
+ }
85
+ /**
86
+ * Resolves the forward direction of a glTF node from its matrix or rotation.
87
+ */
88
+ function getNodeDirection(node) {
89
+ if (node.matrix) {
90
+ return new Matrix4(node.matrix).transformDirection([0, 0, -1]);
91
+ }
92
+ if (node.rotation) {
93
+ return new Matrix4().fromQuaternion(node.rotation).transformDirection([0, 0, -1]);
94
+ }
95
+ return [0, 0, -1];
96
+ }
69
97
  //# sourceMappingURL=parse-gltf-lights.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse-gltf-lights.js","sourceRoot":"","sources":["../../src/parsers/parse-gltf-lights.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"parse-gltf-lights.js","sourceRoot":"","sources":["../../src/parsers/parse-gltf-lights.ts"],"names":[],"mappings":"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"}