@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/AssetInspection.ts
DELETED
|
@@ -1,706 +0,0 @@
|
|
|
1
|
-
import type { AnimationClip } from "@aura3d/animation";
|
|
2
|
-
import type { Texture } from "@aura3d/rendering";
|
|
3
|
-
import type { SceneNode } from "@aura3d/scene";
|
|
4
|
-
import type { AssetDiagnostic } from "./AssetCorpus";
|
|
5
|
-
import type {
|
|
6
|
-
GLTFAsset,
|
|
7
|
-
GLTFCameraAsset,
|
|
8
|
-
GLTFLightAsset,
|
|
9
|
-
GLTFMaterialAsset,
|
|
10
|
-
GLTFMeshAsset,
|
|
11
|
-
GLTFSkinAsset
|
|
12
|
-
} from "./GLTFLoader";
|
|
13
|
-
import {
|
|
14
|
-
createGLTFRenderResourceDiagnostics,
|
|
15
|
-
type GLTFRenderResourceDiagnostics,
|
|
16
|
-
type GLTFRenderResources
|
|
17
|
-
} from "./GLTFRenderResources";
|
|
18
|
-
import {
|
|
19
|
-
evaluateGLTFExtensionSupport,
|
|
20
|
-
getGLTFExtensionSupport,
|
|
21
|
-
type GLTFExtensionSupportEvaluation,
|
|
22
|
-
type GLTFExtensionSupportFamily,
|
|
23
|
-
type GLTFExtensionSupportStatus
|
|
24
|
-
} from "./GLTFExtensionSupport";
|
|
25
|
-
|
|
26
|
-
export interface GLTFSceneHierarchyNodeInspection {
|
|
27
|
-
readonly name: string;
|
|
28
|
-
readonly depth: number;
|
|
29
|
-
readonly childCount: number;
|
|
30
|
-
readonly hasRenderable: boolean;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface GLTFMeshInspection {
|
|
34
|
-
readonly name: string;
|
|
35
|
-
readonly sourceMeshIndex: number;
|
|
36
|
-
readonly primitiveIndex: number;
|
|
37
|
-
readonly vertexCount: number;
|
|
38
|
-
readonly indexCount: number;
|
|
39
|
-
readonly topology: "triangles" | "lines" | "points";
|
|
40
|
-
readonly material: string;
|
|
41
|
-
readonly bounds: {
|
|
42
|
-
readonly min: readonly [number, number, number];
|
|
43
|
-
readonly max: readonly [number, number, number];
|
|
44
|
-
};
|
|
45
|
-
readonly attributeCounts: {
|
|
46
|
-
readonly positions: number;
|
|
47
|
-
readonly normals: number;
|
|
48
|
-
readonly tangents: number;
|
|
49
|
-
readonly colors: number;
|
|
50
|
-
readonly texcoordSets: readonly number[];
|
|
51
|
-
readonly joints: number;
|
|
52
|
-
readonly weights: number;
|
|
53
|
-
};
|
|
54
|
-
readonly morphTargetCount: number;
|
|
55
|
-
readonly skinIndex?: number;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface GLTFMaterialInspection {
|
|
59
|
-
readonly name: string;
|
|
60
|
-
readonly unlit: boolean;
|
|
61
|
-
readonly baseColorFactor: readonly [number, number, number, number];
|
|
62
|
-
readonly metallicFactor: number;
|
|
63
|
-
readonly roughnessFactor: number;
|
|
64
|
-
readonly emissiveFactor: readonly [number, number, number];
|
|
65
|
-
readonly emissiveStrength: number;
|
|
66
|
-
readonly alphaMode: "OPAQUE" | "MASK" | "BLEND";
|
|
67
|
-
readonly alphaCutoff: number;
|
|
68
|
-
readonly doubleSided: boolean;
|
|
69
|
-
readonly textures: readonly GLTFMaterialTextureSlotInspection[];
|
|
70
|
-
readonly features: GLTFMaterialFeatureInspection;
|
|
71
|
-
readonly extensions: readonly string[];
|
|
72
|
-
readonly extensionSupport: readonly GLTFMaterialExtensionSupportInspection[];
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface GLTFMaterialExtensionSupportInspection {
|
|
76
|
-
readonly name: string;
|
|
77
|
-
readonly family: GLTFExtensionSupportFamily;
|
|
78
|
-
readonly status: GLTFExtensionSupportStatus;
|
|
79
|
-
readonly requiredAccepted: boolean;
|
|
80
|
-
readonly knownLimits: readonly string[];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export interface GLTFMaterialFeatureInspection {
|
|
84
|
-
readonly normalScale?: number;
|
|
85
|
-
readonly occlusionStrength?: number;
|
|
86
|
-
readonly clearcoat?: {
|
|
87
|
-
readonly factor: number;
|
|
88
|
-
readonly roughnessFactor: number;
|
|
89
|
-
readonly normalScale?: number;
|
|
90
|
-
};
|
|
91
|
-
readonly transmission?: {
|
|
92
|
-
readonly factor: number;
|
|
93
|
-
};
|
|
94
|
-
readonly diffuseTransmission?: {
|
|
95
|
-
readonly factor: number;
|
|
96
|
-
readonly colorFactor: readonly [number, number, number];
|
|
97
|
-
};
|
|
98
|
-
readonly volume?: {
|
|
99
|
-
readonly thicknessFactor: number;
|
|
100
|
-
readonly attenuationDistance: number;
|
|
101
|
-
readonly attenuationColor: readonly [number, number, number];
|
|
102
|
-
};
|
|
103
|
-
readonly ior?: number;
|
|
104
|
-
readonly specular?: {
|
|
105
|
-
readonly factor: number;
|
|
106
|
-
readonly colorFactor: readonly [number, number, number];
|
|
107
|
-
};
|
|
108
|
-
readonly sheen?: {
|
|
109
|
-
readonly colorFactor: readonly [number, number, number];
|
|
110
|
-
readonly roughnessFactor: number;
|
|
111
|
-
};
|
|
112
|
-
readonly anisotropy?: {
|
|
113
|
-
readonly strength: number;
|
|
114
|
-
readonly rotation: number;
|
|
115
|
-
};
|
|
116
|
-
readonly iridescence?: {
|
|
117
|
-
readonly factor: number;
|
|
118
|
-
readonly ior: number;
|
|
119
|
-
readonly thicknessMinimum: number;
|
|
120
|
-
readonly thicknessMaximum: number;
|
|
121
|
-
};
|
|
122
|
-
readonly dispersion?: number;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export interface GLTFMaterialTextureSlotInspection {
|
|
126
|
-
readonly slot: string;
|
|
127
|
-
readonly texture: number;
|
|
128
|
-
readonly image: number;
|
|
129
|
-
readonly texCoord: number;
|
|
130
|
-
readonly transform?: {
|
|
131
|
-
readonly offset: readonly [number, number];
|
|
132
|
-
readonly scale: readonly [number, number];
|
|
133
|
-
readonly rotation: number;
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export interface GLTFTextureInspection {
|
|
138
|
-
readonly name: string;
|
|
139
|
-
readonly sourceImage: number;
|
|
140
|
-
readonly imageName: string;
|
|
141
|
-
readonly uri?: string;
|
|
142
|
-
readonly mimeType?: string;
|
|
143
|
-
readonly embeddedBytes?: number;
|
|
144
|
-
readonly sampler?: {
|
|
145
|
-
readonly minFilter: "nearest" | "linear" | "nearest-mipmap-nearest" | "linear-mipmap-nearest" | "nearest-mipmap-linear" | "linear-mipmap-linear";
|
|
146
|
-
readonly magFilter: "nearest" | "linear";
|
|
147
|
-
readonly addressU: "clamp-to-edge" | "repeat" | "mirror-repeat";
|
|
148
|
-
readonly addressV: "clamp-to-edge" | "repeat" | "mirror-repeat";
|
|
149
|
-
};
|
|
150
|
-
readonly runtime?: {
|
|
151
|
-
readonly width: number;
|
|
152
|
-
readonly height: number;
|
|
153
|
-
readonly format: string;
|
|
154
|
-
readonly colorSpace: "linear" | "srgb";
|
|
155
|
-
readonly mipLevels: number;
|
|
156
|
-
readonly byteLength: number;
|
|
157
|
-
readonly fallbackByteLength: number;
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export interface GLTFAnimationInspection {
|
|
162
|
-
readonly name: string;
|
|
163
|
-
readonly duration: number;
|
|
164
|
-
readonly trackCount: number;
|
|
165
|
-
readonly tracks: readonly {
|
|
166
|
-
readonly target: string;
|
|
167
|
-
readonly valueType: string;
|
|
168
|
-
readonly keyframes: number;
|
|
169
|
-
}[];
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
export interface GLTFSkinInspection {
|
|
173
|
-
readonly name: string;
|
|
174
|
-
readonly jointCount: number;
|
|
175
|
-
readonly skeletonRoot?: number;
|
|
176
|
-
readonly bones: readonly {
|
|
177
|
-
readonly name: string;
|
|
178
|
-
readonly parentIndex: number;
|
|
179
|
-
}[];
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export interface GLTFMorphTargetInspection {
|
|
183
|
-
readonly mesh: string;
|
|
184
|
-
readonly weights: readonly number[];
|
|
185
|
-
readonly targets: readonly {
|
|
186
|
-
readonly index: number;
|
|
187
|
-
readonly positions: number;
|
|
188
|
-
readonly normals: number;
|
|
189
|
-
readonly tangents: number;
|
|
190
|
-
}[];
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export interface GLTFDependencyInspection {
|
|
194
|
-
readonly owner: string;
|
|
195
|
-
readonly dependency: string;
|
|
196
|
-
readonly kind: "buffer" | "image" | "texture";
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
export interface GLTFAssetInspectionReport {
|
|
200
|
-
readonly extensionSupport: GLTFExtensionSupportEvaluation;
|
|
201
|
-
readonly renderResources?: GLTFRenderResourceDiagnostics;
|
|
202
|
-
readonly sceneHierarchy: readonly GLTFSceneHierarchyNodeInspection[];
|
|
203
|
-
readonly meshes: readonly GLTFMeshInspection[];
|
|
204
|
-
readonly materials: readonly GLTFMaterialInspection[];
|
|
205
|
-
readonly textures: readonly GLTFTextureInspection[];
|
|
206
|
-
readonly animations: readonly GLTFAnimationInspection[];
|
|
207
|
-
readonly skins: readonly GLTFSkinInspection[];
|
|
208
|
-
readonly morphTargets: readonly GLTFMorphTargetInspection[];
|
|
209
|
-
readonly cameras: readonly GLTFCameraAsset[];
|
|
210
|
-
readonly lights: readonly GLTFLightAsset[];
|
|
211
|
-
readonly dependencies: readonly GLTFDependencyInspection[];
|
|
212
|
-
readonly warnings: readonly AssetDiagnostic[];
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
export function inspectGLTFAsset(asset: GLTFAsset, resources?: GLTFRenderResources): GLTFAssetInspectionReport {
|
|
216
|
-
const scene = resources?.scene ?? asset.createScene();
|
|
217
|
-
const renderResources = resources ? createGLTFRenderResourceDiagnostics(resources) : undefined;
|
|
218
|
-
return {
|
|
219
|
-
extensionSupport: asset.loaderDiagnostics.extensionSupport ?? evaluateGLTFExtensionSupport(
|
|
220
|
-
asset.loaderDiagnostics.extensionsUsed,
|
|
221
|
-
asset.loaderDiagnostics.extensionsRequired
|
|
222
|
-
),
|
|
223
|
-
...(renderResources ? { renderResources } : {}),
|
|
224
|
-
sceneHierarchy: inspectSceneHierarchy(scene),
|
|
225
|
-
meshes: asset.meshes.map(inspectMesh),
|
|
226
|
-
materials: asset.materials.map(inspectMaterial),
|
|
227
|
-
textures: asset.textures.map((texture, index) => inspectTexture(asset, resources, index)),
|
|
228
|
-
animations: asset.animations.map(inspectAnimation),
|
|
229
|
-
skins: asset.skins.map(inspectSkin),
|
|
230
|
-
morphTargets: asset.meshes.filter((mesh) => mesh.morphTargets.length > 0).map(inspectMorphTargets),
|
|
231
|
-
cameras: asset.cameras,
|
|
232
|
-
lights: asset.lights,
|
|
233
|
-
dependencies: inspectDependencies(asset),
|
|
234
|
-
warnings: createGLTFInspectionWarnings(asset, renderResources)
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
function inspectSceneHierarchy(scene: ReturnType<GLTFAsset["createScene"]>): readonly GLTFSceneHierarchyNodeInspection[] {
|
|
239
|
-
const rows: GLTFSceneHierarchyNodeInspection[] = [];
|
|
240
|
-
const visit = (node: SceneNode, depth: number): void => {
|
|
241
|
-
rows.push({
|
|
242
|
-
name: node.name,
|
|
243
|
-
depth,
|
|
244
|
-
childCount: node.children.length,
|
|
245
|
-
hasRenderable: Boolean((node as typeof node & { renderable?: unknown }).renderable)
|
|
246
|
-
});
|
|
247
|
-
for (const child of node.children) visit(child, depth + 1);
|
|
248
|
-
};
|
|
249
|
-
visit(scene.root, 0);
|
|
250
|
-
return rows;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function inspectMesh(mesh: GLTFMeshAsset): GLTFMeshInspection {
|
|
254
|
-
return {
|
|
255
|
-
name: mesh.name,
|
|
256
|
-
sourceMeshIndex: mesh.sourceMeshIndex,
|
|
257
|
-
primitiveIndex: mesh.primitiveIndex,
|
|
258
|
-
vertexCount: mesh.geometry.vertexCount,
|
|
259
|
-
indexCount: mesh.geometry.indexCount,
|
|
260
|
-
topology: mesh.topology,
|
|
261
|
-
material: mesh.material,
|
|
262
|
-
bounds: mesh.geometry.bounds,
|
|
263
|
-
attributeCounts: {
|
|
264
|
-
positions: mesh.positions.length,
|
|
265
|
-
normals: mesh.normals.length,
|
|
266
|
-
tangents: mesh.tangents.length,
|
|
267
|
-
colors: mesh.colors.length,
|
|
268
|
-
texcoordSets: mesh.texcoordSets.map((set) => set.length),
|
|
269
|
-
joints: mesh.joints.length,
|
|
270
|
-
weights: mesh.weights.length
|
|
271
|
-
},
|
|
272
|
-
morphTargetCount: mesh.morphTargets.length,
|
|
273
|
-
...(mesh.skinIndex === undefined ? {} : { skinIndex: mesh.skinIndex })
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
function inspectMaterial(material: GLTFMaterialAsset): GLTFMaterialInspection {
|
|
278
|
-
return {
|
|
279
|
-
name: material.name,
|
|
280
|
-
unlit: material.unlit,
|
|
281
|
-
baseColorFactor: material.baseColorFactor,
|
|
282
|
-
metallicFactor: material.metallicFactor,
|
|
283
|
-
roughnessFactor: material.roughnessFactor,
|
|
284
|
-
emissiveFactor: material.emissiveFactor,
|
|
285
|
-
emissiveStrength: material.emissiveStrength,
|
|
286
|
-
alphaMode: material.alphaMode,
|
|
287
|
-
alphaCutoff: material.alphaCutoff,
|
|
288
|
-
doubleSided: material.doubleSided,
|
|
289
|
-
textures: materialTextureSlots(material),
|
|
290
|
-
features: materialFeatures(material),
|
|
291
|
-
extensions: materialExtensions(material),
|
|
292
|
-
extensionSupport: materialExtensions(material).map(inspectMaterialExtensionSupport)
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
function inspectMaterialExtensionSupport(name: string): GLTFMaterialExtensionSupportInspection {
|
|
297
|
-
const support = getGLTFExtensionSupport(name);
|
|
298
|
-
return {
|
|
299
|
-
name: support.name,
|
|
300
|
-
family: support.family,
|
|
301
|
-
status: support.status,
|
|
302
|
-
requiredAccepted: support.requiredAccepted,
|
|
303
|
-
knownLimits: support.knownLimits
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
function materialFeatures(material: GLTFMaterialAsset): GLTFMaterialFeatureInspection {
|
|
308
|
-
return {
|
|
309
|
-
...(material.normalTexture ? { normalScale: material.normalTexture.scale } : {}),
|
|
310
|
-
...(material.occlusionTexture ? { occlusionStrength: material.occlusionTexture.strength } : {}),
|
|
311
|
-
...(material.clearcoat ? {
|
|
312
|
-
clearcoat: {
|
|
313
|
-
factor: material.clearcoat.factor,
|
|
314
|
-
roughnessFactor: material.clearcoat.roughnessFactor,
|
|
315
|
-
...(material.clearcoat.normalTexture ? { normalScale: material.clearcoat.normalTexture.scale } : {})
|
|
316
|
-
}
|
|
317
|
-
} : {}),
|
|
318
|
-
...(material.transmission ? { transmission: { factor: material.transmission.factor } } : {}),
|
|
319
|
-
...(material.diffuseTransmission ? {
|
|
320
|
-
diffuseTransmission: {
|
|
321
|
-
factor: material.diffuseTransmission.factor,
|
|
322
|
-
colorFactor: material.diffuseTransmission.colorFactor
|
|
323
|
-
}
|
|
324
|
-
} : {}),
|
|
325
|
-
...(material.volume ? {
|
|
326
|
-
volume: {
|
|
327
|
-
thicknessFactor: material.volume.thicknessFactor,
|
|
328
|
-
attenuationDistance: material.volume.attenuationDistance,
|
|
329
|
-
attenuationColor: material.volume.attenuationColor
|
|
330
|
-
}
|
|
331
|
-
} : {}),
|
|
332
|
-
...(material.ior !== undefined ? { ior: material.ior } : {}),
|
|
333
|
-
...(material.specular ? {
|
|
334
|
-
specular: {
|
|
335
|
-
factor: material.specular.factor,
|
|
336
|
-
colorFactor: material.specular.colorFactor
|
|
337
|
-
}
|
|
338
|
-
} : {}),
|
|
339
|
-
...(material.sheen ? {
|
|
340
|
-
sheen: {
|
|
341
|
-
colorFactor: material.sheen.colorFactor,
|
|
342
|
-
roughnessFactor: material.sheen.roughnessFactor
|
|
343
|
-
}
|
|
344
|
-
} : {}),
|
|
345
|
-
...(material.anisotropy ? {
|
|
346
|
-
anisotropy: {
|
|
347
|
-
strength: material.anisotropy.strength,
|
|
348
|
-
rotation: material.anisotropy.rotation
|
|
349
|
-
}
|
|
350
|
-
} : {}),
|
|
351
|
-
...(material.iridescence ? {
|
|
352
|
-
iridescence: {
|
|
353
|
-
factor: material.iridescence.factor,
|
|
354
|
-
ior: material.iridescence.ior,
|
|
355
|
-
thicknessMinimum: material.iridescence.thicknessMinimum,
|
|
356
|
-
thicknessMaximum: material.iridescence.thicknessMaximum
|
|
357
|
-
}
|
|
358
|
-
} : {}),
|
|
359
|
-
...(material.dispersion !== undefined ? { dispersion: material.dispersion } : {})
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
function materialTextureSlots(material: GLTFMaterialAsset): readonly GLTFMaterialTextureSlotInspection[] {
|
|
364
|
-
return [
|
|
365
|
-
textureSlot("baseColor", material.baseColorTexture),
|
|
366
|
-
textureSlot("metallicRoughness", material.metallicRoughnessTexture),
|
|
367
|
-
textureSlot("normal", material.normalTexture),
|
|
368
|
-
textureSlot("occlusion", material.occlusionTexture),
|
|
369
|
-
textureSlot("emissive", material.emissiveTexture),
|
|
370
|
-
textureSlot("clearcoat", material.clearcoat?.texture),
|
|
371
|
-
textureSlot("clearcoatRoughness", material.clearcoat?.roughnessTexture),
|
|
372
|
-
textureSlot("clearcoatNormal", material.clearcoat?.normalTexture),
|
|
373
|
-
textureSlot("transmission", material.transmission?.texture),
|
|
374
|
-
textureSlot("diffuseTransmission", material.diffuseTransmission?.texture),
|
|
375
|
-
textureSlot("diffuseTransmissionColor", material.diffuseTransmission?.colorTexture),
|
|
376
|
-
textureSlot("volumeThickness", material.volume?.thicknessTexture),
|
|
377
|
-
textureSlot("specular", material.specular?.texture),
|
|
378
|
-
textureSlot("specularColor", material.specular?.colorTexture),
|
|
379
|
-
textureSlot("sheenColor", material.sheen?.colorTexture),
|
|
380
|
-
textureSlot("sheenRoughness", material.sheen?.roughnessTexture),
|
|
381
|
-
textureSlot("anisotropy", material.anisotropy?.texture),
|
|
382
|
-
textureSlot("iridescence", material.iridescence?.texture),
|
|
383
|
-
textureSlot("iridescenceThickness", material.iridescence?.thicknessTexture)
|
|
384
|
-
].filter((slot): slot is GLTFMaterialTextureSlotInspection => slot !== undefined);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
function textureSlot(
|
|
388
|
-
slot: string,
|
|
389
|
-
info: GLTFMaterialAsset["baseColorTexture"]
|
|
390
|
-
): GLTFMaterialTextureSlotInspection | undefined {
|
|
391
|
-
if (!info) return undefined;
|
|
392
|
-
return {
|
|
393
|
-
slot,
|
|
394
|
-
texture: info.texture,
|
|
395
|
-
image: info.image,
|
|
396
|
-
texCoord: info.texCoord,
|
|
397
|
-
...(info.transform ? { transform: info.transform } : {})
|
|
398
|
-
};
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
function materialExtensions(material: GLTFMaterialAsset): readonly string[] {
|
|
402
|
-
return [
|
|
403
|
-
material.unlit ? "KHR_materials_unlit" : undefined,
|
|
404
|
-
material.emissiveStrength !== 1 ? "KHR_materials_emissive_strength" : undefined,
|
|
405
|
-
material.clearcoat ? "KHR_materials_clearcoat" : undefined,
|
|
406
|
-
material.transmission ? "KHR_materials_transmission" : undefined,
|
|
407
|
-
material.diffuseTransmission ? "KHR_materials_diffuse_transmission" : undefined,
|
|
408
|
-
material.volume ? "KHR_materials_volume" : undefined,
|
|
409
|
-
material.ior !== undefined ? "KHR_materials_ior" : undefined,
|
|
410
|
-
material.specular ? "KHR_materials_specular" : undefined,
|
|
411
|
-
material.pbrSpecularGlossiness ? "KHR_materials_pbrSpecularGlossiness" : undefined,
|
|
412
|
-
material.sheen ? "KHR_materials_sheen" : undefined,
|
|
413
|
-
material.anisotropy ? "KHR_materials_anisotropy" : undefined,
|
|
414
|
-
material.iridescence ? "KHR_materials_iridescence" : undefined,
|
|
415
|
-
material.dispersion !== undefined ? "KHR_materials_dispersion" : undefined
|
|
416
|
-
].filter((extension): extension is string => extension !== undefined);
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
function inspectTexture(asset: GLTFAsset, resources: GLTFRenderResources | undefined, textureIndex: number): GLTFTextureInspection {
|
|
420
|
-
const texture = asset.textures[textureIndex]!;
|
|
421
|
-
const image = asset.images[texture.source]!;
|
|
422
|
-
const runtime = findRuntimeTexture(resources, texture.name);
|
|
423
|
-
return {
|
|
424
|
-
name: texture.name,
|
|
425
|
-
sourceImage: texture.source,
|
|
426
|
-
imageName: image.name,
|
|
427
|
-
...(image.uri ? { uri: image.uri } : {}),
|
|
428
|
-
...(image.mimeType ? { mimeType: image.mimeType } : {}),
|
|
429
|
-
...(image.data ? { embeddedBytes: image.data.byteLength } : {}),
|
|
430
|
-
...(texture.samplerDescriptor ? { sampler: texture.samplerDescriptor } : {}),
|
|
431
|
-
...(runtime ? {
|
|
432
|
-
runtime: {
|
|
433
|
-
width: runtime.width,
|
|
434
|
-
height: runtime.height,
|
|
435
|
-
format: runtime.format,
|
|
436
|
-
colorSpace: runtime.colorSpace,
|
|
437
|
-
mipLevels: Math.max(1, runtime.textureLevels.length),
|
|
438
|
-
byteLength: runtime.byteLength,
|
|
439
|
-
fallbackByteLength: runtime.fallbackByteLength
|
|
440
|
-
}
|
|
441
|
-
} : {})
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
function findRuntimeTexture(resources: GLTFRenderResources | undefined, textureName: string): Texture | undefined {
|
|
446
|
-
if (!resources) return undefined;
|
|
447
|
-
return resources.textureLibrary.get(textureName) ?? resources.textureLibrary.get(`${textureName}:srgb`) ?? resources.textureLibrary.get(`${textureName}:linear`);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
function inspectAnimation(clip: AnimationClip): GLTFAnimationInspection {
|
|
451
|
-
return {
|
|
452
|
-
name: clip.name,
|
|
453
|
-
duration: clip.duration,
|
|
454
|
-
trackCount: clip.tracks.length,
|
|
455
|
-
tracks: clip.tracks.map((track) => ({
|
|
456
|
-
target: track.target,
|
|
457
|
-
valueType: track.valueType,
|
|
458
|
-
keyframes: track.keyframes.length
|
|
459
|
-
}))
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
function inspectSkin(skin: GLTFSkinAsset): GLTFSkinInspection {
|
|
464
|
-
return {
|
|
465
|
-
name: skin.name,
|
|
466
|
-
jointCount: skin.joints.length,
|
|
467
|
-
...(skin.skeletonRoot === undefined ? {} : { skeletonRoot: skin.skeletonRoot }),
|
|
468
|
-
bones: skin.skeleton.bones.map((bone) => ({
|
|
469
|
-
name: bone.name,
|
|
470
|
-
parentIndex: bone.parentIndex
|
|
471
|
-
}))
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
function inspectMorphTargets(mesh: GLTFMeshAsset): GLTFMorphTargetInspection {
|
|
476
|
-
return {
|
|
477
|
-
mesh: mesh.name,
|
|
478
|
-
weights: mesh.morphWeights,
|
|
479
|
-
targets: mesh.morphTargets.map((target, index) => ({
|
|
480
|
-
index,
|
|
481
|
-
positions: target.positions.length,
|
|
482
|
-
normals: target.normals.length,
|
|
483
|
-
tangents: target.tangents.length
|
|
484
|
-
}))
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
function inspectDependencies(asset: GLTFAsset): readonly GLTFDependencyInspection[] {
|
|
489
|
-
const dependencies: GLTFDependencyInspection[] = [];
|
|
490
|
-
for (const [textureIndex, texture] of asset.textures.entries()) {
|
|
491
|
-
dependencies.push({
|
|
492
|
-
owner: texture.name,
|
|
493
|
-
dependency: asset.images[texture.source]?.name ?? `image-${texture.source}`,
|
|
494
|
-
kind: "image"
|
|
495
|
-
});
|
|
496
|
-
dependencies.push({
|
|
497
|
-
owner: `material-slot:${textureIndex}`,
|
|
498
|
-
dependency: texture.name,
|
|
499
|
-
kind: "texture"
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
|
-
return dependencies;
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
function createGLTFInspectionWarnings(
|
|
506
|
-
asset: GLTFAsset,
|
|
507
|
-
renderResources?: GLTFRenderResourceDiagnostics
|
|
508
|
-
): readonly AssetDiagnostic[] {
|
|
509
|
-
const warnings: AssetDiagnostic[] = [];
|
|
510
|
-
const push = (code: string, message: string, nextAction: string): void => {
|
|
511
|
-
warnings.push({ code, severity: "warning", message, nextAction });
|
|
512
|
-
};
|
|
513
|
-
|
|
514
|
-
for (const extension of asset.loaderDiagnostics.unsupportedExtensions) {
|
|
515
|
-
if (isMaterialExtensionName(extension)) {
|
|
516
|
-
push(
|
|
517
|
-
"GLTF_UNSUPPORTED_MATERIAL_EXTENSION",
|
|
518
|
-
`Unsupported glTF material extension ${extension} is declared by this asset and will not be rendered with extension-specific fidelity.`,
|
|
519
|
-
"Use fallback material inspection output unless a renderer/resource path explicitly supports this material extension."
|
|
520
|
-
);
|
|
521
|
-
} else {
|
|
522
|
-
push(
|
|
523
|
-
"GLTF_UNSUPPORTED_EXTENSION",
|
|
524
|
-
`Unsupported glTF extension ${extension} is declared by this asset and may be ignored by current loader or render-resource paths.`,
|
|
525
|
-
"Keep this feature blocked until a loader, inspector, and render-resource path handles the extension."
|
|
526
|
-
);
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
const hasMorphTargets = asset.meshes.some((mesh) => mesh.morphTargets.length > 0);
|
|
531
|
-
const hasMultiUvMaterial = asset.materials.some((material) => new Set(materialTextureSlots(material).map((slot) => slot.texCoord)).size > 1);
|
|
532
|
-
const hasSupportedMultiUvMaterial = asset.materials.some((material) => {
|
|
533
|
-
const texCoordSets = new Set(materialTextureSlots(material).map((slot) => slot.texCoord));
|
|
534
|
-
return texCoordSets.size > 1 && [...texCoordSets].every((texCoord) => texCoord === 0 || texCoord === 1);
|
|
535
|
-
});
|
|
536
|
-
const hasUnsupportedMultiUvMaterial = asset.materials.some((material) =>
|
|
537
|
-
materialTextureSlots(material).some((slot) => slot.texCoord > 1)
|
|
538
|
-
);
|
|
539
|
-
const hasMorphWeightAnimation = asset.animations.some((clip) => clip.tracks.some((track) => track.target.endsWith(".weights") && track.valueType === "number-array"));
|
|
540
|
-
const hasRootMotionTrack = asset.animations.some((clip) => clip.tracks.some((track) =>
|
|
541
|
-
(track.target.endsWith(".position") || track.target.endsWith(".translation")) &&
|
|
542
|
-
track.valueType === "vector3"
|
|
543
|
-
));
|
|
544
|
-
const hasRenderableSkinning = asset.skins.length > 0 &&
|
|
545
|
-
asset.meshes.some((mesh) => mesh.skinIndex !== undefined) &&
|
|
546
|
-
asset.meshes.filter((mesh) => mesh.skinIndex !== undefined).every((mesh) => mesh.joints.length > 0 && mesh.weights.length > 0);
|
|
547
|
-
if (asset.animations.length > 0) {
|
|
548
|
-
if (hasRootMotionTrack && !hasRenderableSkinning && !hasMorphWeightAnimation) {
|
|
549
|
-
push(
|
|
550
|
-
"ASSET_VIEWER_ROOT_MOTION_ACTIVE",
|
|
551
|
-
"glTF animation clips are imported, sampled, and have a vector translation track that asset-viewer playback applies to root-motion controller state.",
|
|
552
|
-
"Use viewer playback root-motion metrics for this generated corpus asset; keep broad animation parity blocked until the wider Khronos/extension corpus is rendered."
|
|
553
|
-
);
|
|
554
|
-
} else {
|
|
555
|
-
push(
|
|
556
|
-
"ASSET_VIEWER_ANIMATION_PLAYBACK_BOUNDED",
|
|
557
|
-
hasRenderableSkinning && hasMorphWeightAnimation
|
|
558
|
-
? "glTF animation clips are imported, node transforms can be sampled, morph-weight tracks can drive renderables, and skinned meshes bind renderable skinning palettes; animation pointer parity remains bounded."
|
|
559
|
-
: hasRenderableSkinning
|
|
560
|
-
? "glTF animation clips are imported, node transforms can be sampled, and skinned meshes bind renderable skinning palettes, but morph weight animation and animation pointer parity remain bounded."
|
|
561
|
-
: hasMorphWeightAnimation
|
|
562
|
-
? "glTF animation clips are imported and node transform plus morph-weight tracks can be sampled into the rendered scene, but skinning and animation pointer parity remain bounded."
|
|
563
|
-
: "glTF animation clips are imported and node transform tracks can be sampled into the rendered scene, but skinning, morph weight animation, and animation pointer parity remain bounded.",
|
|
564
|
-
hasRenderableSkinning && hasMorphWeightAnimation
|
|
565
|
-
? "Use viewer playback for TRS, morph-weight, and skinning diagnostics; keep full animation parity blocked until extension-driven animation paths are rendered."
|
|
566
|
-
: hasRenderableSkinning
|
|
567
|
-
? "Use viewer playback for TRS and skinning diagnostics; keep full animation parity blocked until morph-weight and extension-driven animation paths are rendered."
|
|
568
|
-
: hasMorphWeightAnimation
|
|
569
|
-
? "Use viewer playback for TRS and morph-weight diagnostics; keep full animation parity claims blocked until skinned and extension-driven animation paths are rendered."
|
|
570
|
-
: "Use viewer playback for translation/rotation/scale diagnostics; keep full animation parity claims blocked until skinned, morph, and extension-driven animation paths are rendered."
|
|
571
|
-
);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
if (asset.skins.length > 0 || asset.meshes.some((mesh) => mesh.skinIndex !== undefined)) {
|
|
575
|
-
if (hasRenderableSkinning) {
|
|
576
|
-
push(
|
|
577
|
-
"ASSET_VIEWER_SKINNING_RENDER_ACTIVE",
|
|
578
|
-
"glTF skin and joint data are imported, inspectable, and bound as renderable skinning palettes for skinned mesh draw items.",
|
|
579
|
-
"Keep broad skinned character parity scoped until a wider animated character corpus and external-engine visual comparison exist."
|
|
580
|
-
);
|
|
581
|
-
} else {
|
|
582
|
-
push(
|
|
583
|
-
"ASSET_VIEWER_SKINNING_INSPECT_ONLY",
|
|
584
|
-
"glTF skin and joint data are imported and inspectable, but the viewer render path is not yet applying skinning palettes to these imported meshes.",
|
|
585
|
-
"Keep skinned character visual parity claims blocked until GLTFRenderResources binds skinning data for render items."
|
|
586
|
-
);
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
if (hasMorphTargets) {
|
|
590
|
-
if (hasMorphWeightAnimation) {
|
|
591
|
-
push(
|
|
592
|
-
"ASSET_VIEWER_MORPH_ANIMATION_ACTIVE",
|
|
593
|
-
"glTF morph target data is imported, slider-adjustable, and driven by imported morph-weight animation tracks in the asset viewer.",
|
|
594
|
-
"Keep broad morph parity scoped to the visible corpus and browser evidence; production character parity still requires broader assets and skinning integration."
|
|
595
|
-
);
|
|
596
|
-
} else {
|
|
597
|
-
push(
|
|
598
|
-
"ASSET_VIEWER_MORPH_PLAYBACK_BOUNDED",
|
|
599
|
-
"glTF morph target data is imported and the asset viewer can update renderable morph weights through sliders, but morph animation and production character parity remain bounded.",
|
|
600
|
-
"Use viewer sliders for target-weight diagnostics; keep broad morph parity blocked until animated morph weights and visual corpus coverage exist."
|
|
601
|
-
);
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
if (asset.materialVariants.length > 0) {
|
|
605
|
-
push(
|
|
606
|
-
"ASSET_VIEWER_VARIANTS_SWITCHING_BOUNDED",
|
|
607
|
-
"glTF material variants are imported and the asset viewer can rebuild render resources for a selected material variant, but authoring and full extension parity remain bounded.",
|
|
608
|
-
"Use the viewer selector for import/render diagnostics; keep broad material workflow parity blocked until variant authoring, persistence, and cross-asset visual corpus coverage exist."
|
|
609
|
-
);
|
|
610
|
-
}
|
|
611
|
-
const unbackedTransmissionMaterials = asset.materials.filter(isUnbackedTransmissionMaterial);
|
|
612
|
-
if (unbackedTransmissionMaterials.length > 0) {
|
|
613
|
-
push(
|
|
614
|
-
"GLTF_TRANSMISSION_REFRACTION_FALLBACK",
|
|
615
|
-
`KHR_materials_transmission material(s) ${summarizeMaterialNames(unbackedTransmissionMaterials)} require scene-color refraction for full fidelity; the current WebGL render path uses a bounded alpha/specular fallback instead of true refraction.`,
|
|
616
|
-
"Treat these materials as parsed-with-limits; use authored BLEND glass or implement a backdrop/refraction render path before claiming full transmission fidelity."
|
|
617
|
-
);
|
|
618
|
-
}
|
|
619
|
-
if (hasSupportedMultiUvMaterial) {
|
|
620
|
-
push(
|
|
621
|
-
"ASSET_VIEWER_MULTI_UV_RENDER_ACTIVE",
|
|
622
|
-
"The asset uses multiple texture coordinate sets in one material, and the render path binds TEXCOORD_0/TEXCOORD_1 so each texture slot can sample its declared set.",
|
|
623
|
-
"Keep arbitrary multi-UV parity scoped to two UV sets until assets with TEXCOORD_2+ have render and browser evidence."
|
|
624
|
-
);
|
|
625
|
-
}
|
|
626
|
-
if (hasMultiUvMaterial && hasUnsupportedMultiUvMaterial) {
|
|
627
|
-
push(
|
|
628
|
-
"ASSET_VIEWER_MULTI_UV_RENDER_FALLBACK",
|
|
629
|
-
"The asset uses texture coordinate sets beyond TEXCOORD_1; the current render path supports two UV streams and falls back for higher sets.",
|
|
630
|
-
"Keep full arbitrary multi-UV material parity blocked until render materials bind and sample TEXCOORD_2+."
|
|
631
|
-
);
|
|
632
|
-
}
|
|
633
|
-
if (asset.textures.some((texture) => /\.ktx2(?:[?#]|$)/i.test(asset.images[texture.source]?.uri ?? ""))) {
|
|
634
|
-
push(
|
|
635
|
-
"ASSET_VIEWER_KTX2_TRANSCODER_REQUIRED",
|
|
636
|
-
"KTX2/Basis textures require a configured browser transcoder target before they can be considered real compressed texture evidence.",
|
|
637
|
-
"Inject a KTX2/Basis transcoder profile and report the selected GPU format plus fallback path."
|
|
638
|
-
);
|
|
639
|
-
}
|
|
640
|
-
if (renderResources) {
|
|
641
|
-
if (renderResources.fallbackWhiteDrawItems > 0) {
|
|
642
|
-
push(
|
|
643
|
-
"GLTF_RENDER_RESOURCE_FALLBACK_WHITE",
|
|
644
|
-
`Render resources contain ${renderResources.fallbackWhiteDrawItems} fallback-white draw item(s): ${renderResources.fallbackWhiteLabels.slice(0, 6).join(", ")}.`,
|
|
645
|
-
"Treat these draw items as material failures unless the source material is intentionally white or texture-backed evidence proves otherwise."
|
|
646
|
-
);
|
|
647
|
-
}
|
|
648
|
-
if (renderResources.missingMaterialDrawItems > 0) {
|
|
649
|
-
push(
|
|
650
|
-
"GLTF_RENDER_RESOURCE_MISSING_MATERIAL",
|
|
651
|
-
`Render resources contain ${renderResources.missingMaterialDrawItems} draw item(s) with no runtime material binding: ${renderResources.missingMaterialLabels.slice(0, 6).join(", ")}.`,
|
|
652
|
-
"Fix the glTF material binding or report the exact unsupported primitive before counting this asset as render-ready."
|
|
653
|
-
);
|
|
654
|
-
}
|
|
655
|
-
if (renderResources.missingGeometryDrawItems > 0) {
|
|
656
|
-
push(
|
|
657
|
-
"GLTF_RENDER_RESOURCE_MISSING_GEOMETRY",
|
|
658
|
-
`Render resources contain ${renderResources.missingGeometryDrawItems} draw item(s) with no runtime geometry binding: ${renderResources.missingGeometryLabels.slice(0, 6).join(", ")}.`,
|
|
659
|
-
"Fix the glTF primitive geometry binding or report the exact unsupported primitive before counting this asset as render-ready."
|
|
660
|
-
);
|
|
661
|
-
}
|
|
662
|
-
if (renderResources.unsupportedTexCoordDrawItems > 0) {
|
|
663
|
-
const labels = renderResources.materialFidelityDiagnostics
|
|
664
|
-
.filter((diagnostic) => diagnostic.issue === "unsupported-texcoord-set")
|
|
665
|
-
.slice(0, 6)
|
|
666
|
-
.map((diagnostic) => `${diagnostic.nodeName}:${diagnostic.slot}:TEXCOORD_${diagnostic.texCoord}->TEXCOORD_${diagnostic.renderedTexCoord}`);
|
|
667
|
-
push(
|
|
668
|
-
"GLTF_RENDER_RESOURCE_TEXCOORD_DOWNGRADED",
|
|
669
|
-
`Render resources downgrade ${renderResources.unsupportedTexCoordDrawItems} draw item(s) that reference TEXCOORD_2 or higher: ${labels.join(", ")}.`,
|
|
670
|
-
"Bind and sample the authored texture coordinate set before counting this material as full glTF texture parity."
|
|
671
|
-
);
|
|
672
|
-
}
|
|
673
|
-
if (renderResources.generatedTangentUvMismatchDrawItems > 0) {
|
|
674
|
-
const labels = renderResources.materialFidelityDiagnostics
|
|
675
|
-
.filter((diagnostic) => diagnostic.issue === "generated-tangent-uv-mismatch")
|
|
676
|
-
.slice(0, 6)
|
|
677
|
-
.map((diagnostic) => `${diagnostic.nodeName}:${diagnostic.slot}:TEXCOORD_${diagnostic.texCoord}`);
|
|
678
|
-
push(
|
|
679
|
-
"GLTF_RENDER_RESOURCE_TANGENT_UV_MISMATCH",
|
|
680
|
-
`Render resources generated tangent space from TEXCOORD_0 for ${renderResources.generatedTangentUvMismatchDrawItems} draw item(s) with normal-map slots on another coordinate set: ${labels.join(", ")}.`,
|
|
681
|
-
"Use authored tangents or generate tangents from the sampled normal-map coordinate set before treating the normal/clearcoat normal response as faithful."
|
|
682
|
-
);
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
|
|
686
|
-
return warnings;
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
function isMaterialExtensionName(extension: string): boolean {
|
|
690
|
-
return /(?:^|_)materials?_/.test(extension) || /material/i.test(extension);
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
function isUnbackedTransmissionMaterial(material: GLTFMaterialAsset): boolean {
|
|
694
|
-
const transmission = material.transmission?.factor ?? 0;
|
|
695
|
-
const diffuseTransmission = material.diffuseTransmission?.factor ?? 0;
|
|
696
|
-
if (transmission <= 0 && diffuseTransmission <= 0) return false;
|
|
697
|
-
return material.volume === undefined &&
|
|
698
|
-
material.transmission?.texture === undefined &&
|
|
699
|
-
material.diffuseTransmission?.texture === undefined &&
|
|
700
|
-
material.diffuseTransmission?.colorTexture === undefined;
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
function summarizeMaterialNames(materials: readonly GLTFMaterialAsset[]): string {
|
|
704
|
-
const names = materials.slice(0, 4).map((material) => material.name || "material").join(", ");
|
|
705
|
-
return materials.length > 4 ? `${names}, +${materials.length - 4} more` : names;
|
|
706
|
-
}
|