@aura3d/assets 1.3.3 → 1.4.1
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.
- package/dist/GLTFLoader.js +1 -0
- package/dist/GLTFLoader.js.map +1 -1
- package/dist/GLTFRenderResources.d.ts.map +1 -1
- package/dist/GLTFRenderResources.js +1 -0
- package/dist/GLTFRenderResources.js.map +1 -1
- package/package.json +38 -5
- package/src/AdvancedAssetCorpus.ts +0 -454
- package/src/AssetBundleCacheFixtures.ts +0 -290
- package/src/AssetCache.ts +0 -76
- package/src/AssetCompatibility.ts +0 -224
- package/src/AssetCorpus.ts +0 -329
- package/src/AssetDependencyGraph.ts +0 -83
- package/src/AssetHandle.ts +0 -74
- package/src/AssetImportPreflight.ts +0 -179
- package/src/AssetInspection.ts +0 -706
- package/src/AssetLoader.ts +0 -36
- package/src/AssetManager.ts +0 -211
- package/src/AssetRegistry.ts +0 -44
- package/src/AssetRenderDefaults.ts +0 -36
- package/src/AudioLoader.ts +0 -41
- package/src/BlenderExportValidation.ts +0 -227
- package/src/CarConceptMaterialStability.ts +0 -1405
- package/src/EXRLoader.ts +0 -1
- package/src/ExternalParityGLTFCorpus.ts +0 -65
- package/src/GLTFAnimationRuntime.ts +0 -1416
- package/src/GLTFAutoFit.ts +0 -133
- package/src/GLTFCompressionDecoders.ts +0 -190
- package/src/GLTFExtensionSupport.ts +0 -138
- package/src/GLTFLoader.ts +0 -4059
- package/src/GLTFRenderResources.ts +0 -2269
- package/src/HDRLoader.ts +0 -1
- package/src/ImageLoader.ts +0 -52
- package/src/ImportPipeline.ts +0 -148
- package/src/KTX2BasisTextureTranscoder.ts +0 -225
- package/src/LoadContext.ts +0 -60
- package/src/MaterialLoader.ts +0 -166
- package/src/MeshOptimization.ts +0 -93
- package/src/OBJLoader.ts +0 -551
- package/src/SceneAnalysisFixtures.ts +0 -438
- package/src/SceneLoader.ts +0 -62
- package/src/ShaderLoader.ts +0 -30
- package/src/TextureLoader.ts +0 -30
- package/src/TexturePipeline.ts +0 -96
- package/src/TextureStreaming.ts +0 -20
- package/src/WorkerAssetJobs.ts +0 -56
- package/src/advanced-gallery/index.ts +0 -18
- package/src/asset-corpus/GLTFSceneLoader.ts +0 -9
- package/src/asset-corpus/ProductionAssetCorpus.ts +0 -230
- package/src/asset-corpus/ProductionAssetPipeline.ts +0 -5
- package/src/asset-corpus/ProductionGLTFRenderPipeline.ts +0 -182
- package/src/asset-corpus/ProductionHDRTextureLoader.ts +0 -2
- package/src/asset-corpus/ProductionKTX2TextureLoader.ts +0 -2
- package/src/asset-corpus/ProductionTextureLoader.ts +0 -2
- package/src/asset-corpus/index.ts +0 -29
- package/src/browser-index.ts +0 -229
- package/src/createRenderableScene.ts +0 -128
- package/src/index.ts +0 -325
- package/src/loadRenderableAsset.ts +0 -67
- package/src/loaders/CubeTextureLoader.ts +0 -8
- package/src/loaders/EXRLoader.ts +0 -10
- package/src/loaders/HDRLoader.ts +0 -7
- package/src/loaders/KTX2Loader.ts +0 -7
- package/src/loaders/LoaderDiagnostics.ts +0 -36
- package/src/loaders/MTLLoader.ts +0 -20
- package/src/loaders/OBJLoader.ts +0 -24
- package/src/loaders/TextureLoader.ts +0 -14
- package/src/loaders/ThreeCompatGLTFLoader.ts +0 -19
- package/src/loaders/index.ts +0 -14
- package/src/threejs-compatibility/ThreeCompatAssetProvenance.ts +0 -51
- package/src/threejs-compatibility/ThreeCompatAssetRegistry.ts +0 -61
- package/src/threejs-example-parity/index.ts +0 -262
- package/tests/assets.test.ts +0 -393
- package/tsconfig.json +0 -7
package/src/GLTFAutoFit.ts
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import type { CameraFrameBounds } from "@aura3d/rendering";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Up-axis of the source asset. Most glTF assets are Y-up (spec default), but
|
|
5
|
-
* many catalog exports (CAD/Blender Z-up pipelines) ship Z-up geometry.
|
|
6
|
-
*/
|
|
7
|
-
export type GLTFUpAxis = "y" | "z";
|
|
8
|
-
|
|
9
|
-
export interface AutoFitTransform {
|
|
10
|
-
/** Uniform scale to apply so the model reaches the target height. */
|
|
11
|
-
readonly scale: number;
|
|
12
|
-
/**
|
|
13
|
-
* Translation (post-scale) that recenters the model horizontally and places
|
|
14
|
-
* its lowest point ("feet") at y = 0.
|
|
15
|
-
*/
|
|
16
|
-
readonly translation: readonly [number, number, number];
|
|
17
|
-
/**
|
|
18
|
-
* Quaternion (x, y, z, w) that rotates source up-axis to Y-up, applied before
|
|
19
|
-
* scale/translation. Identity `[0, 0, 0, 1]` when no correction is needed.
|
|
20
|
-
*/
|
|
21
|
-
readonly rotation: readonly [number, number, number, number];
|
|
22
|
-
/** The up-axis correction that was applied (`"none"` when already Y-up). */
|
|
23
|
-
readonly upAxisCorrection: "none" | "z-to-y";
|
|
24
|
-
/** The largest source extent, useful for diagnostics/logging. */
|
|
25
|
-
readonly sourceExtent: number;
|
|
26
|
-
/** The resulting model height after the transform is applied. */
|
|
27
|
-
readonly fittedHeight: number;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface AutoFitOptions {
|
|
31
|
-
/** Target height (in world units) the model should occupy. Default 1.6. */
|
|
32
|
-
readonly targetHeight?: number;
|
|
33
|
-
/**
|
|
34
|
-
* Source up-axis. When omitted, the loader keeps the asset as-authored
|
|
35
|
-
* (`"y"`); pass `"z"` for Z-up catalog exports to rotate them upright.
|
|
36
|
-
*/
|
|
37
|
-
readonly upAxis?: GLTFUpAxis;
|
|
38
|
-
/**
|
|
39
|
-
* Recenter the model on the ground plane (feet at y = 0, centered in X/Z).
|
|
40
|
-
* Default `true`. When `false`, only scale (and optional rotation) is returned.
|
|
41
|
-
*/
|
|
42
|
-
readonly recenter?: boolean;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const IDENTITY_ROTATION = [0, 0, 0, 1] as const;
|
|
46
|
-
// Quaternion for -90deg about X, which maps Z-up geometry to Y-up.
|
|
47
|
-
const Z_TO_Y_ROTATION = [-Math.SQRT1_2, 0, 0, Math.SQRT1_2] as const;
|
|
48
|
-
const DEFAULT_TARGET_HEIGHT = 1.6;
|
|
49
|
-
const MIN_EXTENT_EPSILON = 1e-6;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Compute a fit-to-height transform for a loaded glTF scene's bounds.
|
|
53
|
-
*
|
|
54
|
-
* Catalog models vary wildly in scale and orientation: one Sketchfab export had
|
|
55
|
-
* an extent of ~1821 units while a Kenney prop is ~1 unit, and Z-up CAD exports
|
|
56
|
-
* arrive lying on their side. This helper returns a single uniform scale +
|
|
57
|
-
* translation (and optional up-axis rotation) so any model fits a target height
|
|
58
|
-
* with its feet on the ground plane, independent of the renderer.
|
|
59
|
-
*
|
|
60
|
-
* The returned transform is meant to be applied in order: rotation, then scale,
|
|
61
|
-
* then translation.
|
|
62
|
-
*/
|
|
63
|
-
export function computeAutoFitTransform(
|
|
64
|
-
bounds: CameraFrameBounds,
|
|
65
|
-
options: AutoFitOptions = {}
|
|
66
|
-
): AutoFitTransform {
|
|
67
|
-
const targetHeight = options.targetHeight ?? DEFAULT_TARGET_HEIGHT;
|
|
68
|
-
if (!Number.isFinite(targetHeight) || targetHeight <= 0) {
|
|
69
|
-
throw new Error("computeAutoFitTransform targetHeight must be a positive finite number.");
|
|
70
|
-
}
|
|
71
|
-
const recenter = options.recenter ?? true;
|
|
72
|
-
const upAxisCorrection = options.upAxis === "z" ? "z-to-y" : "none";
|
|
73
|
-
const rotation = upAxisCorrection === "z-to-y" ? Z_TO_Y_ROTATION : IDENTITY_ROTATION;
|
|
74
|
-
|
|
75
|
-
// Reorient the AABB into the post-rotation (Y-up) frame before measuring height.
|
|
76
|
-
const oriented = upAxisCorrection === "z-to-y" ? rotateBoundsZtoY(bounds) : bounds;
|
|
77
|
-
|
|
78
|
-
const size: readonly [number, number, number] = [
|
|
79
|
-
Math.max(0, oriented.max[0] - oriented.min[0]),
|
|
80
|
-
Math.max(0, oriented.max[1] - oriented.min[1]),
|
|
81
|
-
Math.max(0, oriented.max[2] - oriented.min[2])
|
|
82
|
-
];
|
|
83
|
-
const sourceExtent = Math.max(size[0], size[1], size[2]);
|
|
84
|
-
const height = size[1];
|
|
85
|
-
const scale = height > MIN_EXTENT_EPSILON ? targetHeight / height : 1;
|
|
86
|
-
|
|
87
|
-
let translation: readonly [number, number, number] = [0, 0, 0];
|
|
88
|
-
if (recenter) {
|
|
89
|
-
const centerX = (oriented.min[0] + oriented.max[0]) / 2;
|
|
90
|
-
const centerZ = (oriented.min[2] + oriented.max[2]) / 2;
|
|
91
|
-
const floorY = oriented.min[1];
|
|
92
|
-
translation = [-centerX * scale, -floorY * scale, -centerZ * scale];
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return {
|
|
96
|
-
scale,
|
|
97
|
-
translation,
|
|
98
|
-
rotation,
|
|
99
|
-
upAxisCorrection,
|
|
100
|
-
sourceExtent,
|
|
101
|
-
fittedHeight: height * scale
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Convenience wrapper that reads `.bounds` off an object (e.g. a
|
|
107
|
-
* `GLTFRenderResources` instance) and computes the fit transform.
|
|
108
|
-
*/
|
|
109
|
-
export function autoFitGLTFScene(
|
|
110
|
-
scene: { readonly bounds: CameraFrameBounds },
|
|
111
|
-
options: AutoFitOptions = {}
|
|
112
|
-
): AutoFitTransform {
|
|
113
|
-
return computeAutoFitTransform(scene.bounds, options);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Rotate an axis-aligned bounding box by the Z-up -> Y-up correction. Because the
|
|
118
|
-
* rotation is axis-aligned (-90deg about X), this maps each source axis to a
|
|
119
|
-
* destination axis exactly: x -> x, y -> z, z -> -y.
|
|
120
|
-
*/
|
|
121
|
-
function rotateBoundsZtoY(bounds: CameraFrameBounds): CameraFrameBounds {
|
|
122
|
-
const xs = [bounds.min[0], bounds.max[0]];
|
|
123
|
-
const ys = [bounds.min[1], bounds.max[1]];
|
|
124
|
-
const zs = [bounds.min[2], bounds.max[2]];
|
|
125
|
-
// mapped axes: newX = x, newY = z, newZ = -y
|
|
126
|
-
const newX = xs;
|
|
127
|
-
const newY = zs;
|
|
128
|
-
const newZ = ys.map((value) => -value);
|
|
129
|
-
return {
|
|
130
|
-
min: [Math.min(...newX), Math.min(...newY), Math.min(...newZ)],
|
|
131
|
-
max: [Math.max(...newX), Math.max(...newY), Math.max(...newZ)]
|
|
132
|
-
};
|
|
133
|
-
}
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
GLTFDracoDecodeDescriptor,
|
|
3
|
-
GLTFDracoDecodedPrimitive,
|
|
4
|
-
GLTFDracoDecoder,
|
|
5
|
-
GLTFMeshoptDecodeDescriptor,
|
|
6
|
-
GLTFMeshoptDecoder
|
|
7
|
-
} from "./GLTFLoader";
|
|
8
|
-
|
|
9
|
-
export interface GLTFMeshoptDecoderModule {
|
|
10
|
-
readonly ready?: PromiseLike<void>;
|
|
11
|
-
decodeGltfBuffer(
|
|
12
|
-
target: Uint8Array,
|
|
13
|
-
count: number,
|
|
14
|
-
size: number,
|
|
15
|
-
source: Uint8Array,
|
|
16
|
-
mode: GLTFMeshoptDecodeDescriptor["mode"],
|
|
17
|
-
filter?: GLTFMeshoptDecodeDescriptor["filter"]
|
|
18
|
-
): void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface GLTFDracoStatus {
|
|
22
|
-
ok(): boolean;
|
|
23
|
-
error_msg(): string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface GLTFDracoDecoderBuffer {
|
|
27
|
-
Init(data: Uint8Array, byteLength: number): void;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface GLTFDracoMesh {
|
|
31
|
-
num_points(): number;
|
|
32
|
-
num_faces(): number;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface GLTFDracoAttribute {
|
|
36
|
-
num_components(): number;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface GLTFDracoNumericArray {
|
|
40
|
-
size(): number;
|
|
41
|
-
GetValue(index: number): number;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface GLTFDracoDecoderInstance {
|
|
45
|
-
GetEncodedGeometryType(buffer: GLTFDracoDecoderBuffer): number;
|
|
46
|
-
DecodeBufferToMesh(buffer: GLTFDracoDecoderBuffer, mesh: GLTFDracoMesh): GLTFDracoStatus;
|
|
47
|
-
GetAttributeByUniqueId(mesh: GLTFDracoMesh, uniqueId: number): GLTFDracoAttribute | null;
|
|
48
|
-
GetAttributeFloatForAllPoints(mesh: GLTFDracoMesh, attribute: GLTFDracoAttribute, out: GLTFDracoNumericArray): boolean;
|
|
49
|
-
GetFaceFromMesh(mesh: GLTFDracoMesh, faceIndex: number, out: GLTFDracoNumericArray): boolean;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface GLTFDracoDecoderModule {
|
|
53
|
-
readonly TRIANGULAR_MESH: number;
|
|
54
|
-
readonly Decoder: new () => GLTFDracoDecoderInstance;
|
|
55
|
-
readonly DecoderBuffer: new () => GLTFDracoDecoderBuffer;
|
|
56
|
-
readonly Mesh: new () => GLTFDracoMesh;
|
|
57
|
-
readonly DracoFloat32Array: new () => GLTFDracoNumericArray;
|
|
58
|
-
readonly DracoInt32Array: new () => GLTFDracoNumericArray;
|
|
59
|
-
destroy?(object: unknown): void;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function createMeshoptDecoder(module: GLTFMeshoptDecoderModule): GLTFMeshoptDecoder {
|
|
63
|
-
return async (source, descriptor) => {
|
|
64
|
-
if (module.ready) {
|
|
65
|
-
await module.ready;
|
|
66
|
-
}
|
|
67
|
-
const target = new Uint8Array(descriptor.count * descriptor.byteStride);
|
|
68
|
-
module.decodeGltfBuffer(
|
|
69
|
-
target,
|
|
70
|
-
descriptor.count,
|
|
71
|
-
descriptor.byteStride,
|
|
72
|
-
source,
|
|
73
|
-
descriptor.mode,
|
|
74
|
-
descriptor.filter
|
|
75
|
-
);
|
|
76
|
-
return target;
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function createDracoDecoder(module: GLTFDracoDecoderModule): GLTFDracoDecoder {
|
|
81
|
-
return (source, descriptor) => {
|
|
82
|
-
const allocated: unknown[] = [];
|
|
83
|
-
const decoder = track(new module.Decoder(), allocated);
|
|
84
|
-
const buffer = track(new module.DecoderBuffer(), allocated);
|
|
85
|
-
const mesh = track(new module.Mesh(), allocated);
|
|
86
|
-
|
|
87
|
-
try {
|
|
88
|
-
buffer.Init(source, source.byteLength);
|
|
89
|
-
const geometryType = decoder.GetEncodedGeometryType(buffer);
|
|
90
|
-
if (geometryType !== module.TRIANGULAR_MESH) {
|
|
91
|
-
throw new Error(`glTF Draco primitive ${descriptorLabel(descriptor)} must decode to a triangular mesh`);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const status = decoder.DecodeBufferToMesh(buffer, mesh);
|
|
95
|
-
if (!status.ok()) {
|
|
96
|
-
throw new Error(`glTF Draco primitive ${descriptorLabel(descriptor)} decode failed: ${status.error_msg()}`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
attributes: decodeDracoAttributes(module, decoder, mesh, descriptor, allocated),
|
|
101
|
-
indices: decodeDracoIndices(module, decoder, mesh, descriptor, allocated)
|
|
102
|
-
};
|
|
103
|
-
} finally {
|
|
104
|
-
destroyAllocated(module, allocated);
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function decodeDracoAttributes(
|
|
110
|
-
module: GLTFDracoDecoderModule,
|
|
111
|
-
decoder: GLTFDracoDecoderInstance,
|
|
112
|
-
mesh: GLTFDracoMesh,
|
|
113
|
-
descriptor: GLTFDracoDecodeDescriptor,
|
|
114
|
-
allocated: unknown[]
|
|
115
|
-
): GLTFDracoDecodedPrimitive["attributes"] {
|
|
116
|
-
const pointCount = mesh.num_points();
|
|
117
|
-
const attributes: Record<string, number[][]> = {};
|
|
118
|
-
|
|
119
|
-
for (const [semantic, uniqueId] of Object.entries(descriptor.attributes)) {
|
|
120
|
-
const attribute = decoder.GetAttributeByUniqueId(mesh, uniqueId);
|
|
121
|
-
if (!attribute) {
|
|
122
|
-
throw new Error(`glTF Draco primitive ${descriptorLabel(descriptor)} is missing decoded attribute ${semantic} unique id ${uniqueId}`);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const componentCount = attribute.num_components();
|
|
126
|
-
if (!Number.isInteger(componentCount) || componentCount <= 0) {
|
|
127
|
-
throw new Error(`glTF Draco primitive ${descriptorLabel(descriptor)} decoded attribute ${semantic} has invalid component count ${componentCount}`);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const values = track(new module.DracoFloat32Array(), allocated);
|
|
131
|
-
if (!decoder.GetAttributeFloatForAllPoints(mesh, attribute, values)) {
|
|
132
|
-
throw new Error(`glTF Draco primitive ${descriptorLabel(descriptor)} failed to read decoded attribute ${semantic}`);
|
|
133
|
-
}
|
|
134
|
-
if (values.size() !== pointCount * componentCount) {
|
|
135
|
-
throw new Error(`glTF Draco primitive ${descriptorLabel(descriptor)} decoded attribute ${semantic} has ${values.size()} values but expected ${pointCount * componentCount}`);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const rows: number[][] = [];
|
|
139
|
-
for (let pointIndex = 0; pointIndex < pointCount; pointIndex += 1) {
|
|
140
|
-
const row: number[] = [];
|
|
141
|
-
for (let componentIndex = 0; componentIndex < componentCount; componentIndex += 1) {
|
|
142
|
-
row.push(values.GetValue(pointIndex * componentCount + componentIndex));
|
|
143
|
-
}
|
|
144
|
-
rows.push(row);
|
|
145
|
-
}
|
|
146
|
-
attributes[semantic] = rows;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return attributes;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function decodeDracoIndices(
|
|
153
|
-
module: GLTFDracoDecoderModule,
|
|
154
|
-
decoder: GLTFDracoDecoderInstance,
|
|
155
|
-
mesh: GLTFDracoMesh,
|
|
156
|
-
descriptor: GLTFDracoDecodeDescriptor,
|
|
157
|
-
allocated: unknown[]
|
|
158
|
-
): number[] | undefined {
|
|
159
|
-
const faceCount = mesh.num_faces();
|
|
160
|
-
if (faceCount === 0) return undefined;
|
|
161
|
-
|
|
162
|
-
const face = track(new module.DracoInt32Array(), allocated);
|
|
163
|
-
const indices: number[] = [];
|
|
164
|
-
for (let faceIndex = 0; faceIndex < faceCount; faceIndex += 1) {
|
|
165
|
-
if (!decoder.GetFaceFromMesh(mesh, faceIndex, face)) {
|
|
166
|
-
throw new Error(`glTF Draco primitive ${descriptorLabel(descriptor)} failed to read decoded face ${faceIndex}`);
|
|
167
|
-
}
|
|
168
|
-
if (face.size() !== 3) {
|
|
169
|
-
throw new Error(`glTF Draco primitive ${descriptorLabel(descriptor)} decoded face ${faceIndex} has ${face.size()} indices but expected 3`);
|
|
170
|
-
}
|
|
171
|
-
indices.push(face.GetValue(0), face.GetValue(1), face.GetValue(2));
|
|
172
|
-
}
|
|
173
|
-
return indices;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function track<T>(value: T, allocated: unknown[]): T {
|
|
177
|
-
allocated.push(value);
|
|
178
|
-
return value;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function destroyAllocated(module: GLTFDracoDecoderModule, allocated: unknown[]): void {
|
|
182
|
-
if (!module.destroy) return;
|
|
183
|
-
for (let index = allocated.length - 1; index >= 0; index -= 1) {
|
|
184
|
-
module.destroy(allocated[index]);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function descriptorLabel(descriptor: GLTFDracoDecodeDescriptor): string {
|
|
189
|
-
return `${descriptor.meshIndex}/${descriptor.primitiveIndex}`;
|
|
190
|
-
}
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
export type GLTFExtensionSupportFamily =
|
|
2
|
-
| "texture"
|
|
3
|
-
| "geometry"
|
|
4
|
-
| "material"
|
|
5
|
-
| "animation"
|
|
6
|
-
| "scene"
|
|
7
|
-
| "compression";
|
|
8
|
-
|
|
9
|
-
export type GLTFExtensionSupportStatus =
|
|
10
|
-
| "runtime-supported"
|
|
11
|
-
| "decoder-required"
|
|
12
|
-
| "parsed-with-limits"
|
|
13
|
-
| "diagnostic-only"
|
|
14
|
-
| "unsupported";
|
|
15
|
-
|
|
16
|
-
export interface GLTFExtensionSupportEntry {
|
|
17
|
-
readonly name: string;
|
|
18
|
-
readonly family: GLTFExtensionSupportFamily;
|
|
19
|
-
readonly status: GLTFExtensionSupportStatus;
|
|
20
|
-
readonly requiredAccepted: boolean;
|
|
21
|
-
readonly publicApi: readonly string[];
|
|
22
|
-
readonly decoder?: "draco" | "meshopt" | "ktx2-basis";
|
|
23
|
-
readonly knownLimits: readonly string[];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export interface GLTFExtensionSupportEvaluation {
|
|
27
|
-
readonly schemaVersion: "gltf-extension-support";
|
|
28
|
-
readonly requested: readonly GLTFExtensionSupportEntry[];
|
|
29
|
-
readonly supported: readonly GLTFExtensionSupportEntry[];
|
|
30
|
-
readonly runtimeSupported: readonly GLTFExtensionSupportEntry[];
|
|
31
|
-
readonly parsedWithLimits: readonly GLTFExtensionSupportEntry[];
|
|
32
|
-
readonly diagnosticOnly: readonly GLTFExtensionSupportEntry[];
|
|
33
|
-
readonly unsupportedUsed: readonly string[];
|
|
34
|
-
readonly unsupportedRequired: readonly string[];
|
|
35
|
-
readonly notAcceptedUsed: readonly string[];
|
|
36
|
-
readonly decoderRequired: readonly GLTFExtensionSupportEntry[];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export const GLTF_EXTENSION_SUPPORT_MATRIX: readonly GLTFExtensionSupportEntry[] = [
|
|
40
|
-
entry("EXT_texture_avif", "texture", "runtime-supported", ["GLTFLoader"], []),
|
|
41
|
-
entry("EXT_texture_webp", "texture", "runtime-supported", ["GLTFLoader"], []),
|
|
42
|
-
entry("KHR_texture_basisu", "compression", "decoder-required", ["GLTFLoader", "createGLTFRenderResources", "transcodeKTX2BasisTexture"], ["Requires loaders.gl Basis/KTX2 transcoder modules at render-resource creation time."], "ktx2-basis"),
|
|
43
|
-
entry("KHR_texture_transform", "texture", "runtime-supported", ["GLTFLoader", "TexturedPBRMaterial"], []),
|
|
44
|
-
entry("KHR_mesh_quantization", "geometry", "runtime-supported", ["GLTFLoader"], []),
|
|
45
|
-
entry("KHR_draco_mesh_compression", "compression", "decoder-required", ["GLTFLoader", "createDracoDecoder"], ["Requires an injected Draco decoder module."], "draco"),
|
|
46
|
-
entry("EXT_meshopt_compression", "compression", "decoder-required", ["GLTFLoader", "createMeshoptDecoder"], ["Requires an injected meshoptimizer decoder module."], "meshopt"),
|
|
47
|
-
entry("KHR_meshopt_compression", "compression", "decoder-required", ["GLTFLoader", "createMeshoptDecoder"], ["Requires an injected meshoptimizer decoder module."], "meshopt"),
|
|
48
|
-
entry("EXT_mesh_gpu_instancing", "geometry", "runtime-supported", ["GLTFLoader", "Renderable.instanceTransforms", "ProductionWebGL2Renderer"], ["Supports TRS instance attributes; custom per-instance material attributes remain out of scope."]),
|
|
49
|
-
entry("KHR_lights_punctual", "scene", "runtime-supported", ["GLTFLoader", "Scene", "ProductionWebGL2Renderer"], []),
|
|
50
|
-
entry("KHR_materials_unlit", "material", "runtime-supported", ["GLTFLoader", "UnlitMaterial"], []),
|
|
51
|
-
entry("KHR_materials_emissive_strength", "material", "runtime-supported", ["GLTFLoader", "TexturedPBRMaterial"], []),
|
|
52
|
-
entry("KHR_materials_clearcoat", "material", "parsed-with-limits", ["GLTFLoader", "TexturedPBRMaterial"], ["Clearcoat factors/textures are mapped; full reference BRDF parity still requires visual corpus acceptance."]),
|
|
53
|
-
entry("KHR_materials_transmission", "material", "parsed-with-limits", ["GLTFLoader", "TexturedPBRMaterial"], ["Transmission is mapped to the current WebGL2 fallback path; screen-space/refraction parity remains blocked."]),
|
|
54
|
-
entry("KHR_materials_diffuse_transmission", "material", "parsed-with-limits", ["GLTFLoader", "TexturedPBRMaterial"], ["Diffuse transmission factors/textures are mapped; full reference energy parity remains blocked."]),
|
|
55
|
-
entry("KHR_materials_volume", "material", "parsed-with-limits", ["GLTFLoader", "TexturedPBRMaterial"], ["Volume attenuation/thickness are mapped for fallback rendering, not full volumetric path tracing."]),
|
|
56
|
-
entry("KHR_materials_ior", "material", "runtime-supported", ["GLTFLoader", "TexturedPBRMaterial"], []),
|
|
57
|
-
entry("KHR_materials_specular", "material", "parsed-with-limits", ["GLTFLoader", "TexturedPBRMaterial"], ["Specular factors/textures are mapped; full reference BRDF parity still requires visual corpus acceptance."]),
|
|
58
|
-
entry("KHR_materials_sheen", "material", "parsed-with-limits", ["GLTFLoader", "TexturedPBRMaterial"], ["Sheen factors/textures are mapped; cloth reference parity remains blocked."]),
|
|
59
|
-
entry("KHR_materials_anisotropy", "material", "parsed-with-limits", ["GLTFLoader", "TexturedPBRMaterial"], ["Anisotropy factors/textures are mapped; tangent-space visual parity remains under review."]),
|
|
60
|
-
entry("KHR_materials_iridescence", "material", "parsed-with-limits", ["GLTFLoader", "TexturedPBRMaterial"], ["Iridescence factors/textures are mapped; thin-film reference parity remains under review."]),
|
|
61
|
-
entry("KHR_materials_dispersion", "material", "parsed-with-limits", ["GLTFLoader", "TexturedPBRMaterial"], ["Dispersion factor is preserved for material fallback; spectral dispersion rendering remains blocked."]),
|
|
62
|
-
entry("KHR_materials_pbrSpecularGlossiness", "material", "parsed-with-limits", ["GLTFLoader", "TexturedPBRMaterial"], ["Spec/gloss assets are converted into the current metallic-roughness runtime contract."]),
|
|
63
|
-
entry("KHR_materials_variants", "material", "parsed-with-limits", ["GLTFLoader"], ["Variant mappings are loaded; authoring/persistence workflow parity remains blocked."]),
|
|
64
|
-
entry("KHR_animation_pointer", "animation", "diagnostic-only", ["GLTFLoader"], ["Optional animation pointer channels are reported as unsupported tracks unless promoted into runtime targets."])
|
|
65
|
-
];
|
|
66
|
-
|
|
67
|
-
export const GLTF_SUPPORTED_EXTENSION_NAMES = GLTF_EXTENSION_SUPPORT_MATRIX
|
|
68
|
-
.filter((extension) => extension.status !== "diagnostic-only" && extension.status !== "unsupported")
|
|
69
|
-
.map((extension) => extension.name);
|
|
70
|
-
|
|
71
|
-
export const GLTF_RUNTIME_SUPPORTED_EXTENSION_NAMES = extensionNamesByStatus("runtime-supported");
|
|
72
|
-
export const GLTF_DECODER_REQUIRED_EXTENSION_NAMES = extensionNamesByStatus("decoder-required");
|
|
73
|
-
export const GLTF_PARSED_WITH_LIMITS_EXTENSION_NAMES = extensionNamesByStatus("parsed-with-limits");
|
|
74
|
-
export const GLTF_DIAGNOSTIC_ONLY_EXTENSION_NAMES = extensionNamesByStatus("diagnostic-only");
|
|
75
|
-
export const GLTF_REQUIRED_ACCEPTED_EXTENSION_NAMES = GLTF_EXTENSION_SUPPORT_MATRIX
|
|
76
|
-
.filter((extension) => extension.requiredAccepted)
|
|
77
|
-
.map((extension) => extension.name);
|
|
78
|
-
|
|
79
|
-
export function getGLTFExtensionSupport(name: string): GLTFExtensionSupportEntry {
|
|
80
|
-
return GLTF_EXTENSION_SUPPORT_MATRIX.find((entry) => entry.name === name)
|
|
81
|
-
?? {
|
|
82
|
-
name,
|
|
83
|
-
family: "scene",
|
|
84
|
-
status: "unsupported",
|
|
85
|
-
requiredAccepted: false,
|
|
86
|
-
publicApi: [],
|
|
87
|
-
knownLimits: ["No A3D loader/runtime support is registered for this extension."]
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function evaluateGLTFExtensionSupport(
|
|
92
|
-
extensionsUsed: readonly string[] = [],
|
|
93
|
-
extensionsRequired: readonly string[] = []
|
|
94
|
-
): GLTFExtensionSupportEvaluation {
|
|
95
|
-
const requested = [...new Set([...extensionsUsed, ...extensionsRequired])].sort();
|
|
96
|
-
const requestedEntries = requested.map((name) => getGLTFExtensionSupport(name));
|
|
97
|
-
const supported = requestedEntries.filter((entry) => entry.status !== "unsupported");
|
|
98
|
-
const unsupportedUsed = extensionsUsed.filter((name) => getGLTFExtensionSupport(name).status === "unsupported").sort();
|
|
99
|
-
const unsupportedRequired = extensionsRequired.filter((name) => !getGLTFExtensionSupport(name).requiredAccepted).sort();
|
|
100
|
-
const notAcceptedUsed = extensionsUsed.filter((name) => !getGLTFExtensionSupport(name).requiredAccepted).sort();
|
|
101
|
-
return {
|
|
102
|
-
schemaVersion: "gltf-extension-support",
|
|
103
|
-
requested: requestedEntries,
|
|
104
|
-
supported,
|
|
105
|
-
runtimeSupported: supported.filter((entry) => entry.status === "runtime-supported"),
|
|
106
|
-
parsedWithLimits: supported.filter((entry) => entry.status === "parsed-with-limits"),
|
|
107
|
-
diagnosticOnly: supported.filter((entry) => entry.status === "diagnostic-only"),
|
|
108
|
-
unsupportedUsed,
|
|
109
|
-
unsupportedRequired,
|
|
110
|
-
notAcceptedUsed,
|
|
111
|
-
decoderRequired: supported.filter((entry) => entry.status === "decoder-required")
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function extensionNamesByStatus(status: GLTFExtensionSupportStatus): readonly string[] {
|
|
116
|
-
return GLTF_EXTENSION_SUPPORT_MATRIX
|
|
117
|
-
.filter((extension) => extension.status === status)
|
|
118
|
-
.map((extension) => extension.name);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function entry(
|
|
122
|
-
name: string,
|
|
123
|
-
family: GLTFExtensionSupportFamily,
|
|
124
|
-
status: Exclude<GLTFExtensionSupportStatus, "unsupported">,
|
|
125
|
-
publicApi: readonly string[],
|
|
126
|
-
knownLimits: readonly string[],
|
|
127
|
-
decoder?: GLTFExtensionSupportEntry["decoder"]
|
|
128
|
-
): GLTFExtensionSupportEntry {
|
|
129
|
-
return {
|
|
130
|
-
name,
|
|
131
|
-
family,
|
|
132
|
-
status,
|
|
133
|
-
requiredAccepted: status !== "diagnostic-only",
|
|
134
|
-
publicApi,
|
|
135
|
-
...(decoder === undefined ? {} : { decoder }),
|
|
136
|
-
knownLimits
|
|
137
|
-
};
|
|
138
|
-
}
|