@babylonjs/serializers 8.34.1 → 8.35.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.
@@ -8,7 +8,7 @@ import { GetTextureDataAsync, TextureTools } from "@babylonjs/core/Misc/textureT
8
8
  import { Texture } from "@babylonjs/core/Materials/Textures/texture.js";
9
9
  import { RawTexture } from "@babylonjs/core/Materials/Textures/rawTexture.js";
10
10
  import { Constants } from "@babylonjs/core/Engines/constants.js";
11
- import { DumpTools } from "@babylonjs/core/Misc/dumpTools.js";
11
+ import { EncodeImageAsync } from "@babylonjs/core/Misc/dumpTools.js";
12
12
  import { PBRBaseMaterial } from "@babylonjs/core/Materials/PBR/pbrBaseMaterial.js";
13
13
  import { SpecularPowerToRoughness } from "@babylonjs/core/Helpers/materialConversionHelper.js";
14
14
  import { GetMimeType } from "@babylonjs/core/Misc/fileTools.js";
@@ -33,6 +33,22 @@ function GetFileExtensionFromMimeType(mimeType) {
33
33
  return ".ktx2";
34
34
  }
35
35
  }
36
+ /**
37
+ * @param mimeType the MIME type requested by the user
38
+ * @returns true if the given mime type is compatible with glTF
39
+ */
40
+ function IsSupportedMimeType(mimeType) {
41
+ switch (mimeType) {
42
+ case "image/jpeg" /* ImageMimeType.JPEG */:
43
+ case "image/png" /* ImageMimeType.PNG */:
44
+ case "image/webp" /* ImageMimeType.WEBP */:
45
+ case "image/avif" /* ImageMimeType.AVIF */:
46
+ case "image/ktx2" /* ImageMimeType.KTX2 */:
47
+ return true;
48
+ default:
49
+ return false;
50
+ }
51
+ }
36
52
  /**
37
53
  * Gets cached image from a texture, if available.
38
54
  * @param babylonTexture texture to check for cached image
@@ -71,8 +87,8 @@ async function GetCachedImageAsync(babylonTexture) {
71
87
  data = await Tools.LoadFileAsync(buffer.src);
72
88
  mimeType = GetMimeType(buffer.src) || mimeType;
73
89
  }
74
- if (data && mimeType) {
75
- return { data, mimeType };
90
+ if (data && IsSupportedMimeType(mimeType)) {
91
+ return new Blob([data], { type: mimeType });
76
92
  }
77
93
  return null;
78
94
  }
@@ -245,9 +261,6 @@ export class GLTFMaterialExporter {
245
261
  await Promise.all(promises);
246
262
  await this._exporter._extensionsPostExportMaterialAsync("exportMaterial", glTFMaterial, babylonMaterial);
247
263
  }
248
- async _getImageDataAsync(buffer, width, height, mimeType) {
249
- return await DumpTools.DumpDataAsync(width, height, buffer, mimeType, undefined, false, true);
250
- }
251
264
  /**
252
265
  * Resizes the two source textures to the same dimensions. If a texture is null, a default white texture is generated. If both textures are null, returns null
253
266
  * @param texture1 first texture to resize
@@ -294,10 +307,9 @@ export class GLTFMaterialExporter {
294
307
  * @param diffuseTexture texture used to store diffuse information
295
308
  * @param specularGlossinessTexture texture used to store specular and glossiness information
296
309
  * @param factors specular glossiness material factors
297
- * @param mimeType the mime type to use for the texture
298
310
  * @returns pbr metallic roughness interface or null
299
311
  */
