@babylonjs/loaders 9.7.0 → 9.9.0
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/SPLAT/splatFileLoader.js +11 -3
- package/SPLAT/splatFileLoader.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js +4 -0
- package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_materials_transmission.js +3 -331
- package/glTF/2.0/Extensions/KHR_materials_transmission.js.map +1 -1
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.js +2 -1
- package/glTF/2.0/Extensions/MSFT_minecraftMesh.js.map +1 -1
- package/glTF/2.0/Extensions/index.d.ts +1 -0
- package/glTF/2.0/Extensions/index.js +1 -0
- package/glTF/2.0/Extensions/index.js.map +1 -1
- package/glTF/2.0/Extensions/transmissionHelper.d.ts +157 -0
- package/glTF/2.0/Extensions/transmissionHelper.js +373 -0
- package/glTF/2.0/Extensions/transmissionHelper.js.map +1 -0
- package/glTF/2.0/glTFLoader.d.ts +26 -7
- package/glTF/2.0/glTFLoader.js +107 -58
- package/glTF/2.0/glTFLoader.js.map +1 -1
- package/glTF/2.0/materialLoadingAdapter.d.ts +8 -10
- package/glTF/2.0/materialLoadingAdapter.js.map +1 -1
- package/glTF/2.0/openpbrMaterialLoadingAdapter.d.ts +3 -3
- package/glTF/2.0/openpbrMaterialLoadingAdapter.js +17 -18
- package/glTF/2.0/openpbrMaterialLoadingAdapter.js.map +1 -1
- package/glTF/2.0/pbrMaterialLoadingAdapter.d.ts +6 -0
- package/glTF/2.0/pbrMaterialLoadingAdapter.js +5 -0
- package/glTF/2.0/pbrMaterialLoadingAdapter.js.map +1 -1
- package/package.json +3 -3
package/glTF/2.0/glTFLoader.js
CHANGED
|
@@ -10,6 +10,7 @@ import { Material } from "@babylonjs/core/Materials/material.js";
|
|
|
10
10
|
import { Texture } from "@babylonjs/core/Materials/Textures/texture.js";
|
|
11
11
|
import { TransformNode } from "@babylonjs/core/Meshes/transformNode.js";
|
|
12
12
|
import { Buffer, VertexBuffer } from "@babylonjs/core/Buffers/buffer.js";
|
|
13
|
+
import { VertexBufferForEach, VertexBufferGetTypeByteLength } from "@babylonjs/core/Buffers/buffer.pure.js";
|
|
13
14
|
import { Geometry } from "@babylonjs/core/Meshes/geometry.js";
|
|
14
15
|
import { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh.js";
|
|
15
16
|
import { Mesh } from "@babylonjs/core/Meshes/mesh.js";
|
|
@@ -105,13 +106,19 @@ export function LoadBoundingInfoFromPositionAccessor(accessor) {
|
|
|
105
106
|
*/
|
|
106
107
|
export class GLTFLoader {
|
|
107
108
|
/**
|
|
108
|
-
* Test if the given material is
|
|
109
|
+
* Test if the given material is an instance of any PBR material type known to this loader.
|
|
109
110
|
* @param material The material to test
|
|
110
|
-
* @returns true if the material
|
|
111
|
+
* @returns true if the material matches one of the loaded PBR implementations
|
|
111
112
|
*/
|
|
112
113
|
isMatchingMaterialType(material) {
|
|
113
|
-
if (material
|
|
114
|
-
return
|
|
114
|
+
if (!material) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
const materialImpls = Array.from(this._pbrMaterialImpls.values());
|
|
118
|
+
for (const impl of materialImpls) {
|
|
119
|
+
if (material instanceof impl.materialClass) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
115
122
|
}
|
|
116
123
|
return false;
|
|
117
124
|
}
|
|
@@ -181,8 +188,6 @@ export class GLTFLoader {
|
|
|
181
188
|
constructor(parent) {
|
|
182
189
|
/** @internal */
|
|
183
190
|
this._completePromises = new Array();
|
|
184
|
-
/** AbortController used to cancel in-flight finalizeAsync() calls when dispose() is called. */
|
|
185
|
-
this._finalizeController = null;
|
|
186
191
|
/** @internal */
|
|
187
192
|
this._assetContainer = null;
|
|
188
193
|
/** Storage */
|
|
@@ -194,6 +199,7 @@ export class GLTFLoader {
|
|
|
194
199
|
/** @internal */
|
|
195
200
|
this._skipStartAnimationStep = false;
|
|
196
201
|
this._extensions = new Array();
|
|
202
|
+
/** @internal */
|
|
197
203
|
this._disposed = false;
|
|
198
204
|
this._rootUrl = null;
|
|
199
205
|
this._fileName = null;
|
|
@@ -204,8 +210,13 @@ export class GLTFLoader {
|
|
|
204
210
|
this._postSceneLoadActions = new Array();
|
|
205
211
|
this._materialAdapterCache = new WeakMap();
|
|
206
212
|
this._materialAdapters = new Set();
|
|
207
|
-
/**
|
|
208
|
-
|
|
213
|
+
/**
|
|
214
|
+
* Loaded PBR material implementations, keyed by their identifier (e.g. "pbr", "openpbr").
|
|
215
|
+
* Only populated after the load has started and only for the types actually needed by the asset.
|
|
216
|
+
* Empty when PBR materials are disabled (skipMaterials).
|
|
217
|
+
* @internal
|
|
218
|
+
*/
|
|
219
|
+
this._pbrMaterialImpls = new Map();
|
|
209
220
|
this._parent = parent;
|
|
210
221
|
}
|
|
211
222
|
/**
|
|
@@ -217,10 +228,14 @@ export class GLTFLoader {
|
|
|
217
228
|
_getOrCreateMaterialAdapter(material) {
|
|
218
229
|
let adapter = this._materialAdapterCache.get(material);
|
|
219
230
|
if (!adapter) {
|
|
220
|
-
|
|
221
|
-
|
|
231
|
+
const materialImpls = Array.from(this._pbrMaterialImpls.values());
|
|
232
|
+
for (const impl of materialImpls) {
|
|
233
|
+
if (material instanceof impl.materialClass) {
|
|
234
|
+
adapter = new impl.adapterClass(material);
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
222
237
|
}
|
|
223
|
-
|
|
238
|
+
if (!adapter) {
|
|
224
239
|
throw new Error(`Appropriate material adapter class not found`);
|
|
225
240
|
}
|
|
226
241
|
const createdAdapter = adapter;
|
|
@@ -235,8 +250,6 @@ export class GLTFLoader {
|
|
|
235
250
|
return;
|
|
236
251
|
}
|
|
237
252
|
this._disposed = true;
|
|
238
|
-
this._finalizeController?.abort();
|
|
239
|
-
this._finalizeController = null;
|
|
240
253
|
this._completePromises.length = 0;
|
|
241
254
|
this._extensions.forEach((extension) => extension.dispose && extension.dispose());
|
|
242
255
|
this._extensions.length = 0;
|
|
@@ -306,20 +319,35 @@ export class GLTFLoader {
|
|
|
306
319
|
this._fileName = fileName;
|
|
307
320
|
this._allMaterialsDirtyRequired = false;
|
|
308
321
|
await this._loadExtensionsAsync();
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
};
|
|
322
|
+
if (!this.parent.skipMaterials) {
|
|
323
|
+
const needsOpenPBR = this.parent.useOpenPBR || this.isExtensionUsed("KHR_materials_openpbr");
|
|
324
|
+
let needsPBR = false;
|
|
325
|
+
if (!this.parent.useOpenPBR) {
|
|
326
|
+
// PBR is needed when useOpenPBR is turned off.
|
|
327
|
+
needsPBR = true;
|
|
316
328
|
}
|
|
317
|
-
else {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
329
|
+
else if (this._gltf.materials?.length && this._gltf.materials.some((m) => !m.extensions?.["KHR_materials_openpbr"])) {
|
|
330
|
+
// PBR is needed if there is at least one material that does not use the KHR_materials_openpbr extension (i.e. relies on the default PBR implementation).
|
|
331
|
+
needsPBR = true;
|
|
332
|
+
}
|
|
333
|
+
const implPromises = [];
|
|
334
|
+
if (needsOpenPBR && !this._pbrMaterialImpls.has("openpbr")) {
|
|
335
|
+
implPromises.push(Promise.all([import("@babylonjs/core/Materials/PBR/openpbrMaterial.js"), import("./openpbrMaterialLoadingAdapter.js")]).then(([{ OpenPBRMaterial: openPBRMaterialClass }, { OpenPBRMaterialLoadingAdapter: openPBRAdapterClass }]) => {
|
|
336
|
+
this._pbrMaterialImpls.set("openpbr", {
|
|
337
|
+
materialClass: openPBRMaterialClass,
|
|
338
|
+
adapterClass: openPBRAdapterClass,
|
|
339
|
+
});
|
|
340
|
+
}));
|
|
322
341
|
}
|
|
342
|
+
if (needsPBR && !this._pbrMaterialImpls.has("pbr")) {
|
|
343
|
+
implPromises.push(Promise.all([import("@babylonjs/core/Materials/PBR/pbrMaterial.js"), import("./pbrMaterialLoadingAdapter.js")]).then(([{ PBRMaterial: pbrMaterialClass }, { PBRMaterialLoadingAdapter: pbrAdapterClass }]) => {
|
|
344
|
+
this._pbrMaterialImpls.set("pbr", {
|
|
345
|
+
materialClass: pbrMaterialClass,
|
|
346
|
+
adapterClass: pbrAdapterClass,
|
|
347
|
+
});
|
|
348
|
+
}));
|
|
349
|
+
}
|
|
350
|
+
await Promise.all(implPromises);
|
|
323
351
|
}
|
|
324
352
|
const loadingToReadyCounterName = `${GLTFLoaderState[GLTFLoaderState.LOADING]} => ${GLTFLoaderState[GLTFLoaderState.READY]}`;
|
|
325
353
|
const loadingToCompleteCounterName = `${GLTFLoaderState[GLTFLoaderState.LOADING]} => ${GLTFLoaderState[GLTFLoaderState.COMPLETE]}`;
|
|
@@ -377,25 +405,10 @@ export class GLTFLoader {
|
|
|
377
405
|
}
|
|
378
406
|
}
|
|
379
407
|
// Finalize all material adapters. finalizeAsync() may return a Promise for async
|
|
380
|
-
// work (e.g. GPU texture processing);
|
|
381
|
-
// _completePromises so
|
|
382
|
-
// Fall back to the deprecated finalize() for third-party adapters that have not
|
|
383
|
-
// yet migrated, logging a warning so authors know to update.
|
|
384
|
-
// An AbortController is created here and aborted in dispose() so that adapters
|
|
385
|
-
// can detect mid-flight disposal and clean up intermediate resources early.
|
|
386
|
-
this._finalizeController = new AbortController();
|
|
387
|
-
const finalizeSignal = this._finalizeController.signal;
|
|
408
|
+
// work (e.g. GPU texture processing); any returned Promise is pushed into
|
|
409
|
+
// _completePromises so it is awaited before the COMPLETE state is reached.
|
|
388
410
|
for (const adapter of Array.from(this._materialAdapters)) {
|
|
389
|
-
|
|
390
|
-
const finalizePromise = adapter.finalizeAsync(finalizeSignal);
|
|
391
|
-
if (finalizePromise) {
|
|
392
|
-
this._completePromises.push(finalizePromise);
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
else if (adapter.finalize) {
|
|
396
|
-
Logger.Warn("GLTFLoader: IMaterialLoadingAdapter.finalize() is deprecated. Implement finalizeAsync() instead.");
|
|
397
|
-
adapter.finalize();
|
|
398
|
-
}
|
|
411
|
+
this._completePromises.push(adapter.finalizeAsync(this));
|
|
399
412
|
}
|
|
400
413
|
this._extensionsOnReady();
|
|
401
414
|
this._parent._setState(GLTFLoaderState.READY);
|
|
@@ -884,7 +897,7 @@ export class GLTFLoader {
|
|
|
884
897
|
if (primitive.material == undefined) {
|
|
885
898
|
let babylonMaterial = this._defaultBabylonMaterialData[babylonDrawMode];
|
|
886
899
|
if (!babylonMaterial) {
|
|
887
|
-
babylonMaterial = this._createDefaultMaterial("__GLTFLoader._default", babylonDrawMode);
|
|
900
|
+
babylonMaterial = this._createDefaultMaterial("__GLTFLoader._default", babylonDrawMode, this._getDefaultImpl());
|
|
888
901
|
this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial);
|
|
889
902
|
this._defaultBabylonMaterialData[babylonDrawMode] = babylonMaterial;
|
|
890
903
|
}
|
|
@@ -1621,7 +1634,7 @@ export class GLTFLoader {
|
|
|
1621
1634
|
return accessor._data;
|
|
1622
1635
|
}
|
|
1623
1636
|
const numComponents = GLTFLoader._GetNumComponents(context, accessor.type);
|
|
1624
|
-
const byteStride = numComponents *
|
|
1637
|
+
const byteStride = numComponents * VertexBufferGetTypeByteLength(accessor.componentType);
|
|
1625
1638
|
const length = numComponents * accessor.count;
|
|
1626
1639
|
if (accessor.bufferView == undefined) {
|
|
1627
1640
|
accessor._data = Promise.resolve(new constructor(length));
|
|
@@ -1634,7 +1647,7 @@ export class GLTFLoader {
|
|
|
1634
1647
|
}
|
|
1635
1648
|
else {
|
|
1636
1649
|
const typedArray = new constructor(length);
|
|
1637
|
-
|
|
1650
|
+
VertexBufferForEach(data, accessor.byteOffset || 0, bufferView.byteStride || byteStride, numComponents, accessor.componentType, typedArray.length, accessor.normalized || false, (value, index) => {
|
|
1638
1651
|
typedArray[index] = value;
|
|
1639
1652
|
});
|
|
1640
1653
|
return typedArray;
|
|
@@ -1660,7 +1673,7 @@ export class GLTFLoader {
|
|
|
1660
1673
|
else {
|
|
1661
1674
|
const sparseData = GLTFLoader._GetTypedArray(`${context}/sparse/values`, accessor.componentType, valuesData, sparse.values.byteOffset, sparseLength);
|
|
1662
1675
|
values = new constructor(sparseLength);
|
|
1663
|
-
|
|
1676
|
+
VertexBufferForEach(sparseData, 0, byteStride, numComponents, accessor.componentType, values.length, accessor.normalized || false, (value, index) => {
|
|
1664
1677
|
values[index] = value;
|
|
1665
1678
|
});
|
|
1666
1679
|
}
|
|
@@ -1820,16 +1833,52 @@ export class GLTFLoader {
|
|
|
1820
1833
|
return babylonData.babylonMaterial;
|
|
1821
1834
|
});
|
|
1822
1835
|
}
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1836
|
+
/**
|
|
1837
|
+
* Selects the appropriate PBR material implementation for a given glTF material.
|
|
1838
|
+
* Uses OpenPBR when the material carries a "KHR_materials_openpbr" extension or when
|
|
1839
|
+
* the loader-level `useOpenPBR` flag is set; falls back to standard PBR otherwise.
|
|
1840
|
+
* @param material The glTF material
|
|
1841
|
+
* @returns The matching loaded implementation
|
|
1842
|
+
*/
|
|
1843
|
+
_selectImplForGltfMaterial(material) {
|
|
1844
|
+
if (this.parent.useOpenPBR || material.extensions?.["KHR_materials_openpbr"]) {
|
|
1845
|
+
const impl = this._pbrMaterialImpls.get("openpbr");
|
|
1846
|
+
if (impl) {
|
|
1847
|
+
return impl;
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
const impl = this._pbrMaterialImpls.get("pbr");
|
|
1851
|
+
if (impl) {
|
|
1852
|
+
return impl;
|
|
1826
1853
|
}
|
|
1854
|
+
throw new Error("No PBR material implementation loaded");
|
|
1855
|
+
}
|
|
1856
|
+
/**
|
|
1857
|
+
* Returns the default PBR material implementation used when there is no per-material
|
|
1858
|
+
* selection context (e.g. when creating the built-in default material for primitives
|
|
1859
|
+
* that have no glTF material assigned). Prefers OpenPBR when `useOpenPBR` is set.
|
|
1860
|
+
* @returns The default loaded implementation
|
|
1861
|
+
*/
|
|
1862
|
+
_getDefaultImpl() {
|
|
1863
|
+
if (this.parent.useOpenPBR) {
|
|
1864
|
+
const impl = this._pbrMaterialImpls.get("openpbr");
|
|
1865
|
+
if (impl) {
|
|
1866
|
+
return impl;
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
const impl = this._pbrMaterialImpls.get("pbr") ?? this._pbrMaterialImpls.values().next().value;
|
|
1870
|
+
if (impl) {
|
|
1871
|
+
return impl;
|
|
1872
|
+
}
|
|
1873
|
+
throw new Error("No PBR material implementation loaded");
|
|
1874
|
+
}
|
|
1875
|
+
_createDefaultMaterial(name, babylonDrawMode, impl) {
|
|
1827
1876
|
this._babylonScene._blockEntityCollection = !!this._assetContainer;
|
|
1828
|
-
const babylonMaterial = new
|
|
1877
|
+
const babylonMaterial = new impl.materialClass(name, this._babylonScene);
|
|
1829
1878
|
babylonMaterial._parentContainer = this._assetContainer;
|
|
1830
1879
|
this._babylonScene._blockEntityCollection = false;
|
|
1831
1880
|
babylonMaterial.fillMode = babylonDrawMode;
|
|
1832
|
-
babylonMaterial.transparencyMode =
|
|
1881
|
+
babylonMaterial.transparencyMode = impl.materialClass.MATERIAL_OPAQUE;
|
|
1833
1882
|
// Create the material adapter and set some default properties.
|
|
1834
1883
|
// We don't need to wait for the promise to resolve here.
|
|
1835
1884
|
const adapter = this._getOrCreateMaterialAdapter(babylonMaterial);
|
|
@@ -1852,7 +1901,7 @@ export class GLTFLoader {
|
|
|
1852
1901
|
return extensionMaterial;
|
|
1853
1902
|
}
|
|
1854
1903
|
const name = material.name || `material${material.index}`;
|
|
1855
|
-
const babylonMaterial = this._createDefaultMaterial(name, babylonDrawMode);
|
|
1904
|
+
const babylonMaterial = this._createDefaultMaterial(name, babylonDrawMode, this._selectImplForGltfMaterial(material));
|
|
1856
1905
|
return babylonMaterial;
|
|
1857
1906
|
}
|
|
1858
1907
|
/**
|
|
@@ -1942,7 +1991,7 @@ export class GLTFLoader {
|
|
|
1942
1991
|
* @param babylonMaterial The Babylon material
|
|
1943
1992
|
*/
|
|
1944
1993
|
loadMaterialAlphaProperties(context, material, babylonMaterial) {
|
|
1945
|
-
if (
|
|
1994
|
+
if (this._pbrMaterialImpls.size === 0) {
|
|
1946
1995
|
throw new Error(`${context}: Material type not supported`);
|
|
1947
1996
|
}
|
|
1948
1997
|
const adapter = this._getOrCreateMaterialAdapter(babylonMaterial);
|
|
@@ -1950,12 +1999,12 @@ export class GLTFLoader {
|
|
|
1950
1999
|
const alphaMode = material.alphaMode || "OPAQUE" /* MaterialAlphaMode.OPAQUE */;
|
|
1951
2000
|
switch (alphaMode) {
|
|
1952
2001
|
case "OPAQUE" /* MaterialAlphaMode.OPAQUE */: {
|
|
1953
|
-
babylonMaterial.transparencyMode =
|
|
2002
|
+
babylonMaterial.transparencyMode = Material.MATERIAL_OPAQUE;
|
|
1954
2003
|
babylonMaterial.alpha = 1.0; // Force alpha to 1.0 for opaque mode.
|
|
1955
2004
|
break;
|
|
1956
2005
|
}
|
|
1957
2006
|
case "MASK" /* MaterialAlphaMode.MASK */: {
|
|
1958
|
-
babylonMaterial.transparencyMode =
|
|
2007
|
+
babylonMaterial.transparencyMode = Material.MATERIAL_ALPHATEST;
|
|
1959
2008
|
adapter.alphaCutOff = material.alphaCutoff == undefined ? 0.5 : material.alphaCutoff;
|
|
1960
2009
|
if (baseColorTexture) {
|
|
1961
2010
|
baseColorTexture.hasAlpha = true;
|
|
@@ -1963,7 +2012,7 @@ export class GLTFLoader {
|
|
|
1963
2012
|
break;
|
|
1964
2013
|
}
|
|
1965
2014
|
case "BLEND" /* MaterialAlphaMode.BLEND */: {
|
|
1966
|
-
babylonMaterial.transparencyMode =
|
|
2015
|
+
babylonMaterial.transparencyMode = Material.MATERIAL_ALPHABLEND;
|
|
1967
2016
|
if (baseColorTexture) {
|
|
1968
2017
|
baseColorTexture.hasAlpha = true;
|
|
1969
2018
|
adapter.useAlphaFromBaseColorTexture = true;
|
|
@@ -2219,7 +2268,7 @@ export class GLTFLoader {
|
|
|
2219
2268
|
const buffer = bufferView.buffer;
|
|
2220
2269
|
byteOffset = bufferView.byteOffset + (byteOffset || 0);
|
|
2221
2270
|
const constructor = GLTFLoader._GetTypedArrayConstructor(`${context}/componentType`, componentType);
|
|
2222
|
-
const componentTypeLength =
|
|
2271
|
+
const componentTypeLength = VertexBufferGetTypeByteLength(componentType);
|
|
2223
2272
|
if (byteOffset % componentTypeLength !== 0) {
|
|
2224
2273
|
// HACK: Copy the buffer if byte offset is not a multiple of component type byte length.
|
|
2225
2274
|
Logger.Warn(`${context}: Copying buffer as byte offset (${byteOffset}) is not a multiple of component type byte length (${componentTypeLength})`);
|