@loaders.gl/gltf
Version:
Framework-independent loader for the glTF format
101 lines (88 loc) • 3.96 kB
text/typescript
/* 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<void>;
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;
}