300
- async _convertSpecularGlossinessTexturesToMetallicRoughnessAsync(diffuseTexture, specularGlossinessTexture, factors, mimeType) {
312
+ async _convertSpecularGlossinessTexturesToMetallicRoughnessAsync(diffuseTexture, specularGlossinessTexture, factors) {
301
313
  const promises = new Array();
302
314
  if (!(diffuseTexture || specularGlossinessTexture)) {
303
315
  return await Promise.reject("diffuse and specular glossiness textures are not defined!");
@@ -393,12 +405,12 @@ export class GLTFMaterialExporter {
393
405
  }
394
406
  }
395
407
  if (writeOutMetallicRoughnessTexture) {
396
- promises.push(this._getImageDataAsync(metallicRoughnessBuffer, width, height, mimeType).then((data) => {
408
+ promises.push(EncodeImageAsync(metallicRoughnessBuffer, width, height).then((data) => {
397
409
  metallicRoughnessFactors.metallicRoughnessTextureData = data;
398
410
  }));
399
411
  }
400
412
  if (writeOutBaseColorTexture) {
401
- promises.push(this._getImageDataAsync(baseColorBuffer, width, height, mimeType).then((data) => {
413
+ promises.push(EncodeImageAsync(baseColorBuffer, width, height).then((data) => {
402
414
  metallicRoughnessFactors.baseColorTextureData = data;
403
415
  }));
404
416
  }
@@ -648,7 +660,6 @@ export class GLTFMaterialExporter {
648
660
  * @returns glTF PBR Metallic Roughness factors
649
661
  */
650
662
  async _convertSpecGlossFactorsToMetallicRoughnessAsync(babylonPBRMaterial, pbrMetallicRoughness, hasUVs) {
651
- const mimeType = "image/png" /* ImageMimeType.PNG */;
652
663
  const specGloss = {
653
664
  diffuseColor: babylonPBRMaterial._albedoColor,
654
665
  specularColor: babylonPBRMaterial._reflectivityColor,
@@ -663,14 +674,14 @@ export class GLTFMaterialExporter {
663
674
  if ((albedoTexture || reflectivityTexture) && hasUVs) {
664
675
  this._exporter._materialNeedsUVsSet.add(babylonPBRMaterial);
665
676
  const samplerIndex = this._exportTextureSampler(albedoTexture || reflectivityTexture);
666
- const metallicRoughnessFactors = await this._convertSpecularGlossinessTexturesToMetallicRoughnessAsync(albedoTexture, reflectivityTexture, specGloss, mimeType);
677
+ const metallicRoughnessFactors = await this._convertSpecularGlossinessTexturesToMetallicRoughnessAsync(albedoTexture, reflectivityTexture, specGloss);
667
678
  const textures = this._exporter._textures;
668
679
  if (metallicRoughnessFactors.baseColorTextureData) {
669
- const imageIndex = this._exportImage(`baseColor${textures.length}`, mimeType, metallicRoughnessFactors.baseColorTextureData);
680
+ const imageIndex = await this._exportImageAsync(`baseColor${textures.length}`, metallicRoughnessFactors.baseColorTextureData);
670
681
  pbrMetallicRoughness.baseColorTexture = this._exportTextureInfo(imageIndex, samplerIndex, albedoTexture?.coordinatesIndex);
671
682
  }
672
683
  if (metallicRoughnessFactors.metallicRoughnessTextureData) {
673
- const imageIndex = this._exportImage(`metallicRoughness${textures.length}`, mimeType, metallicRoughnessFactors.metallicRoughnessTextureData);
684
+ const imageIndex = await this._exportImageAsync(`metallicRoughness${textures.length}`, metallicRoughnessFactors.metallicRoughnessTextureData);
674
685
  pbrMetallicRoughness.metallicRoughnessTexture = this._exportTextureInfo(imageIndex, samplerIndex, reflectivityTexture?.coordinatesIndex);
675
686
  }
676
687
  return metallicRoughnessFactors;
@@ -824,48 +835,46 @@ export class GLTFMaterialExporter {
824
835
  imageIndexPromise = (async () => {
825
836
  // Try to get the image from memory first, if applicable
826
837
  const cache = await GetCachedImageAsync(babylonTexture);
827
- if (cache && (requestedMimeType === "none" || cache.mimeType === requestedMimeType)) {
828
- return this._exportImage(babylonTexture.name, cache.mimeType, cache.data);
838
+ if (cache && (requestedMimeType === "none" || cache.type === requestedMimeType)) {
839
+ return await this._exportImageAsync(babylonTexture.name, cache);
829
840
  }
830
841
  // Preserve texture mime type if defined
831
842
  let mimeType = "image/png" /* ImageMimeType.PNG */;
832
843
  if (requestedMimeType !== "none") {
833
- switch (requestedMimeType) {
834
- case "image/jpeg" /* ImageMimeType.JPEG */:
835
- case "image/png" /* ImageMimeType.PNG */:
836
- case "image/webp" /* ImageMimeType.WEBP */:
837
- mimeType = requestedMimeType;
838
- break;
839
- default:
840
- Tools.Warn(`Unsupported media type: ${requestedMimeType}. Exporting texture as PNG.`);
841
- break;
844
+ if (IsSupportedMimeType(requestedMimeType)) {
845
+ mimeType = requestedMimeType;
846
+ }
847
+ else {
848
+ mimeType = "image/png" /* ImageMimeType.PNG */;
849
+ Tools.Warn(`Unsupported media type: ${requestedMimeType}. Exporting texture as PNG.`);
842
850
  }
843
851
  }
844
852
  const size = babylonTexture.getSize();
845
853
  const pixels = await GetTextureDataAsync(babylonTexture);
846
- const data = await this._getImageDataAsync(pixels, size.width, size.height, mimeType);
847
- return this._exportImage(babylonTexture.name, mimeType, data);
854
+ const imageData = await EncodeImageAsync(pixels, size.width, size.height, mimeType);
855
+ return await this._exportImageAsync(babylonTexture.name, imageData);
848
856
  })();
849
857
  internalTextureToImage[internalTextureUniqueId][requestedMimeType] = imageIndexPromise;
850
858
  }
851
859
  return await imageIndexPromise;
852
860
  }
853
- _exportImage(name, mimeType, data) {
861
+ async _exportImageAsync(name, imageData) {
854
862
  const images = this._exporter._images;
855
863
  let image;
856
864
  if (this._exporter._shouldUseGlb) {
857
865
  image = {
858
866
  name: name,
859
- mimeType: mimeType,
867
+ mimeType: imageData.type,
860
868
  bufferView: undefined, // Will be updated later by BufferManager
861
869
  };
870
+ const data = await imageData.arrayBuffer();
862
871
  const bufferView = this._exporter._bufferManager.createBufferView(new Uint8Array(data));
863
872
  this._exporter._bufferManager.setBufferView(image, bufferView);
864
873
  }
865
874
  else {
866
875
  // Build a unique URI
867
876
  const baseName = name.replace(/\.\/|\/|\.\\|\\/g, "_");
868
- const extension = GetFileExtensionFromMimeType(mimeType);
877
+ const extension = GetFileExtensionFromMimeType(imageData.type);
869
878
  let fileName = baseName + extension;
870
879
  if (images.some((image) => image.uri === fileName)) {
871
880
  fileName = `${baseName}_${Tools.RandomId()}${extension}`;
@@ -874,7 +883,7 @@ export class GLTFMaterialExporter {
874
883
  name: name,
875
884
  uri: fileName,
876
885
  };
877
- this._exporter._imageData[fileName] = { data: data, mimeType: mimeType }; // Save image data to be written to file later
886
+ this._exporter._imageData[fileName] = imageData; // Save image data to be written to file later
878
887
  }
879
888
  images.push(image);
880
889
  return images.length - 1;