@babylonjs/serializers 7.37.1 → 7.37.2

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.
Files changed (70) hide show
  1. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.d.ts +6 -7
  2. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js +18 -12
  3. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js.map +1 -1
  4. package/glTF/2.0/Extensions/KHR_lights_punctual.d.ts +5 -6
  5. package/glTF/2.0/Extensions/KHR_lights_punctual.js +99 -109
  6. package/glTF/2.0/Extensions/KHR_lights_punctual.js.map +1 -1
  7. package/glTF/2.0/Extensions/KHR_materials_anisotropy.d.ts +2 -2
  8. package/glTF/2.0/Extensions/KHR_materials_anisotropy.js +6 -6
  9. package/glTF/2.0/Extensions/KHR_materials_anisotropy.js.map +1 -1
  10. package/glTF/2.0/Extensions/KHR_materials_clearcoat.d.ts +2 -2
  11. package/glTF/2.0/Extensions/KHR_materials_clearcoat.js +9 -9
  12. package/glTF/2.0/Extensions/KHR_materials_clearcoat.js.map +1 -1
  13. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.d.ts +2 -2
  14. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js +7 -7
  15. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js.map +1 -1
  16. package/glTF/2.0/Extensions/KHR_materials_dispersion.js +2 -2
  17. package/glTF/2.0/Extensions/KHR_materials_dispersion.js.map +1 -1
  18. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js +2 -2
  19. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js.map +1 -1
  20. package/glTF/2.0/Extensions/KHR_materials_ior.js +2 -2
  21. package/glTF/2.0/Extensions/KHR_materials_ior.js.map +1 -1
  22. package/glTF/2.0/Extensions/KHR_materials_iridescence.d.ts +2 -2
  23. package/glTF/2.0/Extensions/KHR_materials_iridescence.js +7 -7
  24. package/glTF/2.0/Extensions/KHR_materials_iridescence.js.map +1 -1
  25. package/glTF/2.0/Extensions/KHR_materials_sheen.d.ts +2 -2
  26. package/glTF/2.0/Extensions/KHR_materials_sheen.js +8 -8
  27. package/glTF/2.0/Extensions/KHR_materials_sheen.js.map +1 -1
  28. package/glTF/2.0/Extensions/KHR_materials_specular.d.ts +2 -2
  29. package/glTF/2.0/Extensions/KHR_materials_specular.js +7 -7
  30. package/glTF/2.0/Extensions/KHR_materials_specular.js.map +1 -1
  31. package/glTF/2.0/Extensions/KHR_materials_transmission.d.ts +2 -2
  32. package/glTF/2.0/Extensions/KHR_materials_transmission.js +6 -6
  33. package/glTF/2.0/Extensions/KHR_materials_transmission.js.map +1 -1
  34. package/glTF/2.0/Extensions/KHR_materials_unlit.js +2 -2
  35. package/glTF/2.0/Extensions/KHR_materials_unlit.js.map +1 -1
  36. package/glTF/2.0/Extensions/KHR_materials_volume.d.ts +2 -2
  37. package/glTF/2.0/Extensions/KHR_materials_volume.js +6 -6
  38. package/glTF/2.0/Extensions/KHR_materials_volume.js.map +1 -1
  39. package/glTF/2.0/Extensions/KHR_texture_transform.js +2 -2
  40. package/glTF/2.0/Extensions/KHR_texture_transform.js.map +1 -1
  41. package/glTF/2.0/Extensions/index.d.ts +9 -9
  42. package/glTF/2.0/Extensions/index.js +9 -9
  43. package/glTF/2.0/Extensions/index.js.map +1 -1
  44. package/glTF/2.0/dataWriter.d.ts +18 -0
  45. package/glTF/2.0/dataWriter.js +65 -0
  46. package/glTF/2.0/dataWriter.js.map +1 -0
  47. package/glTF/2.0/glTFAnimation.d.ts +4 -10
  48. package/glTF/2.0/glTFAnimation.js +87 -19
  49. package/glTF/2.0/glTFAnimation.js.map +1 -1
  50. package/glTF/2.0/glTFData.d.ts +5 -3
  51. package/glTF/2.0/glTFData.js +35 -36
  52. package/glTF/2.0/glTFData.js.map +1 -1
  53. package/glTF/2.0/glTFExporter.d.ts +62 -363
  54. package/glTF/2.0/glTFExporter.js +867 -1579
  55. package/glTF/2.0/glTFExporter.js.map +1 -1
  56. package/glTF/2.0/glTFExporterExtension.d.ts +8 -9
  57. package/glTF/2.0/glTFExporterExtension.js.map +1 -1
  58. package/glTF/2.0/glTFMaterialExporter.d.ts +26 -126
  59. package/glTF/2.0/glTFMaterialExporter.js +276 -438
  60. package/glTF/2.0/glTFMaterialExporter.js.map +1 -1
  61. package/glTF/2.0/glTFMorphTargetsUtilities.d.ts +14 -0
  62. package/glTF/2.0/glTFMorphTargetsUtilities.js +105 -0
  63. package/glTF/2.0/glTFMorphTargetsUtilities.js.map +1 -0
  64. package/glTF/2.0/glTFSerializer.d.ts +10 -13
  65. package/glTF/2.0/glTFSerializer.js +25 -44
  66. package/glTF/2.0/glTFSerializer.js.map +1 -1
  67. package/glTF/2.0/glTFUtilities.d.ts +75 -43
  68. package/glTF/2.0/glTFUtilities.js +350 -103
  69. package/glTF/2.0/glTFUtilities.js.map +1 -1
  70. package/package.json +3 -3
@@ -1,3 +1,4 @@
1
+ /* eslint-disable babylonjs/available */
1
2
  import { Vector2 } from "@babylonjs/core/Maths/math.vector.js";
2
3
  import { Color3 } from "@babylonjs/core/Maths/math.color.js";
3
4
  import { Scalar } from "@babylonjs/core/Maths/math.scalar.js";
@@ -7,7 +8,12 @@ import { Texture } from "@babylonjs/core/Materials/Textures/texture.js";
7
8
  import { RawTexture } from "@babylonjs/core/Materials/Textures/rawTexture.js";
8
9
  import { Constants } from "@babylonjs/core/Engines/constants.js";
9
10
  import { DumpTools } from "@babylonjs/core/Misc/dumpTools.js";
