/* eslint-disable camelcase */ import {GLTF} from '../types/gltf-json-schema'; import type {GLTFLoaderOptions} from '../../gltf-loader'; import {GLTFWriterOptions} from '../../gltf-writer'; // GLTF 1.0 extensions (decode only) // import * as KHR_binary_gltf from './KHR_draco_mesh_compression'; // GLTF 2.0 Vendor extensions import * as EXT_mesh_features from '../extensions/EXT_mesh_features'; import * as EXT_structural_metadata from '../extensions/EXT_structural_metadata'; // GLTF 2.0 Khronos extensions (decode/encode) import * as EXT_meshopt_compression from '../extensions/EXT_meshopt_compression'; import * as EXT_texture_webp from '../extensions/EXT_texture_webp'; import * as KHR_texture_basisu from '../extensions/KHR_texture_basisu'; import * as KHR_draco_mesh_compression from '../extensions/KHR_draco_mesh_compression'; import * as KHR_texture_transform from '../extensions/KHR_texture_transform'; // Deprecated. These should be handled by rendering library (e.g. luma.gl), not the loader. import * as KHR_lights_punctual from '../extensions/deprecated/KHR_lights_punctual'; import * as KHR_materials_unlit from '../extensions/deprecated/KHR_materials_unlit'; import * as KHR_techniques_webgl from '../extensions/deprecated/KHR_techniques_webgl'; import * as EXT_feature_metadata from '../extensions/deprecated/EXT_feature_metadata'; type GLTFExtensionPlugin = { name: string; preprocess?: (gltfData: {json: GLTF}, options: GLTFLoaderOptions, context) => void; decode?: ( gltfData: { json: GLTF; buffers: {arrayBuffer: ArrayBuffer; byteOffset: number; byteLength: number}[]; }, options: GLTFLoaderOptions, context ) => Promise; encode?: (gltfData: {json: GLTF}, options: GLTFWriterOptions) => void; }; /** * List of extensions processed by the GLTFLoader * Note that may extensions can only be handled on the rendering stage and are left out here * These are just extensions that can be handled fully or partially during loading. */ export const EXTENSIONS: GLTFExtensionPlugin[] = [ // 1.0 // KHR_binary_gltf is handled separately - must be processed before other parsing starts // KHR_binary_gltf, // 2.0 EXT_structural_metadata, EXT_mesh_features, EXT_meshopt_compression, EXT_texture_webp, // Basisu should come after webp, we want basisu to be preferred if both are provided KHR_texture_basisu, KHR_draco_mesh_compression, KHR_lights_punctual, KHR_materials_unlit, KHR_techniques_webgl, KHR_texture_transform, EXT_feature_metadata ]; /** * List of extensions processed by the GLTFWriter */ const EXTENSIONS_ENCODING: GLTFExtensionPlugin[] = [EXT_structural_metadata, EXT_mesh_features]; /** Call before any resource loading starts */ export function preprocessExtensions(gltf, options: GLTFLoaderOptions = {}, context?) { const extensions = EXTENSIONS.filter((extension) => useExtension(extension.name, options)); for (const extension of extensions) { extension.preprocess?.(gltf, options, context); } } /** Call after resource loading */ export async function decodeExtensions(gltf, options: GLTFLoaderOptions = {}, context?) { const extensions = EXTENSIONS.filter((extension) => useExtension(extension.name, options)); for (const extension of extensions) { // Note: We decode async extensions sequentially, this might not be necessary // Currently we only have Draco, but when we add Basis we may revisit await extension.decode?.(gltf, options, context); } } /** Call before resource writing */ export function encodeExtensions(gltf, options: GLTFWriterOptions = {}) { for (const extension of EXTENSIONS_ENCODING) { gltf = extension.encode?.(gltf, options) ?? gltf; } return gltf; } function useExtension(extensionName: string, options: GLTFLoaderOptions) { const excludes = options?.gltf?.excludeExtensions || {}; const exclude = extensionName in excludes && !excludes[extensionName]; return !exclude; }