10
- function getFileExtensionFromMimeType(mimeType) {
11
+ const epsilon = 1e-6;
12
+ const dielectricSpecular = new Color3(0.04, 0.04, 0.04);
13
+ const maxSpecularPower = 1024;
14
+ const white = Color3.White();
15
+ const black = Color3.Black();
16
+ function GetFileExtensionFromMimeType(mimeType) {
11
17
  switch (mimeType) {
12
18
  case "image/jpeg" /* ImageMimeType.JPEG */:
13
19
  return ".jpg";
@@ -20,202 +26,78 @@ function getFileExtensionFromMimeType(mimeType) {
20
26
  }
21
27
  }
22
28
  /**
23
- * Utility methods for working with glTF material conversion properties. This class should only be used internally
29
+ * Computes the metallic factor.
30
+ * @param diffuse diffused value
31
+ * @param specular specular value
32
+ * @param oneMinusSpecularStrength one minus the specular strength
33
+ * @returns metallic value
24
34
  * @internal
25
35
  */
26
- export class _GLTFMaterialExporter {
27
- constructor(exporter) {
28
- /**
29
- * Mapping to store textures
30
- */
31
- this._textureMap = {};
32
- // Mapping of internal textures to images to avoid exporting duplicate images.
33
- this._internalTextureToImage = {};
34
- this._textureMap = {};
35
- this._exporter = exporter;
36
+ export function _SolveMetallic(diffuse, specular, oneMinusSpecularStrength) {
37
+ if (specular < dielectricSpecular.r) {
38
+ dielectricSpecular;
39
+ return 0;
36
40
  }
37
- /**
38
- * Specifies if two colors are approximately equal in value
39
- * @param color1 first color to compare to
40
- * @param color2 second color to compare to
41
- * @param epsilon threshold value
42
- * @returns boolean specifying if the colors are approximately equal in value
43
- */
44
- static _FuzzyEquals(color1, color2, epsilon) {
45
- return Scalar.WithinEpsilon(color1.r, color2.r, epsilon) && Scalar.WithinEpsilon(color1.g, color2.g, epsilon) && Scalar.WithinEpsilon(color1.b, color2.b, epsilon);
41
+ const a = dielectricSpecular.r;
42
+ const b = (diffuse * oneMinusSpecularStrength) / (1.0 - dielectricSpecular.r) + specular - 2.0 * dielectricSpecular.r;
43
+ const c = dielectricSpecular.r - specular;
44
+ const d = b * b - 4.0 * a * c;
45
+ return Scalar.Clamp((-b + Math.sqrt(d)) / (2.0 * a), 0, 1);
46
+ }
47
+ /**
48
+ * Sets the glTF alpha mode to a glTF material from the Babylon Material
49
+ * @param glTFMaterial glTF material
50
+ * @param babylonMaterial Babylon material
51
+ */
52
+ function SetAlphaMode(glTFMaterial, babylonMaterial) {
53
+ if (babylonMaterial.needAlphaBlending()) {
54
+ glTFMaterial.alphaMode = "BLEND" /* MaterialAlphaMode.BLEND */;
46
55
  }
47
- /**
48
- * Gets the materials from a Babylon scene and converts them to glTF materials
49
- * @param exportMaterials
50
- * @param mimeType texture mime type
51
- * @param hasTextureCoords specifies if texture coordinates are present on the material
52
- * @returns promise that resolves after all materials have been converted
53
- */
54
- _convertMaterialsToGLTFAsync(exportMaterials, mimeType, hasTextureCoords) {
55
- const promises = [];
56
- exportMaterials.forEach((material) => {
57
- if (material.getClassName() === "StandardMaterial") {
58
- promises.push(this._convertStandardMaterialAsync(material, mimeType, hasTextureCoords));
59
- }
60
- else if (material.getClassName().indexOf("PBR") !== -1) {
61
- promises.push(this._convertPBRMaterialAsync(material, mimeType, hasTextureCoords));
62
- }
63
- else {
64
- Tools.Warn(`Unsupported material type: ${material.name}`);
65
- }
66
- });
67
- return Promise.all(promises).then(() => {
68
- /* do nothing */
69
- });
56
+ else if (babylonMaterial.needAlphaTesting()) {
57
+ glTFMaterial.alphaMode = "MASK" /* MaterialAlphaMode.MASK */;
58
+ glTFMaterial.alphaCutoff = babylonMaterial.alphaCutOff;
70
59
  }
71
- /**
72
- * Makes a copy of the glTF material without the texture parameters
73
- * @param originalMaterial original glTF material
74
- * @returns glTF material without texture parameters
75
- */
76
- _stripTexturesFromMaterial(originalMaterial) {
77
- const newMaterial = {};
78
- if (originalMaterial) {
79
- newMaterial.name = originalMaterial.name;
80
- newMaterial.doubleSided = originalMaterial.doubleSided;
81
- newMaterial.alphaMode = originalMaterial.alphaMode;
82
- newMaterial.alphaCutoff = originalMaterial.alphaCutoff;
83
- newMaterial.emissiveFactor = originalMaterial.emissiveFactor;
84
- const originalPBRMetallicRoughness = originalMaterial.pbrMetallicRoughness;
85
- if (originalPBRMetallicRoughness) {
86
- newMaterial.pbrMetallicRoughness = {};
87
- newMaterial.pbrMetallicRoughness.baseColorFactor = originalPBRMetallicRoughness.baseColorFactor;
88
- newMaterial.pbrMetallicRoughness.metallicFactor = originalPBRMetallicRoughness.metallicFactor;
89
- newMaterial.pbrMetallicRoughness.roughnessFactor = originalPBRMetallicRoughness.roughnessFactor;
90
- }
91
- }
92
- return newMaterial;
60
+ }
61
+ function CreateWhiteTexture(width, height, scene) {
62
+ const data = new Uint8Array(width * height * 4);
63
+ for (let i = 0; i < data.length; i = i + 4) {
64
+ data[i] = data[i + 1] = data[i + 2] = data[i + 3] = 0xff;
93
65
  }
94
- /**
95
- * Specifies if the material has any texture parameters present
96
- * @param material glTF Material
97
- * @returns boolean specifying if texture parameters are present
98
- */
99
- _hasTexturesPresent(material) {
100
- if (material.emissiveTexture || material.normalTexture || material.occlusionTexture) {
101
- return true;
102
- }
103
- const pbrMat = material.pbrMetallicRoughness;
104
- if (pbrMat) {
105
- if (pbrMat.baseColorTexture || pbrMat.metallicRoughnessTexture) {
106
- return true;
107
- }
108
- }
109
- if (material.extensions) {
110
- for (const extension in material.extensions) {
111
- const extensionObject = material.extensions[extension];
112
- if (extensionObject) {
113
- return extensionObject.hasTextures?.();
114
- }
115
- }
66
+ const rawTexture = RawTexture.CreateRGBATexture(data, width, height, scene);
67
+ return rawTexture;
68
+ }
69
+ function ConvertPixelArrayToFloat32(pixels) {
70
+ if (pixels instanceof Uint8Array) {
71
+ const length = pixels.length;
72
+ const buffer = new Float32Array(pixels.length);
73
+ for (let i = 0; i < length; ++i) {
74
+ buffer[i] = pixels[i] / 255;
116
75
  }
117
- return false;
76
+ return buffer;
118
77
  }
119
- _getTextureInfo(babylonTexture) {
120
- if (babylonTexture) {
121
- const textureUid = babylonTexture.uid;
122
- if (textureUid in this._textureMap) {
123
- return this._textureMap[textureUid];
124
- }
125
- }
126
- return null;
78
+ else if (pixels instanceof Float32Array) {
79
+ return pixels;
127
80
  }
128
- /**
129
- * Converts a Babylon StandardMaterial to a glTF Metallic Roughness Material
130
- * @param babylonStandardMaterial
131
- * @returns glTF Metallic Roughness Material representation
132
- */
133
- _convertToGLTFPBRMetallicRoughness(babylonStandardMaterial) {
134
- // Defines a cubic bezier curve where x is specular power and y is roughness
135
- const P0 = new Vector2(0, 1);
136
- const P1 = new Vector2(0, 0.1);
137
- const P2 = new Vector2(0, 0.1);
138
- const P3 = new Vector2(1300, 0.1);
139
- /**
140
- * Given the control points, solve for x based on a given t for a cubic bezier curve
141
- * @param t a value between 0 and 1
142
- * @param p0 first control point
143
- * @param p1 second control point
144
- * @param p2 third control point
145
- * @param p3 fourth control point
146
- * @returns number result of cubic bezier curve at the specified t
147
- */
148
- function cubicBezierCurve(t, p0, p1, p2, p3) {
149
- return (1 - t) * (1 - t) * (1 - t) * p0 + 3 * (1 - t) * (1 - t) * t * p1 + 3 * (1 - t) * t * t * p2 + t * t * t * p3;
150
- }
151
- /**
152
- * Evaluates a specified specular power value to determine the appropriate roughness value,
153
- * based on a pre-defined cubic bezier curve with specular on the abscissa axis (x-axis)
154
- * and roughness on the ordinant axis (y-axis)
155
- * @param specularPower specular power of standard material
156
- * @returns Number representing the roughness value
157
- */
158
- function solveForRoughness(specularPower) {
159
- // Given P0.x = 0, P1.x = 0, P2.x = 0
160
- // x = t * t * t * P3.x
161
- // t = (x / P3.x)^(1/3)
162
- const t = Math.pow(specularPower / P3.x, 0.333333);
163
- return cubicBezierCurve(t, P0.y, P1.y, P2.y, P3.y);
164
- }
165
- const diffuse = babylonStandardMaterial.diffuseColor.toLinearSpace(babylonStandardMaterial.getScene().getEngine().useExactSrgbConversions).scale(0.5);
166
- const opacity = babylonStandardMaterial.alpha;
167
- const specularPower = Scalar.Clamp(babylonStandardMaterial.specularPower, 0, _GLTFMaterialExporter._MaxSpecularPower);
168
- const roughness = solveForRoughness(specularPower);
169
- const glTFPbrMetallicRoughness = {
170
- baseColorFactor: [diffuse.r, diffuse.g, diffuse.b, opacity],
171
- metallicFactor: 0,
172
- roughnessFactor: roughness,
173
- };
174
- return glTFPbrMetallicRoughness;
81
+ else {
82
+ throw new Error("Unsupported pixel format!");
175
83
  }
176
- /**
177
- * Computes the metallic factor
178
- * @param diffuse diffused value
179
- * @param specular specular value
180
- * @param oneMinusSpecularStrength one minus the specular strength
181
- * @returns metallic value
182
- */
183
- static _SolveMetallic(diffuse, specular, oneMinusSpecularStrength) {
184
- if (specular < this._DielectricSpecular.r) {
185
- this._DielectricSpecular;
186
- return 0;
187
- }
188
- const a = this._DielectricSpecular.r;
189
- const b = (diffuse * oneMinusSpecularStrength) / (1.0 - this._DielectricSpecular.r) + specular - 2.0 * this._DielectricSpecular.r;
190
- const c = this._DielectricSpecular.r - specular;
191
- const D = b * b - 4.0 * a * c;
192
- return Scalar.Clamp((-b + Math.sqrt(D)) / (2.0 * a), 0, 1);
84
+ }
85
+ /**
86
+ * Utility methods for working with glTF material conversion properties.
87
+ * @internal
88
+ */
89
+ export class GLTFMaterialExporter {
90
+ constructor(_exporter) {
91
+ this._exporter = _exporter;
92
+ // Mapping to store textures
93
+ this._textureMap = new Map();
94
+ // Mapping of internal textures to images to avoid exporting duplicate images
95
+ this._internalTextureToImage = {};
193
96
  }
194
- /**
195
- * Sets the glTF alpha mode to a glTF material from the Babylon Material
196
- * @param glTFMaterial glTF material
197
- * @param babylonMaterial Babylon material
198
- */
199
- static _SetAlphaMode(glTFMaterial, babylonMaterial) {
200
- if (babylonMaterial.needAlphaBlending()) {
201
- glTFMaterial.alphaMode = "BLEND" /* MaterialAlphaMode.BLEND */;
202
- }
203
- else if (babylonMaterial.needAlphaTesting()) {
204
- glTFMaterial.alphaMode = "MASK" /* MaterialAlphaMode.MASK */;
205
- glTFMaterial.alphaCutoff = babylonMaterial.alphaCutOff;
206
- }
97
+ getTextureInfo(babylonTexture) {
98
+ return babylonTexture ? (this._textureMap.get(babylonTexture) ?? null) : null;
207
99
  }
208
- /**
209
- * Converts a Babylon Standard Material to a glTF Material
210
- * @param babylonStandardMaterial BJS Standard Material
211
- * @param mimeType mime type to use for the textures
212
- * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
213
- * @returns promise, resolved with the material
214
- */
215
- _convertStandardMaterialAsync(babylonStandardMaterial, mimeType, hasTextureCoords) {
216
- const materialMap = this._exporter._materialMap;
217
- const materials = this._exporter._materials;
218
- const promises = [];
100
+ async exportStandardMaterialAsync(babylonStandardMaterial, mimeType, hasUVs) {
219
101
  const pbrMetallicRoughness = this._convertToGLTFPBRMetallicRoughness(babylonStandardMaterial);
220
102
  const material = { name: babylonStandardMaterial.name };
221
103
  if (babylonStandardMaterial.backFaceCulling != null && !babylonStandardMaterial.backFaceCulling) {
@@ -224,9 +106,11 @@ export class _GLTFMaterialExporter {
224
106
  }
225
107
  material.doubleSided = true;
226
108
  }
227
- if (hasTextureCoords) {
228
- if (babylonStandardMaterial.diffuseTexture) {
229
- promises.push(this._exportTextureAsync(babylonStandardMaterial.diffuseTexture, mimeType).then((textureInfo) => {
109
+ if (hasUVs) {
110
+ const promises = [];
111
+ const diffuseTexture = babylonStandardMaterial.diffuseTexture;
112
+ if (diffuseTexture) {
113
+ promises.push(this.exportTextureAsync(diffuseTexture, mimeType).then((textureInfo) => {
230
114
  if (textureInfo) {
231
115
  pbrMetallicRoughness.baseColorTexture = textureInfo;
232
116
  }
@@ -234,7 +118,7 @@ export class _GLTFMaterialExporter {
234
118
  }
235
119
  const bumpTexture = babylonStandardMaterial.bumpTexture;
236
120
  if (bumpTexture) {
237
- promises.push(this._exportTextureAsync(bumpTexture, mimeType).then((textureInfo) => {
121
+ promises.push(this.exportTextureAsync(bumpTexture, mimeType).then((textureInfo) => {
238
122
  if (textureInfo) {
239
123
  material.normalTexture = textureInfo;
240
124
  if (bumpTexture.level !== 1) {
@@ -243,16 +127,18 @@ export class _GLTFMaterialExporter {
243
127
  }
244
128
  }));
245
129
  }
246
- if (babylonStandardMaterial.emissiveTexture) {
130
+ const emissiveTexture = babylonStandardMaterial.emissiveTexture;
131
+ if (emissiveTexture) {
247
132
  material.emissiveFactor = [1.0, 1.0, 1.0];
248
- promises.push(this._exportTextureAsync(babylonStandardMaterial.emissiveTexture, mimeType).then((textureInfo) => {
133
+ promises.push(this.exportTextureAsync(emissiveTexture, mimeType).then((textureInfo) => {
249
134
  if (textureInfo) {
250
135
  material.emissiveTexture = textureInfo;
251
136
  }
252
137
  }));
253
138
  }
254
- if (babylonStandardMaterial.ambientTexture) {
255
- promises.push(this._exportTextureAsync(babylonStandardMaterial.ambientTexture, mimeType).then((textureInfo) => {
139
+ const ambientTexture = babylonStandardMaterial.ambientTexture;
140
+ if (ambientTexture) {
141
+ promises.push(this.exportTextureAsync(ambientTexture, mimeType).then((textureInfo) => {
256
142
  if (textureInfo) {
257
143
  const occlusionTexture = {
258
144
  index: textureInfo.index,
@@ -261,6 +147,10 @@ export class _GLTFMaterialExporter {
261
147
  }
262
148
  }));
263
149
  }
150
+ if (promises.length > 0) {
151
+ this._exporter._materialNeedsUVsSet.add(babylonStandardMaterial);
152
+ await Promise.all(promises);
153
+ }
264
154
  }
265
155
  if (babylonStandardMaterial.alpha < 1.0 || babylonStandardMaterial.opacityTexture) {
266
156
  if (babylonStandardMaterial.alphaMode === Constants.ALPHA_COMBINE) {
@@ -270,45 +160,68 @@ export class _GLTFMaterialExporter {
270
160
  Tools.Warn(babylonStandardMaterial.name + ": glTF 2.0 does not support alpha mode: " + babylonStandardMaterial.alphaMode.toString());
271
161
  }
272
162
  }
273
- if (babylonStandardMaterial.emissiveColor && !_GLTFMaterialExporter._FuzzyEquals(babylonStandardMaterial.emissiveColor, Color3.Black(), _GLTFMaterialExporter._Epsilon)) {
163
+ if (babylonStandardMaterial.emissiveColor && !babylonStandardMaterial.emissiveColor.equalsWithEpsilon(black, epsilon)) {
274
164
  material.emissiveFactor = babylonStandardMaterial.emissiveColor.asArray();
275
165
  }
276
166
  material.pbrMetallicRoughness = pbrMetallicRoughness;
277
- _GLTFMaterialExporter._SetAlphaMode(material, babylonStandardMaterial);
167
+ SetAlphaMode(material, babylonStandardMaterial);
168
+ await this._finishMaterialAsync(material, babylonStandardMaterial, mimeType);
169
+ const materials = this._exporter._materials;
278
170
  materials.push(material);
279
- materialMap[babylonStandardMaterial.uniqueId] = materials.length - 1;
280
- return this._finishMaterial(promises, material, babylonStandardMaterial, mimeType);
171
+ return materials.length - 1;
281
172
  }
282
- _finishMaterial(promises, glTFMaterial, babylonMaterial, mimeType) {
283
- return Promise.all(promises).then(() => {
284
- const textures = this._exporter._extensionsPostExportMaterialAdditionalTextures("exportMaterial", glTFMaterial, babylonMaterial);
285
- let tasks = null;
286
- for (const texture of textures) {
287
- if (!tasks) {
288
- tasks = [];
289
- }
290
- tasks.push(this._exportTextureAsync(texture, mimeType));
291
- }
292
- if (!tasks) {
293
- tasks = [Promise.resolve(null)];
294
- }
295
- return Promise.all(tasks).then(() => {
296
- const extensionWork = this._exporter._extensionsPostExportMaterialAsync("exportMaterial", glTFMaterial, babylonMaterial);
297
- if (!extensionWork) {
298
- return glTFMaterial;
299
- }
300
- return extensionWork.then(() => glTFMaterial);
301
- });
302
- });
173
+ _convertToGLTFPBRMetallicRoughness(babylonStandardMaterial) {
174
+ // Defines a cubic bezier curve where x is specular power and y is roughness
175
+ const P0 = new Vector2(0, 1);
176
+ const P1 = new Vector2(0, 0.1);
177
+ const P2 = new Vector2(0, 0.1);
178
+ const P3 = new Vector2(1300, 0.1);
179
+ /**
180
+ * Given the control points, solve for x based on a given t for a cubic bezier curve
181
+ * @param t a value between 0 and 1
182
+ * @param p0 first control point
183
+ * @param p1 second control point
184
+ * @param p2 third control point
185
+ * @param p3 fourth control point
186
+ * @returns number result of cubic bezier curve at the specified t
187
+ */
188
+ function cubicBezierCurve(t, p0, p1, p2, p3) {
189
+ return (1 - t) * (1 - t) * (1 - t) * p0 + 3 * (1 - t) * (1 - t) * t * p1 + 3 * (1 - t) * t * t * p2 + t * t * t * p3;
190
+ }
191
+ /**
192
+ * Evaluates a specified specular power value to determine the appropriate roughness value,
193
+ * based on a pre-defined cubic bezier curve with specular on the abscissa axis (x-axis)
194
+ * and roughness on the ordinant axis (y-axis)
195
+ * @param specularPower specular power of standard material
196
+ * @returns Number representing the roughness value
197
+ */
198
+ function solveForRoughness(specularPower) {
199
+ // Given P0.x = 0, P1.x = 0, P2.x = 0
200
+ // x = t * t * t * P3.x
201
+ // t = (x / P3.x)^(1/3)
202
+ const t = Math.pow(specularPower / P3.x, 0.333333);
203
+ return cubicBezierCurve(t, P0.y, P1.y, P2.y, P3.y);
204
+ }
205
+ const diffuse = babylonStandardMaterial.diffuseColor.toLinearSpace(babylonStandardMaterial.getScene().getEngine().useExactSrgbConversions).scale(0.5);
206
+ const opacity = babylonStandardMaterial.alpha;
207
+ const specularPower = Scalar.Clamp(babylonStandardMaterial.specularPower, 0, maxSpecularPower);
208
+ const roughness = solveForRoughness(specularPower);
209
+ const glTFPbrMetallicRoughness = {
210
+ baseColorFactor: [diffuse.r, diffuse.g, diffuse.b, opacity],
211
+ metallicFactor: 0,
212
+ roughnessFactor: roughness,
213
+ };
214
+ return glTFPbrMetallicRoughness;
215
+ }
216
+ async _finishMaterialAsync(glTFMaterial, babylonMaterial, mimeType) {
217
+ const textures = this._exporter._extensionsPostExportMaterialAdditionalTextures("exportMaterial", glTFMaterial, babylonMaterial);
218
+ const promises = [];
219
+ for (const texture of textures) {
220
+ promises.push(this.exportTextureAsync(texture, mimeType));
221
+ }
222
+ await Promise.all(promises);
223
+ await this._exporter._extensionsPostExportMaterialAsync("exportMaterial", glTFMaterial, babylonMaterial);
303
224
  }
304
- /**
305
- * Converts an image typed array buffer to a base64 image
306
- * @param buffer typed array buffer
307
- * @param width width of the image
308
- * @param height height of the image
309
- * @param mimeType mimetype of the image
310
- * @returns base64 image string
311
- */
312
225
  async _getImageDataAsync(buffer, width, height, mimeType) {
313
226
  const textureType = Constants.TEXTURETYPE_UNSIGNED_BYTE;
314
227
  const hostingScene = this._exporter._babylonScene;
@@ -319,21 +232,6 @@ export class _GLTFMaterialExporter {
319
232
  const data = await engine._readTexturePixels(tempTexture, width, height);
320
233
  return (await DumpTools.DumpDataAsync(width, height, data, mimeType, undefined, true, true));
321
234
  }
322
- /**
323
- * Generates a white texture based on the specified width and height
324
- * @param width width of the texture in pixels
325
- * @param height height of the texture in pixels
326
- * @param scene babylonjs scene
327
- * @returns white texture
328
- */
329
- _createWhiteTexture(width, height, scene) {
330
- const data = new Uint8Array(width * height * 4);
331
- for (let i = 0; i < data.length; i = i + 4) {
332
- data[i] = data[i + 1] = data[i + 2] = data[i + 3] = 0xff;
333
- }
334
- const rawTexture = RawTexture.CreateRGBATexture(data, width, height, scene);
335
- return rawTexture;
336
- }
337
235
  /**
338
236
  * 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
339
237
  * @param texture1 first texture to resize
@@ -351,7 +249,7 @@ export class _GLTFMaterialExporter {
351
249
  resizedTexture1 = TextureTools.CreateResizedCopy(texture1, texture2Size.width, texture2Size.height, true);
352
250
  }
353
251
  else {
354
- resizedTexture1 = this._createWhiteTexture(texture2Size.width, texture2Size.height, scene);
252
+ resizedTexture1 = CreateWhiteTexture(texture2Size.width, texture2Size.height, scene);
355
253
  }
356
254
  resizedTexture2 = texture2;
357
255
  }
@@ -360,7 +258,7 @@ export class _GLTFMaterialExporter {
360
258
  resizedTexture2 = TextureTools.CreateResizedCopy(texture2, texture1Size.width, texture1Size.height, true);
361
259
  }
362
260
  else {
363
- resizedTexture2 = this._createWhiteTexture(texture1Size.width, texture1Size.height, scene);
261
+ resizedTexture2 = CreateWhiteTexture(texture1Size.width, texture1Size.height, scene);
364
262
  }
365
263
  resizedTexture1 = texture1;
366
264
  }
@@ -373,32 +271,10 @@ export class _GLTFMaterialExporter {
373
271
  texture2: resizedTexture2,
374
272
  };
375
273
  }
376
- /**
377
- * Converts an array of pixels to a Float32Array
378
- * Throws an error if the pixel format is not supported
379
- * @param pixels - array buffer containing pixel values
380
- * @returns Float32 of pixels
381
- */
382
- _convertPixelArrayToFloat32(pixels) {
383
- if (pixels instanceof Uint8Array) {
384
- const length = pixels.length;
385
- const buffer = new Float32Array(pixels.length);
386
- for (let i = 0; i < length; ++i) {
387
- buffer[i] = pixels[i] / 255;
388
- }
389
- return buffer;
390
- }
391
- else if (pixels instanceof Float32Array) {
392
- return pixels;
393
- }
394
- else {
395
- throw new Error("Unsupported pixel format!");
396
- }
397
- }
398
274
  /**
399
275
  * Convert Specular Glossiness Textures to Metallic Roughness
400
276
  * See link below for info on the material conversions from PBR Metallic/Roughness and Specular/Glossiness
401
- * @link https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-.js/babylon.pbrUtilities.js
277
+ * @see https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows-.js/babylon.pbrUtilities.js
402
278
  * @param diffuseTexture texture used to store diffuse information
403
279
  * @param specularGlossinessTexture texture used to store specular and glossiness information
404
280
  * @param factors specular glossiness material factors
@@ -408,7 +284,7 @@ export class _GLTFMaterialExporter {
408
284
  async _convertSpecularGlossinessTexturesToMetallicRoughnessAsync(diffuseTexture, specularGlossinessTexture, factors, mimeType) {
409
285
  const promises = new Array();
410
286
  if (!(diffuseTexture || specularGlossinessTexture)) {
411
- return Promise.reject("_ConvertSpecularGlosinessTexturesToMetallicRoughness: diffuse and specular glossiness textures are not defined!");
287
+ return Promise.reject("diffuse and specular glossiness textures are not defined!");
412
288
  }
413
289
  const scene = diffuseTexture ? diffuseTexture.getScene() : specularGlossinessTexture ? specularGlossinessTexture.getScene() : null;
414
290
  if (scene) {
@@ -421,13 +297,13 @@ export class _GLTFMaterialExporter {
421
297
  const diffusePixels = await resizedTextures.texture1.readPixels();
422
298
  const specularPixels = await resizedTextures.texture2.readPixels();
423
299
  if (diffusePixels) {
424
- diffuseBuffer = this._convertPixelArrayToFloat32(diffusePixels);
300
+ diffuseBuffer = ConvertPixelArrayToFloat32(diffusePixels);
425
301
  }
426
302
  else {
427
303
  return Promise.reject("Failed to retrieve pixels from diffuse texture!");
428
304
  }
429
305
  if (specularPixels) {
430
- specularGlossinessBuffer = this._convertPixelArrayToFloat32(specularPixels);
306
+ specularGlossinessBuffer = ConvertPixelArrayToFloat32(specularPixels);
431
307
  }
432
308
  else {
433
309
  return Promise.reject("Failed to retrieve pixels from specular glossiness texture!");
@@ -436,7 +312,7 @@ export class _GLTFMaterialExporter {
436
312
  const metallicRoughnessBuffer = new Uint8Array(byteLength);
437
313
  const baseColorBuffer = new Uint8Array(byteLength);
438
314
  const strideSize = 4;
439
- const maxBaseColor = Color3.Black();
315
+ const maxBaseColor = black;
440
316
  let maxMetallic = 0;
441
317
  let maxRoughness = 0;
442
318
  for (let h = 0; h < height; ++h) {
@@ -481,22 +357,21 @@ export class _GLTFMaterialExporter {
481
357
  for (let h = 0; h < height; ++h) {
482
358
  for (let w = 0; w < width; ++w) {
483
359
  const destinationOffset = (width * h + w) * strideSize;
484
- baseColorBuffer[destinationOffset] /= metallicRoughnessFactors.baseColor.r > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.baseColor.r : 1;
485
- baseColorBuffer[destinationOffset + 1] /= metallicRoughnessFactors.baseColor.g > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.baseColor.g : 1;
486
- baseColorBuffer[destinationOffset + 2] /= metallicRoughnessFactors.baseColor.b > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.baseColor.b : 1;
360
+ baseColorBuffer[destinationOffset] /= metallicRoughnessFactors.baseColor.r > epsilon ? metallicRoughnessFactors.baseColor.r : 1;
361
+ baseColorBuffer[destinationOffset + 1] /= metallicRoughnessFactors.baseColor.g > epsilon ? metallicRoughnessFactors.baseColor.g : 1;
362
+ baseColorBuffer[destinationOffset + 2] /= metallicRoughnessFactors.baseColor.b > epsilon ? metallicRoughnessFactors.baseColor.b : 1;
487
363
  const linearBaseColorPixel = Color3.FromInts(baseColorBuffer[destinationOffset], baseColorBuffer[destinationOffset + 1], baseColorBuffer[destinationOffset + 2]);
488
364
  const sRGBBaseColorPixel = linearBaseColorPixel.toGammaSpace(scene.getEngine().useExactSrgbConversions);
489
365
  baseColorBuffer[destinationOffset] = sRGBBaseColorPixel.r * 255;
490
366
  baseColorBuffer[destinationOffset + 1] = sRGBBaseColorPixel.g * 255;
491
367
  baseColorBuffer[destinationOffset + 2] = sRGBBaseColorPixel.b * 255;
492
- if (!_GLTFMaterialExporter._FuzzyEquals(sRGBBaseColorPixel, Color3.White(), _GLTFMaterialExporter._Epsilon)) {
368
+ if (!sRGBBaseColorPixel.equalsWithEpsilon(white, epsilon)) {
493
369
  writeOutBaseColorTexture = true;
494
370
  }
495
- metallicRoughnessBuffer[destinationOffset + 1] /=
496
- metallicRoughnessFactors.roughness > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.roughness : 1;
497
- metallicRoughnessBuffer[destinationOffset + 2] /= metallicRoughnessFactors.metallic > _GLTFMaterialExporter._Epsilon ? metallicRoughnessFactors.metallic : 1;
371
+ metallicRoughnessBuffer[destinationOffset + 1] /= metallicRoughnessFactors.roughness > epsilon ? metallicRoughnessFactors.roughness : 1;
372
+ metallicRoughnessBuffer[destinationOffset + 2] /= metallicRoughnessFactors.metallic > epsilon ? metallicRoughnessFactors.metallic : 1;
498
373
  const metallicRoughnessPixel = Color3.FromInts(255, metallicRoughnessBuffer[destinationOffset + 1], metallicRoughnessBuffer[destinationOffset + 2]);
499
- if (!_GLTFMaterialExporter._FuzzyEquals(metallicRoughnessPixel, Color3.White(), _GLTFMaterialExporter._Epsilon)) {
374
+ if (!metallicRoughnessPixel.equalsWithEpsilon(white, epsilon)) {
500
375
  writeOutMetallicRoughnessTexture = true;
501
376
  }
502
377
  }
@@ -528,11 +403,9 @@ export class _GLTFMaterialExporter {
528
403
  const diffusePerceivedBrightness = this._getPerceivedBrightness(specularGlossiness.diffuseColor);
529
404
  const specularPerceivedBrightness = this._getPerceivedBrightness(specularGlossiness.specularColor);
530
405
  const oneMinusSpecularStrength = 1 - this._getMaxComponent(specularGlossiness.specularColor);
531
- const metallic = _GLTFMaterialExporter._SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength);
532
- const baseColorFromDiffuse = specularGlossiness.diffuseColor.scale(oneMinusSpecularStrength / (1.0 - _GLTFMaterialExporter._DielectricSpecular.r) / Math.max(1 - metallic, _GLTFMaterialExporter._Epsilon));
533
- const baseColorFromSpecular = specularGlossiness.specularColor
534
- .subtract(_GLTFMaterialExporter._DielectricSpecular.scale(1 - metallic))
535
- .scale(1 / Math.max(metallic, _GLTFMaterialExporter._Epsilon));
406
+ const metallic = _SolveMetallic(diffusePerceivedBrightness, specularPerceivedBrightness, oneMinusSpecularStrength);
407
+ const baseColorFromDiffuse = specularGlossiness.diffuseColor.scale(oneMinusSpecularStrength / (1.0 - dielectricSpecular.r) / Math.max(1 - metallic));
408
+ const baseColorFromSpecular = specularGlossiness.specularColor.subtract(dielectricSpecular.scale(1 - metallic)).scale(1 / Math.max(metallic));
536
409
  let baseColor = Color3.Lerp(baseColorFromDiffuse, baseColorFromSpecular, metallic * metallic);
537
410
  baseColor = baseColor.clampToRef(0, 1, baseColor);
538
411
  const metallicRoughness = {
@@ -569,23 +442,20 @@ export class _GLTFMaterialExporter {
569
442
  * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
570
443
  * @param mimeType mime type to use for the textures
571
444
  * @param glTFPbrMetallicRoughness glTF PBR Metallic Roughness interface
572
- * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
445
+ * @param hasUVs specifies if texture coordinates are present on the submesh to determine if textures should be applied
573
446
  * @returns glTF PBR Metallic Roughness factors
574
447
  */
575
- _convertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasTextureCoords) {
448
+ async _convertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasUVs) {
576
449
  const promises = [];
577
- const baseColor = babylonPBRMaterial._albedoColor;
578
- const metallic = babylonPBRMaterial._metallic;
579
- const roughness = babylonPBRMaterial._roughness;
580
450
  const metallicRoughness = {
581
- baseColor: baseColor,
582
- metallic: metallic,
583
- roughness: roughness,
451
+ baseColor: babylonPBRMaterial._albedoColor,
452
+ metallic: babylonPBRMaterial._metallic,
453
+ roughness: babylonPBRMaterial._roughness,
584
454
  };
585
- if (hasTextureCoords) {
455
+ if (hasUVs) {
586
456
  const albedoTexture = babylonPBRMaterial._albedoTexture;
587
457
  if (albedoTexture) {
588
- promises.push(this._exportTextureAsync(babylonPBRMaterial._albedoTexture, mimeType).then((glTFTexture) => {
458
+ promises.push(this.exportTextureAsync(babylonPBRMaterial._albedoTexture, mimeType).then((glTFTexture) => {
589
459
  if (glTFTexture) {
590
460
  glTFPbrMetallicRoughness.baseColorTexture = glTFTexture;
591
461
  }
@@ -593,16 +463,18 @@ export class _GLTFMaterialExporter {
593
463
  }
594
464
  const metallicTexture = babylonPBRMaterial._metallicTexture;
595
465
  if (metallicTexture) {
596
- promises.push(this._exportTextureAsync(metallicTexture, mimeType).then((glTFTexture) => {
466
+ promises.push(this.exportTextureAsync(metallicTexture, mimeType).then((glTFTexture) => {
597
467
  if (glTFTexture) {
598
468
  glTFPbrMetallicRoughness.metallicRoughnessTexture = glTFTexture;
599
469
  }
600
470
  }));
601
471
  }
602
472
  }
603
- return Promise.all(promises).then(() => {
604
- return metallicRoughness;
605
- });
473
+ if (promises.length > 0) {
474
+ this._exporter._materialNeedsUVsSet.add(babylonPBRMaterial);
475
+ await Promise.all(promises);
476
+ }
477
+ return metallicRoughness;
606
478
  }
607
479
  _getTextureSampler(texture) {
608
480
  const sampler = {};
@@ -703,50 +575,41 @@ export class _GLTFMaterialExporter {
703
575
  * @param babylonPBRMaterial BJS PBR Metallic Roughness Material
704
576
  * @param mimeType mime type to use for the textures
705
577
  * @param pbrMetallicRoughness glTF PBR Metallic Roughness interface
706
- * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
578
+ * @param hasUVs specifies if texture coordinates are present on the submesh to determine if textures should be applied
707
579
  * @returns glTF PBR Metallic Roughness factors
708
580
  */
709
- _convertSpecGlossFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, pbrMetallicRoughness, hasTextureCoords) {
710
- return Promise.resolve().then(() => {
711
- const specGloss = {
712
- diffuseColor: babylonPBRMaterial._albedoColor,
713
- specularColor: babylonPBRMaterial._reflectivityColor,
714
- glossiness: babylonPBRMaterial._microSurface,
715
- };
716
- const albedoTexture = babylonPBRMaterial._albedoTexture;
717
- const reflectivityTexture = babylonPBRMaterial._reflectivityTexture;
718
- const useMicrosurfaceFromReflectivityMapAlpha = babylonPBRMaterial._useMicroSurfaceFromReflectivityMapAlpha;
719
- if (reflectivityTexture && !useMicrosurfaceFromReflectivityMapAlpha) {
720
- return Promise.reject("_ConvertPBRMaterial: Glossiness values not included in the reflectivity texture are currently not supported");
721
- }
722
- if ((albedoTexture || reflectivityTexture) && hasTextureCoords) {
723
- const samplerIndex = this._exportTextureSampler(albedoTexture || reflectivityTexture);
724
- return this._convertSpecularGlossinessTexturesToMetallicRoughnessAsync(albedoTexture, reflectivityTexture, specGloss, mimeType).then((metallicRoughnessFactors) => {
725
- const textures = this._exporter._textures;
726
- if (metallicRoughnessFactors.baseColorTextureData) {
727
- const imageIndex = this._exportImage(`baseColor${textures.length}`, mimeType, metallicRoughnessFactors.baseColorTextureData);
728
- pbrMetallicRoughness.baseColorTexture = this._exportTextureInfo(imageIndex, samplerIndex, albedoTexture?.coordinatesIndex);
729
- }
730
- if (metallicRoughnessFactors.metallicRoughnessTextureData) {
731
- const imageIndex = this._exportImage(`metallicRoughness${textures.length}`, mimeType, metallicRoughnessFactors.metallicRoughnessTextureData);
732
- pbrMetallicRoughness.metallicRoughnessTexture = this._exportTextureInfo(imageIndex, samplerIndex, reflectivityTexture?.coordinatesIndex);
733
- }
734
- return metallicRoughnessFactors;
735
- });
736
- }
737
- else {
738
- return this._convertSpecularGlossinessToMetallicRoughness(specGloss);
739
- }
740
- });
581
+ async _convertSpecGlossFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, pbrMetallicRoughness, hasUVs) {
582
+ const specGloss = {
583
+ diffuseColor: babylonPBRMaterial._albedoColor,
584
+ specularColor: babylonPBRMaterial._reflectivityColor,
585
+ glossiness: babylonPBRMaterial._microSurface,
586
+ };
587
+ const albedoTexture = babylonPBRMaterial._albedoTexture;
588
+ const reflectivityTexture = babylonPBRMaterial._reflectivityTexture;
589
+ const useMicrosurfaceFromReflectivityMapAlpha = babylonPBRMaterial._useMicroSurfaceFromReflectivityMapAlpha;
590
+ if (reflectivityTexture && !useMicrosurfaceFromReflectivityMapAlpha) {
591
+ return Promise.reject("_ConvertPBRMaterial: Glossiness values not included in the reflectivity texture are currently not supported");
592
+ }
593
+ if ((albedoTexture || reflectivityTexture) && hasUVs) {
594
+ this._exporter._materialNeedsUVsSet.add(babylonPBRMaterial);
595
+ const samplerIndex = this._exportTextureSampler(albedoTexture || reflectivityTexture);
596
+ const metallicRoughnessFactors = await this._convertSpecularGlossinessTexturesToMetallicRoughnessAsync(albedoTexture, reflectivityTexture, specGloss, mimeType);
597
+ const textures = this._exporter._textures;
598
+ if (metallicRoughnessFactors.baseColorTextureData) {
599
+ const imageIndex = this._exportImage(`baseColor${textures.length}`, mimeType, metallicRoughnessFactors.baseColorTextureData);
600
+ pbrMetallicRoughness.baseColorTexture = this._exportTextureInfo(imageIndex, samplerIndex, albedoTexture?.coordinatesIndex);
601
+ }
602
+ if (metallicRoughnessFactors.metallicRoughnessTextureData) {
603
+ const imageIndex = this._exportImage(`metallicRoughness${textures.length}`, mimeType, metallicRoughnessFactors.metallicRoughnessTextureData);
604
+ pbrMetallicRoughness.metallicRoughnessTexture = this._exportTextureInfo(imageIndex, samplerIndex, reflectivityTexture?.coordinatesIndex);
605
+ }
606
+ return metallicRoughnessFactors;
607
+ }
608
+ else {
609
+ return this._convertSpecularGlossinessToMetallicRoughness(specGloss);
610
+ }
741
611
  }
742
- /**
743
- * Converts a Babylon PBR Base Material to a glTF Material
744
- * @param babylonPBRMaterial BJS PBR Base Material
745
- * @param mimeType mime type to use for the textures
746
- * @param hasTextureCoords specifies if texture coordinates are present on the submesh to determine if textures should be applied
747
- * @returns async glTF Material representation
748
- */
749
- _convertPBRMaterialAsync(babylonPBRMaterial, mimeType, hasTextureCoords) {
612
+ async exportPBRMaterialAsync(babylonPBRMaterial, mimeType, hasUVs) {
750
613
  const glTFPbrMetallicRoughness = {};
751
614
  const glTFMaterial = {
752
615
  name: babylonPBRMaterial.name,
@@ -758,88 +621,81 @@ export class _GLTFMaterialExporter {
758
621
  if (albedoColor) {
759
622
  glTFPbrMetallicRoughness.baseColorFactor = [albedoColor.r, albedoColor.g, albedoColor.b, alpha];
760
623
  }
761
- return this._convertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasTextureCoords).then((metallicRoughness) => {
762
- return this._setMetallicRoughnessPbrMaterial(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, hasTextureCoords);
763
- });
764
- }
765
- else {
766
- return this._convertSpecGlossFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasTextureCoords).then((metallicRoughness) => {
767
- return this._setMetallicRoughnessPbrMaterial(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, hasTextureCoords);
768
- });
769
624
  }
770
- }
771
- _setMetallicRoughnessPbrMaterial(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, hasTextureCoords) {
772
- const materialMap = this._exporter._materialMap;
625
+ const metallicRoughness = useMetallicRoughness
626
+ ? await this._convertMetalRoughFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasUVs)
627
+ : await this._convertSpecGlossFactorsToMetallicRoughnessAsync(babylonPBRMaterial, mimeType, glTFPbrMetallicRoughness, hasUVs);
628
+ await this._setMetallicRoughnessPbrMaterialAsync(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, hasUVs);
629
+ await this._finishMaterialAsync(glTFMaterial, babylonPBRMaterial, mimeType);
773
630
  const materials = this._exporter._materials;
774
- const promises = [];
775
- if (metallicRoughness) {
776
- _GLTFMaterialExporter._SetAlphaMode(glTFMaterial, babylonPBRMaterial);
777
- if (!(_GLTFMaterialExporter._FuzzyEquals(metallicRoughness.baseColor, Color3.White(), _GLTFMaterialExporter._Epsilon) &&
778
- babylonPBRMaterial.alpha >= _GLTFMaterialExporter._Epsilon)) {
779
- glTFPbrMetallicRoughness.baseColorFactor = [metallicRoughness.baseColor.r, metallicRoughness.baseColor.g, metallicRoughness.baseColor.b, babylonPBRMaterial.alpha];
780
- }
781
- if (metallicRoughness.metallic != null && metallicRoughness.metallic !== 1) {
782
- glTFPbrMetallicRoughness.metallicFactor = metallicRoughness.metallic;
783
- }
784
- if (metallicRoughness.roughness != null && metallicRoughness.roughness !== 1) {
785
- glTFPbrMetallicRoughness.roughnessFactor = metallicRoughness.roughness;
631
+ materials.push(glTFMaterial);
632
+ return materials.length - 1;
633
+ }
634
+ async _setMetallicRoughnessPbrMaterialAsync(metallicRoughness, babylonPBRMaterial, glTFMaterial, glTFPbrMetallicRoughness, mimeType, hasUVs) {
635
+ SetAlphaMode(glTFMaterial, babylonPBRMaterial);
636
+ if (!metallicRoughness.baseColor.equalsWithEpsilon(white, epsilon) || !Scalar.WithinEpsilon(babylonPBRMaterial.alpha, 1, epsilon)) {
637
+ glTFPbrMetallicRoughness.baseColorFactor = [metallicRoughness.baseColor.r, metallicRoughness.baseColor.g, metallicRoughness.baseColor.b, babylonPBRMaterial.alpha];
638
+ }
639
+ if (metallicRoughness.metallic != null && metallicRoughness.metallic !== 1) {
640
+ glTFPbrMetallicRoughness.metallicFactor = metallicRoughness.metallic;
641
+ }
642
+ if (metallicRoughness.roughness != null && metallicRoughness.roughness !== 1) {
643
+ glTFPbrMetallicRoughness.roughnessFactor = metallicRoughness.roughness;
644
+ }
645
+ if (babylonPBRMaterial.backFaceCulling != null && !babylonPBRMaterial.backFaceCulling) {
646
+ if (!babylonPBRMaterial._twoSidedLighting) {
647
+ Tools.Warn(babylonPBRMaterial.name + ": Back-face culling disabled and two-sided lighting disabled is not supported in glTF.");
786
648
  }
787
- if (babylonPBRMaterial.backFaceCulling != null && !babylonPBRMaterial.backFaceCulling) {
788
- if (!babylonPBRMaterial._twoSidedLighting) {
789
- Tools.Warn(babylonPBRMaterial.name + ": Back-face culling disabled and two-sided lighting disabled is not supported in glTF.");
790
- }
791
- glTFMaterial.doubleSided = true;
792
- }
793
- if (hasTextureCoords) {
794
- const bumpTexture = babylonPBRMaterial._bumpTexture;
795
- if (bumpTexture) {
796
- const promise = this._exportTextureAsync(bumpTexture, mimeType).then((glTFTexture) => {
797
- if (glTFTexture) {
798
- glTFMaterial.normalTexture = glTFTexture;
799
- if (bumpTexture.level !== 1) {
800
- glTFMaterial.normalTexture.scale = bumpTexture.level;
801
- }
802
- }
803
- });
804
- promises.push(promise);
805
- }
806
- const ambientTexture = babylonPBRMaterial._ambientTexture;
807
- if (ambientTexture) {
808
- const promise = this._exportTextureAsync(ambientTexture, mimeType).then((glTFTexture) => {
809
- if (glTFTexture) {
810
- const occlusionTexture = {
811
- index: glTFTexture.index,
812
- texCoord: glTFTexture.texCoord,
813
- extensions: glTFTexture.extensions,
814
- };
815
- glTFMaterial.occlusionTexture = occlusionTexture;
816
- const ambientTextureStrength = babylonPBRMaterial._ambientTextureStrength;
817
- if (ambientTextureStrength) {
818
- occlusionTexture.strength = ambientTextureStrength;
819
- }
649
+ glTFMaterial.doubleSided = true;
650
+ }
651
+ if (hasUVs) {
652
+ const promises = [];
653
+ const bumpTexture = babylonPBRMaterial._bumpTexture;
654
+ if (bumpTexture) {
655
+ promises.push(this.exportTextureAsync(bumpTexture, mimeType).then((glTFTexture) => {
656
+ if (glTFTexture) {
657
+ glTFMaterial.normalTexture = glTFTexture;
658
+ if (bumpTexture.level !== 1) {
659
+ glTFMaterial.normalTexture.scale = bumpTexture.level;
820
660
  }
821
- });
822
- promises.push(promise);
823
- }
824
- const emissiveTexture = babylonPBRMaterial._emissiveTexture;
825
- if (emissiveTexture) {
826
- const promise = this._exportTextureAsync(emissiveTexture, mimeType).then((glTFTexture) => {
827
- if (glTFTexture) {
828
- glTFMaterial.emissiveTexture = glTFTexture;
661
+ }
662
+ }));
663
+ }
664
+ const ambientTexture = babylonPBRMaterial._ambientTexture;
665
+ if (ambientTexture) {
666
+ promises.push(this.exportTextureAsync(ambientTexture, mimeType).then((glTFTexture) => {
667
+ if (glTFTexture) {
668
+ const occlusionTexture = {
669
+ index: glTFTexture.index,
670
+ texCoord: glTFTexture.texCoord,
671
+ extensions: glTFTexture.extensions,
672
+ };
673
+ glTFMaterial.occlusionTexture = occlusionTexture;
674
+ const ambientTextureStrength = babylonPBRMaterial._ambientTextureStrength;
675
+ if (ambientTextureStrength) {
676
+ occlusionTexture.strength = ambientTextureStrength;
829
677
  }
830
- });
831
- promises.push(promise);
832
- }
678
+ }
679
+ }));
833
680
  }
834
- const emissiveColor = babylonPBRMaterial._emissiveColor;
835
- if (!_GLTFMaterialExporter._FuzzyEquals(emissiveColor, Color3.Black(), _GLTFMaterialExporter._Epsilon)) {
836
- glTFMaterial.emissiveFactor = emissiveColor.asArray();
681
+ const emissiveTexture = babylonPBRMaterial._emissiveTexture;
682
+ if (emissiveTexture) {
683
+ promises.push(this.exportTextureAsync(emissiveTexture, mimeType).then((glTFTexture) => {
684
+ if (glTFTexture) {
685
+ glTFMaterial.emissiveTexture = glTFTexture;
686
+ }
687
+ }));
837
688
  }
838
- glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
839
- materials.push(glTFMaterial);
840
- materialMap[babylonPBRMaterial.uniqueId] = materials.length - 1;
689
+ if (promises.length > 0) {
690
+ this._exporter._materialNeedsUVsSet.add(babylonPBRMaterial);
691
+ await Promise.all(promises);
692
+ }
693
+ }
694
+ const emissiveColor = babylonPBRMaterial._emissiveColor;
695
+ if (!emissiveColor.equalsWithEpsilon(black, epsilon)) {
696
+ glTFMaterial.emissiveFactor = emissiveColor.asArray();
841
697
  }
842
- return this._finishMaterial(promises, glTFMaterial, babylonPBRMaterial, mimeType);
698
+ glTFMaterial.pbrMetallicRoughness = glTFPbrMetallicRoughness;
843
699
  }
844
700
  _getPixelsFromTexture(babylonTexture) {
845
701
  const pixels = babylonTexture.textureType === Constants.TEXTURETYPE_UNSIGNED_BYTE
@@ -847,13 +703,7 @@ export class _GLTFMaterialExporter {
847
703
  : babylonTexture.readPixels();
848
704
  return pixels;
849
705
  }
850
- /**
851
- * Extracts a texture from a Babylon texture into file data and glTF data
852
- * @param babylonTexture Babylon texture to extract
853
- * @param mimeType Mime Type of the babylonTexture
854
- * @returns glTF texture info, or null if the texture format is not supported
855
- */
856
- _exportTextureAsync(babylonTexture, mimeType) {
706
+ async exportTextureAsync(babylonTexture, mimeType) {
857
707
  const extensionPromise = this._exporter._extensionsPreExportTextureAsync("exporter", babylonTexture, mimeType);
858
708
  if (!extensionPromise) {
859
709
  return this._exportTextureInfoAsync(babylonTexture, mimeType);
@@ -866,8 +716,8 @@ export class _GLTFMaterialExporter {
866
716
  });
867
717
  }
868
718
  async _exportTextureInfoAsync(babylonTexture, mimeType) {
869
- const textureUid = babylonTexture.uid;
870
- if (!(textureUid in this._textureMap)) {
719
+ let textureInfo = this._textureMap.get(babylonTexture);
720
+ if (!textureInfo) {
871
721
  const pixels = await this._getPixelsFromTexture(babylonTexture);
872
722
  if (!pixels) {
873
723
  return null;
@@ -899,16 +749,16 @@ export class _GLTFMaterialExporter {
899
749
  })();
900
750
  internalTextureToImage[internalTextureUniqueId][mimeType] = imageIndexPromise;
901
751
  }
902
- const textureInfo = this._exportTextureInfo(await imageIndexPromise, samplerIndex, babylonTexture.coordinatesIndex);
903
- this._textureMap[textureUid] = textureInfo;
904
- this._exporter._extensionsPostExportTextures("exporter", this._textureMap[textureUid], babylonTexture);
752
+ textureInfo = this._exportTextureInfo(await imageIndexPromise, samplerIndex, babylonTexture.coordinatesIndex);
753
+ this._textureMap.set(babylonTexture, textureInfo);
754
+ this._exporter._extensionsPostExportTextures("exporter", textureInfo, babylonTexture);
905
755
  }
906
- return this._textureMap[textureUid];
756
+ return textureInfo;
907
757
  }
908
758
  _exportImage(name, mimeType, data) {
909
759
  const imageData = this._exporter._imageData;
910
760
  const baseName = name.replace(/\.\/|\/|\.\\|\\/g, "_");
911
- const extension = getFileExtensionFromMimeType(mimeType);
761
+ const extension = GetFileExtensionFromMimeType(mimeType);
912
762
  let fileName = baseName + extension;
913
763
  if (fileName in imageData) {
914
764
  fileName = `${baseName}_${Tools.RandomId()}${extension}`;
@@ -952,16 +802,4 @@ export class _GLTFMaterialExporter {
952
802
  return samplers.length - 1;
953
803
  }
954
804
  }
955
- /**
956
- * Represents the dielectric specular values for R, G and B
957
- */
958
- _GLTFMaterialExporter._DielectricSpecular = new Color3(0.04, 0.04, 0.04);
959
- /**
960
- * Allows the maximum specular power to be defined for material calculations
961
- */
962
- _GLTFMaterialExporter._MaxSpecularPower = 1024;
963
- /**
964
- * Numeric tolerance value
965
- */
966
- _GLTFMaterialExporter._Epsilon = 1e-6;
967
805
  //# sourceMappingURL=glTFMaterialExporter.js.map