@onerjs/serializers 8.23.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.
Files changed (135) hide show
  1. package/OBJ/index.d.ts +1 -0
  2. package/OBJ/index.js +2 -0
  3. package/OBJ/index.js.map +1 -0
  4. package/OBJ/objSerializer.d.ts +21 -0
  5. package/OBJ/objSerializer.js +171 -0
  6. package/OBJ/objSerializer.js.map +1 -0
  7. package/USDZ/index.d.ts +1 -0
  8. package/USDZ/index.js +3 -0
  9. package/USDZ/index.js.map +1 -0
  10. package/USDZ/usdzExporter.d.ts +50 -0
  11. package/USDZ/usdzExporter.js +589 -0
  12. package/USDZ/usdzExporter.js.map +1 -0
  13. package/exportUtils.d.ts +12 -0
  14. package/exportUtils.js +37 -0
  15. package/exportUtils.js.map +1 -0
  16. package/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.d.ts +24 -0
  17. package/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.js +61 -0
  18. package/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.js.map +1 -0
  19. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.d.ts +36 -0
  20. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js +109 -0
  21. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js.map +1 -0
  22. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.d.ts +32 -0
  23. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js +135 -0
  24. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js.map +1 -0
  25. package/glTF/2.0/Extensions/KHR_lights_punctual.d.ts +39 -0
  26. package/glTF/2.0/Extensions/KHR_lights_punctual.js +145 -0
  27. package/glTF/2.0/Extensions/KHR_lights_punctual.js.map +1 -0
  28. package/glTF/2.0/Extensions/KHR_materials_anisotropy.d.ts +24 -0
  29. package/glTF/2.0/Extensions/KHR_materials_anisotropy.js +62 -0
  30. package/glTF/2.0/Extensions/KHR_materials_anisotropy.js.map +1 -0
  31. package/glTF/2.0/Extensions/KHR_materials_clearcoat.d.ts +24 -0
  32. package/glTF/2.0/Extensions/KHR_materials_clearcoat.js +85 -0
  33. package/glTF/2.0/Extensions/KHR_materials_clearcoat.js.map +1 -0
  34. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.d.ts +40 -0
  35. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js +118 -0
  36. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js.map +1 -0
  37. package/glTF/2.0/Extensions/KHR_materials_dispersion.d.ts +31 -0
  38. package/glTF/2.0/Extensions/KHR_materials_dispersion.js +63 -0
  39. package/glTF/2.0/Extensions/KHR_materials_dispersion.js.map +1 -0
  40. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.d.ts +27 -0
  41. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js +54 -0
  42. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js.map +1 -0
  43. package/glTF/2.0/Extensions/KHR_materials_ior.d.ts +29 -0
  44. package/glTF/2.0/Extensions/KHR_materials_ior.js +55 -0
  45. package/glTF/2.0/Extensions/KHR_materials_ior.js.map +1 -0
  46. package/glTF/2.0/Extensions/KHR_materials_iridescence.d.ts +24 -0
  47. package/glTF/2.0/Extensions/KHR_materials_iridescence.js +69 -0
  48. package/glTF/2.0/Extensions/KHR_materials_iridescence.js.map +1 -0
  49. package/glTF/2.0/Extensions/KHR_materials_sheen.d.ts +24 -0
  50. package/glTF/2.0/Extensions/KHR_materials_sheen.js +66 -0
  51. package/glTF/2.0/Extensions/KHR_materials_sheen.js.map +1 -0
  52. package/glTF/2.0/Extensions/KHR_materials_specular.d.ts +41 -0
  53. package/glTF/2.0/Extensions/KHR_materials_specular.js +94 -0
  54. package/glTF/2.0/Extensions/KHR_materials_specular.js.map +1 -0
  55. package/glTF/2.0/Extensions/KHR_materials_transmission.d.ts +41 -0
  56. package/glTF/2.0/Extensions/KHR_materials_transmission.js +92 -0
  57. package/glTF/2.0/Extensions/KHR_materials_transmission.js.map +1 -0
  58. package/glTF/2.0/Extensions/KHR_materials_unlit.d.ts +20 -0
  59. package/glTF/2.0/Extensions/KHR_materials_unlit.js +46 -0
  60. package/glTF/2.0/Extensions/KHR_materials_unlit.js.map +1 -0
  61. package/glTF/2.0/Extensions/KHR_materials_volume.d.ts +40 -0
  62. package/glTF/2.0/Extensions/KHR_materials_volume.js +96 -0
  63. package/glTF/2.0/Extensions/KHR_materials_volume.js.map +1 -0
  64. package/glTF/2.0/Extensions/KHR_texture_transform.d.ts +21 -0
  65. package/glTF/2.0/Extensions/KHR_texture_transform.js +93 -0
  66. package/glTF/2.0/Extensions/KHR_texture_transform.js.map +1 -0
  67. package/glTF/2.0/Extensions/index.d.ts +17 -0
  68. package/glTF/2.0/Extensions/index.js +18 -0
  69. package/glTF/2.0/Extensions/index.js.map +1 -0
  70. package/glTF/2.0/bufferManager.d.ts +68 -0
  71. package/glTF/2.0/bufferManager.js +154 -0
  72. package/glTF/2.0/bufferManager.js.map +1 -0
  73. package/glTF/2.0/dataWriter.d.ts +20 -0
  74. package/glTF/2.0/dataWriter.js +83 -0
  75. package/glTF/2.0/dataWriter.js.map +1 -0
  76. package/glTF/2.0/glTFAnimation.d.ts +191 -0
  77. package/glTF/2.0/glTFAnimation.js +786 -0
  78. package/glTF/2.0/glTFAnimation.js.map +1 -0
  79. package/glTF/2.0/glTFData.d.ts +21 -0
  80. package/glTF/2.0/glTFData.js +30 -0
  81. package/glTF/2.0/glTFData.js.map +1 -0
  82. package/glTF/2.0/glTFExporter.d.ts +109 -0
  83. package/glTF/2.0/glTFExporter.js +1166 -0
  84. package/glTF/2.0/glTFExporter.js.map +1 -0
  85. package/glTF/2.0/glTFExporterExtension.d.ts +77 -0
  86. package/glTF/2.0/glTFExporterExtension.js +4 -0
  87. package/glTF/2.0/glTFExporterExtension.js.map +1 -0
  88. package/glTF/2.0/glTFMaterialExporter.d.ts +99 -0
  89. package/glTF/2.0/glTFMaterialExporter.js +778 -0
  90. package/glTF/2.0/glTFMaterialExporter.js.map +1 -0
  91. package/glTF/2.0/glTFMorphTargetsUtilities.d.ts +14 -0
  92. package/glTF/2.0/glTFMorphTargetsUtilities.js +149 -0
  93. package/glTF/2.0/glTFMorphTargetsUtilities.js.map +1 -0
  94. package/glTF/2.0/glTFSerializer.d.ts +78 -0
  95. package/glTF/2.0/glTFSerializer.js +39 -0
  96. package/glTF/2.0/glTFSerializer.js.map +1 -0
  97. package/glTF/2.0/glTFUtilities.d.ts +89 -0
  98. package/glTF/2.0/glTFUtilities.js +349 -0
  99. package/glTF/2.0/glTFUtilities.js.map +1 -0
  100. package/glTF/2.0/index.d.ts +4 -0
  101. package/glTF/2.0/index.js +6 -0
  102. package/glTF/2.0/index.js.map +1 -0
  103. package/glTF/glTFFileExporter.d.ts +20 -0
  104. package/glTF/glTFFileExporter.js +4 -0
  105. package/glTF/glTFFileExporter.js.map +1 -0
  106. package/glTF/index.d.ts +2 -0
  107. package/glTF/index.js +4 -0
  108. package/glTF/index.js.map +1 -0
  109. package/index.d.ts +4 -0
  110. package/index.js +6 -0
  111. package/index.js.map +1 -0
  112. package/legacy/legacy-glTF2Serializer.d.ts +2 -0
  113. package/legacy/legacy-glTF2Serializer.js +45 -0
  114. package/legacy/legacy-glTF2Serializer.js.map +1 -0
  115. package/legacy/legacy-objSerializer.d.ts +1 -0
  116. package/legacy/legacy-objSerializer.js +14 -0
  117. package/legacy/legacy-objSerializer.js.map +1 -0
  118. package/legacy/legacy-stlSerializer.d.ts +1 -0
  119. package/legacy/legacy-stlSerializer.js +14 -0
  120. package/legacy/legacy-stlSerializer.js.map +1 -0
  121. package/legacy/legacy-usdzSerializer.d.ts +1 -0
  122. package/legacy/legacy-usdzSerializer.js +14 -0
  123. package/legacy/legacy-usdzSerializer.js.map +1 -0
  124. package/legacy/legacy.d.ts +5 -0
  125. package/legacy/legacy.js +8 -0
  126. package/legacy/legacy.js.map +1 -0
  127. package/license.md +71 -0
  128. package/package.json +49 -0
  129. package/readme.md +29 -0
  130. package/stl/index.d.ts +1 -0
  131. package/stl/index.js +2 -0
  132. package/stl/index.js.map +1 -0
  133. package/stl/stlSerializer.d.ts +20 -0
  134. package/stl/stlSerializer.js +135 -0
  135. package/stl/stlSerializer.js.map +1 -0
@@ -0,0 +1,589 @@
1
+ /* eslint-disable @typescript-eslint/naming-convention */
2
+ import { VertexBuffer } from "@babylonjs/core/Buffers/buffer.js";
3
+ import { Constants } from "@babylonjs/core/Engines/constants.js";
4
+ import { Material } from "@babylonjs/core/Materials/material.js";
5
+ import { PBRBaseMaterial } from "@babylonjs/core/Materials/PBR/pbrBaseMaterial.js";
6
+ import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial.js";
7
+ import { Color3 } from "@babylonjs/core/Maths/math.color.js";
8
+ import { Matrix, Vector2 } from "@babylonjs/core/Maths/math.vector.js";
9
+ import { DumpTools } from "@babylonjs/core/Misc/dumpTools.js";
10
+ import { Tools } from "@babylonjs/core/Misc/tools.js";
11
+ import { IsNoopNode } from "../exportUtils.js";
12
+ import { GetTextureDataAsync } from "@babylonjs/core/Misc/textureTools.js";
13
+ function BuildHeader() {
14
+ return `#usda 1.0
15
+ (
16
+ customLayerData = {
17
+ string creator = "Babylon.js USDZExportAsync"
18
+ }
19
+ defaultPrim = "Root"
20
+ metersPerUnit = 1
21
+ upAxis = "Y"
22
+ )`;
23
+ }
24
+ function BuildRootAndSceneStart(options) {
25
+ const alignment = options.includeAnchoringProperties === true
26
+ ? `
27
+ token preliminary:anchoring:type = "${options.anchoringType}"
28
+ token preliminary:planeAnchoring:alignment = "${options.planeAnchoringAlignment}"`
29
+ : "";
30
+ return `def Xform "Root"
31
+ {
32
+ def Scope "Scenes" (
33
+ kind = "sceneLibrary"
34
+ )
35
+ {
36
+ def Xform "Scene" (
37
+ customData = {
38
+ bool preliminary_collidesWithEnvironment = 0
39
+ string sceneName = "Scene"
40
+ }
41
+ sceneName = "Scene"
42
+ )
43
+ {${alignment}
44
+ `;
45
+ }
46
+ function BuildSceneEnd() {
47
+ return `
48
+ }
49
+ }`;
50
+ }
51
+ function BuildRootEnd() {
52
+ return `
53
+ }`;
54
+ }
55
+ function BuildMeshVertexCount(geometry) {
56
+ const count = geometry.getIndices()?.length ? geometry.getTotalIndices() : geometry.getTotalVertices();
57
+ return Array(count / 3)
58
+ .fill(3)
59
+ .join(", ");
60
+ }
61
+ function BuildMeshVertexIndices(geometry) {
62
+ const indices = geometry.getIndices();
63
+ const count = indices?.length ?? geometry.getTotalVertices();
64
+ const array = [];
65
+ if (indices !== null) {
66
+ for (let i = 0; i < count; i++) {
67
+ array.push(indices[i]);
68
+ }
69
+ }
70
+ else {
71
+ for (let i = 0; i < count; i++) {
72
+ array.push(i);
73
+ }
74
+ }
75
+ return array.join(", ");
76
+ }
77
+ function BuildVector3Array(attribute, options, stride = 3, convertToRightHanded = false) {
78
+ const array = [];
79
+ for (let i = 0; i < attribute.length / stride; i++) {
80
+ const x = attribute[i * stride] * (convertToRightHanded ? -1 : 1);
81
+ const y = attribute[i * stride + 1];
82
+ const z = attribute[i * stride + 2];
83
+ array.push(`(${x.toPrecision(options.precision)}, ${y.toPrecision(options.precision)}, ${z.toPrecision(options.precision)})`);
84
+ }
85
+ return array.join(", ");
86
+ }
87
+ function BuildVector2Array(attribute, options) {
88
+ const array = [];
89
+ for (let i = 0; i < attribute.length / 2; i++) {
90
+ const x = attribute[i * 2];
91
+ const y = attribute[i * 2 + 1];
92
+ array.push(`(${x.toPrecision(options.precision)}, ${(1 - y).toPrecision(options.precision)})`);
93
+ }
94
+ return array.join(", ");
95
+ }
96
+ function BuildAdditionalAttributes(geometry, options) {
97
+ let string = "";
98
+ for (let i = 0; i < 4; i++) {
99
+ const id = i > 0 ? i : "";
100
+ const uvAttribute = geometry.getVerticesData(VertexBuffer.UVKind + (id ? id + 1 : "")); // UV names go like "uv", "uv2", "uv3", etc.
101
+ if (uvAttribute) {
102
+ string += `
103
+ texCoord2f[] primvars:st${id} = [${BuildVector2Array(uvAttribute, options)}] (
104
+ interpolation = "vertex"
105
+ )`;
106
+ }
107
+ }
108
+ // vertex colors
109
+ const colorAttribute = geometry.getVerticesData(VertexBuffer.ColorKind);
110
+ if (colorAttribute) {
111
+ string += `
112
+ color3f[] primvars:displayColor = [${BuildVector3Array(colorAttribute, options, colorAttribute.length / geometry.getTotalVertices())}] (
113
+ interpolation = "vertex"
114
+ )`;
115
+ }
116
+ return string;
117
+ }
118
+ function BuildMesh(geometry, options, windingOrder, convertToRightHanded) {
119
+ const name = "Geometry";
120
+ const position = geometry.getVerticesData(VertexBuffer.PositionKind);
121
+ const normal = geometry.getVerticesData(VertexBuffer.NormalKind);
122
+ if (!position || !normal) {
123
+ return;
124
+ }
125
+ return `
126
+ def Mesh "${name}"
127
+ {
128
+ uniform token orientation = "${windingOrder}"
129
+ int[] faceVertexCounts = [${BuildMeshVertexCount(geometry)}]
130
+ int[] faceVertexIndices = [${BuildMeshVertexIndices(geometry)}]
131
+ normal3f[] normals = [${BuildVector3Array(normal, options, undefined, convertToRightHanded)}] (
132
+ interpolation = "vertex"
133
+ )
134
+ point3f[] points = [${BuildVector3Array(position, options, undefined, convertToRightHanded)}]
135
+ ${BuildAdditionalAttributes(geometry, options)}
136
+ uniform token subdivisionScheme = "none"
137
+ }
138
+ `;
139
+ }
140
+ function BuildMeshObject(geometry, options, windingOrder, convertToRightHanded) {
141
+ const meshObject = BuildMesh(geometry, options, windingOrder, convertToRightHanded);
142
+ return `
143
+ def "Geometry"
144
+ {
145
+ ${meshObject}
146
+ }
147
+ `;
148
+ }
149
+ function BuildUSDFileAsString(dataToInsert) {
150
+ let output = BuildHeader();
151
+ output += dataToInsert;
152
+ return fflate.strToU8(output);
153
+ }
154
+ function BuildMatrix(matrix) {
155
+ const array = matrix.m;
156
+ return `( ${BuildMatrixRow(array, 0)}, ${BuildMatrixRow(array, 4)}, ${BuildMatrixRow(array, 8)}, ${BuildMatrixRow(array, 12)} )`;
157
+ }
158
+ function BuildMatrixRow(array, offset) {
159
+ return `(${array[offset + 0]}, ${array[offset + 1]}, ${array[offset + 2]}, ${array[offset + 3]})`;
160
+ }
161
+ function BuildXform(mesh, matrix) {
162
+ const name = "Object_" + mesh.uniqueId;
163
+ const transform = BuildMatrix(matrix);
164
+ return `def Xform "${name}" (
165
+ prepend references = @./geometries/Geometry_${mesh.geometry.uniqueId}.usda@</Geometry>
166
+ prepend apiSchemas = ["MaterialBindingAPI"]
167
+ )
168
+ {
169
+ matrix4d xformOp:transform = ${transform}
170
+ uniform token[] xformOpOrder = ["xformOp:transform"]
171
+
172
+ rel material:binding = </Root/Materials/Material_${mesh.material.uniqueId}>
173
+ }
174
+
175
+ `;
176
+ }
177
+ function BuildMaterials(materials, textureToExports, options) {
178
+ const array = [];
179
+ for (const uuid in materials) {
180
+ const material = materials[uuid];
181
+ array.push(BuildMaterial(material, textureToExports, options));
182
+ }
183
+ return `
184
+ def "Materials"
185
+ {
186
+ ${array.join("")}
187
+ }
188
+
189
+ `;
190
+ }
191
+ function BuildWrapping(wrapping) {
192
+ switch (wrapping) {
193
+ case Constants.TEXTURE_CLAMP_ADDRESSMODE:
194
+ return "clamp";
195
+ case Constants.TEXTURE_MIRROR_ADDRESSMODE:
196
+ return "mirror";
197
+ case Constants.TEXTURE_WRAP_ADDRESSMODE:
198
+ default:
199
+ return "repeat";
200
+ }
201
+ }
202
+ function BuildColor4(color) {
203
+ return `(${color.r}, ${color.g}, ${color.b}, 1.0)`;
204
+ }
205
+ function BuildVector2(vector) {
206
+ return `(${vector.x}, ${vector.y})`;
207
+ }
208
+ function BuildColor(color) {
209
+ return `(${color.r}, ${color.g}, ${color.b})`;
210
+ }
211
+ function BuildTexture(texture, material, mapType, color, textureToExports, options) {
212
+ const id = texture.getInternalTexture().uniqueId + "_" + texture.invertY;
213
+ textureToExports[id] = texture;
214
+ const uv = texture.coordinatesIndex > 0 ? "st" + texture.coordinatesIndex : "st";
215
+ const repeat = new Vector2(texture.uScale, texture.vScale);
216
+ const offset = new Vector2(texture.uOffset, texture.vOffset);
217
+ const rotation = texture.wAng;
218
+ // rotation is around the wrong point. after rotation we need to shift offset again so that we're rotating around the right spot
219
+ const xRotationOffset = Math.sin(rotation);
220
+ const yRotationOffset = Math.cos(rotation);
221
+ // texture coordinates start in the opposite corner, need to correct
222
+ offset.y = 1 - offset.y - repeat.y;
223
+ offset.x += xRotationOffset * repeat.x;
224
+ offset.y += (1 - yRotationOffset) * repeat.y;
225
+ return `
226
+ def Shader "PrimvarReader_${mapType}"
227
+ {
228
+ uniform token info:id = "UsdPrimvarReader_float2"
229
+ float2 inputs:fallback = (0.0, 0.0)
230
+ token inputs:varname = "${uv}"
231
+ float2 outputs:result
232
+ }
233
+
234
+ def Shader "Transform2d_${mapType}"
235
+ {
236
+ uniform token info:id = "UsdTransform2d"
237
+ token inputs:in.connect = </Root/Materials/Material_${material.uniqueId}/PrimvarReader_${mapType}.outputs:result>
238
+ float inputs:rotation = ${(rotation * (180 / Math.PI)).toFixed(options.precision)}
239
+ float2 inputs:scale = ${BuildVector2(repeat)}
240
+ float2 inputs:translation = ${BuildVector2(offset)}
241
+ float2 outputs:result
242
+ }
243
+
244
+ def Shader "Texture_${texture.uniqueId}_${mapType}"
245
+ {
246
+ uniform token info:id = "UsdUVTexture"
247
+ asset inputs:file = @textures/Texture_${id}.png@
248
+ float2 inputs:st.connect = </Root/Materials/Material_${material.uniqueId}/Transform2d_${mapType}.outputs:result>
249
+ ${color ? "float4 inputs:scale = " + BuildColor4(color) : ""}
250
+ token inputs:sourceColorSpace = "${texture.gammaSpace ? "sRGB" : "raw"}"
251
+ token inputs:wrapS = "${BuildWrapping(texture.wrapU)}"
252
+ token inputs:wrapT = "${BuildWrapping(texture.wrapV)}"
253
+ float outputs:r
254
+ float outputs:g
255
+ float outputs:b
256
+ float3 outputs:rgb
257
+ ${material.needAlphaBlending() || material.needAlphaTesting() ? "float outputs:a" : ""}
258
+ }`;
259
+ }
260
+ function ExtractTextureInformations(material) {
261
+ const defaults = {
262
+ diffuseMap: null,
263
+ diffuse: null,
264
+ alphaCutOff: 0,
265
+ emissiveMap: null,
266
+ emissive: null,
267
+ normalMap: null,
268
+ roughnessMap: null,
269
+ roughnessChannel: "a",
270
+ roughness: 0,
271
+ metalnessMap: null,
272
+ metalnessChannel: "r",
273
+ metalness: 0,
274
+ aoMap: null,
275
+ aoMapChannel: "rgb",
276
+ aoMapIntensity: 0,
277
+ alphaMap: null,
278
+ ior: 1,
279
+ clearCoatEnabled: false,
280
+ clearCoat: 0,
281
+ clearCoatMap: null,
282
+ clearCoatRoughness: 0,
283
+ clearCoatRoughnessMap: null,
284
+ };
285
+ if (material instanceof StandardMaterial) {
286
+ return {
287
+ ...defaults,
288
+ diffuseMap: material.diffuseTexture,
289
+ diffuse: material.diffuseColor,
290
+ alphaCutOff: material.alphaCutOff,
291
+ emissiveMap: material.emissiveTexture,
292
+ emissive: material.emissiveColor,
293
+ roughness: 1,
294
+ alphaMap: material.opacityTexture,
295
+ };
296
+ }
297
+ if (material instanceof PBRBaseMaterial) {
298
+ return {
299
+ ...defaults,
300
+ diffuseMap: material._albedoTexture,
301
+ diffuse: material._albedoColor,
302
+ alphaCutOff: material._alphaCutOff,
303
+ emissiveMap: material._emissiveTexture,
304
+ emissive: material._emissiveColor,
305
+ normalMap: material._bumpTexture,
306
+ roughnessMap: material._metallicTexture,
307
+ roughnessChannel: material._useRoughnessFromMetallicTextureAlpha ? "a" : "g",
308
+ roughness: material._roughness ?? 1,
309
+ metalnessMap: material._metallicTexture,
310
+ metalnessChannel: material._useMetallnessFromMetallicTextureBlue ? "b" : "r",
311
+ metalness: material._metallic ?? 0,
312
+ aoMap: material._ambientTexture,
313
+ aoMapChannel: material._useAmbientInGrayScale ? "r" : "rgb",
314
+ aoMapIntensity: material._ambientTextureStrength,
315
+ alphaMap: material._opacityTexture,
316
+ ior: material.subSurface.indexOfRefraction,
317
+ clearCoatEnabled: material.clearCoat.isEnabled,
318
+ clearCoat: material.clearCoat.intensity,
319
+ clearCoatMap: material.clearCoat.texture,
320
+ clearCoatRoughness: material.clearCoat.roughness,
321
+ clearCoatRoughnessMap: material.clearCoat.useRoughnessFromMainTexture ? material.clearCoat.texture : material.clearCoat.textureRoughness,
322
+ };
323
+ }
324
+ return defaults;
325
+ }
326
+ function BuildMaterial(material, textureToExports, options) {
327
+ // https://graphics.pixar.com/usd/docs/UsdPreviewSurface-Proposal.html
328
+ const pad = " ";
329
+ const inputs = [];
330
+ const samplers = [];
331
+ const { diffuseMap, diffuse, alphaCutOff, emissiveMap, emissive, normalMap, roughnessMap, roughnessChannel, roughness, metalnessMap, metalnessChannel, metalness, aoMap, aoMapChannel, aoMapIntensity, alphaMap, ior, clearCoatEnabled, clearCoat, clearCoatMap, clearCoatRoughness, clearCoatRoughnessMap, } = ExtractTextureInformations(material);
332
+ if (diffuseMap !== null) {
333
+ inputs.push(`${pad}color3f inputs:diffuseColor.connect = </Root/Materials/Material_${material.uniqueId}/Texture_${diffuseMap.uniqueId}_diffuse.outputs:rgb>`);
334
+ if (material.needAlphaBlending()) {
335
+ inputs.push(`${pad}float inputs:opacity.connect = </Root/Materials/Material_${material.uniqueId}/Texture_${diffuseMap.uniqueId}_diffuse.outputs:a>`);
336
+ }
337
+ else if (material.needAlphaTesting()) {
338
+ inputs.push(`${pad}float inputs:opacity.connect = </Root/Materials/Material_${material.uniqueId}/Texture_${diffuseMap.uniqueId}_diffuse.outputs:a>`);
339
+ inputs.push(`${pad}float inputs:opacityThreshold = ${alphaCutOff}`);
340
+ }
341
+ samplers.push(BuildTexture(diffuseMap, material, "diffuse", diffuse, textureToExports, options));
342
+ }
343
+ else {
344
+ inputs.push(`${pad}color3f inputs:diffuseColor = ${BuildColor(diffuse || Color3.White())}`);
345
+ }
346
+ if (emissiveMap !== null) {
347
+ inputs.push(`${pad}color3f inputs:emissiveColor.connect = </Root/Materials/Material_${material.uniqueId}/Texture_${emissiveMap.uniqueId}_emissive.outputs:rgb>`);
348
+ samplers.push(BuildTexture(emissiveMap, material, "emissive", emissive, textureToExports, options));
349
+ }
350
+ else if (emissive && emissive.toLuminance() > 0) {
351
+ inputs.push(`${pad}color3f inputs:emissiveColor = ${BuildColor(emissive)}`);
352
+ }
353
+ if (normalMap !== null) {
354
+ inputs.push(`${pad}normal3f inputs:normal.connect = </Root/Materials/Material_${material.uniqueId}/Texture_${normalMap.uniqueId}_normal.outputs:rgb>`);
355
+ samplers.push(BuildTexture(normalMap, material, "normal", null, textureToExports, options));
356
+ }
357
+ if (aoMap !== null) {
358
+ inputs.push(`${pad}float inputs:occlusion.connect = </Root/Materials/Material_${material.uniqueId}/Texture_${aoMap.uniqueId}_occlusion.outputs:${aoMapChannel}>`);
359
+ samplers.push(BuildTexture(aoMap, material, "occlusion", new Color3(aoMapIntensity, aoMapIntensity, aoMapIntensity), textureToExports, options));
360
+ }
361
+ if (roughnessMap !== null) {
362
+ inputs.push(`${pad}float inputs:roughness.connect = </Root/Materials/Material_${material.uniqueId}/Texture_${roughnessMap.uniqueId}_roughness.outputs:${roughnessChannel}>`);
363
+ samplers.push(BuildTexture(roughnessMap, material, "roughness", new Color3(roughness, roughness, roughness), textureToExports, options));
364
+ }
365
+ else {
366
+ inputs.push(`${pad}float inputs:roughness = ${roughness}`);
367
+ }
368
+ if (metalnessMap !== null) {
369
+ inputs.push(`${pad}float inputs:metallic.connect = </Root/Materials/Material_${material.uniqueId}/Texture_${metalnessMap.uniqueId}_metallic.outputs:${metalnessChannel}>`);
370
+ samplers.push(BuildTexture(metalnessMap, material, "metallic", new Color3(metalness, metalness, metalness), textureToExports, options));
371
+ }
372
+ else {
373
+ inputs.push(`${pad}float inputs:metallic = ${metalness}`);
374
+ }
375
+ if (alphaMap !== null) {
376
+ inputs.push(`${pad}float inputs:opacity.connect = </Root/Materials/Material_${material.uniqueId}/Texture_${alphaMap.uniqueId}_opacity.outputs:r>`);
377
+ inputs.push(`${pad}float inputs:opacityThreshold = 0.0001`);
378
+ samplers.push(BuildTexture(alphaMap, material, "opacity", null, textureToExports, options));
379
+ }
380
+ else {
381
+ inputs.push(`${pad}float inputs:opacity = ${material.alpha}`);
382
+ }
383
+ if (clearCoatEnabled) {
384
+ if (clearCoatMap !== null) {
385
+ inputs.push(`${pad}float inputs:clearcoat.connect = </Root/Materials/Material_${material.uniqueId}/Texture_${clearCoatMap.uniqueId}_clearcoat.outputs:r>`);
386
+ samplers.push(BuildTexture(clearCoatMap, material, "clearcoat", new Color3(clearCoat, clearCoat, clearCoat), textureToExports, options));
387
+ }
388
+ else {
389
+ inputs.push(`${pad}float inputs:clearcoat = ${clearCoat}`);
390
+ }
391
+ if (clearCoatRoughnessMap !== null) {
392
+ inputs.push(`${pad}float inputs:clearcoatRoughness.connect = </Root/Materials/Material_${material.uniqueId}/Texture_${clearCoatRoughnessMap.uniqueId}_clearcoatRoughness.outputs:g>`);
393
+ samplers.push(BuildTexture(clearCoatRoughnessMap, material, "clearcoatRoughness", new Color3(clearCoatRoughness, clearCoatRoughness, clearCoatRoughness), textureToExports, options));
394
+ }
395
+ else {
396
+ inputs.push(`${pad}float inputs:clearcoatRoughness = ${clearCoatRoughness}`);
397
+ }
398
+ }
399
+ inputs.push(`${pad}float inputs:ior = ${ior}`);
400
+ return `
401
+ def Material "Material_${material.uniqueId}"
402
+ {
403
+ def Shader "PreviewSurface"
404
+ {
405
+ uniform token info:id = "UsdPreviewSurface"
406
+ ${inputs.join("\n")}
407
+ int inputs:useSpecularWorkflow = 0
408
+ token outputs:surface
409
+ }
410
+
411
+ token outputs:surface.connect = </Root/Materials/Material_${material.uniqueId}/PreviewSurface.outputs:surface>
412
+
413
+ ${samplers.join("\n")}
414
+
415
+ }
416
+ `;
417
+ }
418
+ function BuildCamera(camera, options) {
419
+ const name = "Camera_" + camera.uniqueId;
420
+ const matrix = Matrix.RotationY(Math.PI).multiply(camera.getWorldMatrix()); // work towards positive z
421
+ const transform = BuildMatrix(matrix);
422
+ if (camera.mode === Constants.ORTHOGRAPHIC_CAMERA) {
423
+ return `def Camera "${name}"
424
+ {
425
+ matrix4d xformOp:transform = ${transform}
426
+ uniform token[] xformOpOrder = ["xformOp:transform"]
427
+
428
+ float2 clippingRange = (${camera.minZ.toPrecision(options.precision)}, ${camera.maxZ.toPrecision(options.precision)})
429
+ float horizontalAperture = ${((Math.abs(camera.orthoLeft || 1) + Math.abs(camera.orthoRight || 1)) * 10).toPrecision(options.precision)}
430
+ float verticalAperture = ${((Math.abs(camera.orthoTop || 1) + Math.abs(camera.orthoBottom || 1)) * 10).toPrecision(options.precision)}
431
+ token projection = "orthographic"
432
+ }
433
+
434
+ `;
435
+ }
436
+ else {
437
+ const aspect = camera.getEngine().getAspectRatio(camera);
438
+ const sensorwidth = options.cameraSensorWidth || 35;
439
+ return `def Camera "${name}"
440
+ {
441
+ matrix4d xformOp:transform = ${transform}
442
+ uniform token[] xformOpOrder = ["xformOp:transform"]
443
+
444
+ float2 clippingRange = (${camera.minZ.toPrecision(options.precision)}, ${camera.maxZ.toPrecision(options.precision)})
445
+ float focalLength = ${(sensorwidth / (2 * Math.tan(camera.fov * 0.5))).toPrecision(options.precision)}
446
+ token projection = "perspective"
447
+ float horizontalAperture = ${(sensorwidth * aspect).toPrecision(options.precision)}
448
+ float verticalAperture = ${(sensorwidth / aspect).toPrecision(options.precision)}
449
+ }
450
+
451
+ `;
452
+ }
453
+ }
454
+ function ExtractMeshInformations(mesh) {
455
+ mesh.computeWorldMatrix(true);
456
+ const matrix = mesh.getWorldMatrix().clone();
457
+ const sceneIsRightHanded = mesh.getScene().useRightHandedSystem;
458
+ let sideOrientation = mesh.material?._getEffectiveOrientation(mesh) ?? mesh.sideOrientation;
459
+ let convertToRightHanded = !sceneIsRightHanded;
460
+ // Search for a root conversion node from the glTF loader in the mesh's ancestors.
461
+ let current = mesh.parent;
462
+ while (current) {
463
+ if (IsNoopNode(current, sceneIsRightHanded) && current.parent === null) {
464
+ if (!sceneIsRightHanded) {
465
+ // If it's a RH->LH node, cancel out its inversion effect on the mesh's matrix and winding order.
466
+ matrix.multiplyToRef(current.getWorldMatrix().invert(), matrix);
467
+ sideOrientation = sideOrientation === Material.ClockWiseSideOrientation ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation;
468
+ }
469
+ convertToRightHanded = false;
470
+ break;
471
+ }
472
+ current = current.parent;
473
+ }
474
+ if (matrix.determinant() < 0) {
475
+ // RealityKit doesn't seem to automatically flip faces of a mesh with negative scale, like other engines do (including us).
476
+ Tools.Warn(`Mesh ${mesh.name} has a negative scale, which may look incorrect in destinations like QuickLook.`);
477
+ }
478
+ return {
479
+ matrix,
480
+ windingOrder: sideOrientation === Material.ClockWiseSideOrientation ? "leftHanded" : "rightHanded",
481
+ convertToRightHanded,
482
+ };
483
+ }
484
+ /**
485
+ *
486
+ * @param scene scene to export
487
+ * @param options options to configure the export
488
+ * @param meshPredicate predicate to filter the meshes to export
489
+ * @returns a uint8 array containing the USDZ file
490
+ * @see [Simple sphere](https://playground.babylonjs.com/#H2G5XW#6)
491
+ * @see [Red sphere](https://playground.babylonjs.com/#H2G5XW#7)
492
+ * @see [Boombox](https://playground.babylonjs.com/#5N3RWK#5)
493
+ */
494
+ export async function USDZExportAsync(scene, options, meshPredicate) {
495
+ const localOptions = {
496
+ fflateUrl: "https://unpkg.com/fflate@0.8.2",
497
+ includeAnchoringProperties: true,
498
+ anchoringType: "plane",
499
+ planeAnchoringAlignment: "horizontal",
500
+ modelFileName: "model.usda",
501
+ precision: 5,
502
+ exportCamera: false,
503
+ cameraSensorWidth: 35,
504
+ ...options,
505
+ };
506
+ // Get the fflate library
507
+ if (typeof fflate === "undefined") {
508
+ await Tools.LoadScriptAsync(localOptions.fflateUrl);
509
+ }
510
+ // Start the export
511
+ const files = {};
512
+ // model file should be first in USDZ archive so we init it here
513
+ files[localOptions.modelFileName] = null;
514
+ let output = BuildHeader();
515
+ output += BuildRootAndSceneStart(localOptions);
516
+ const materialToExports = {};
517
+ // Meshes
518
+ for (const abstractMesh of scene.meshes) {
519
+ if (abstractMesh.getTotalVertices() === 0) {
520
+ continue;
521
+ }
522
+ const mesh = abstractMesh;
523
+ const geometry = mesh.geometry;
524
+ const material = mesh.material;
525
+ if (!material || !geometry || (meshPredicate && !meshPredicate(mesh))) {
526
+ continue;
527
+ }
528
+ const supportedMaterials = ["StandardMaterial", "PBRMaterial", "PBRMetallicRoughnessMaterial"];
529
+ if (supportedMaterials.indexOf(material.getClassName()) !== -1) {
530
+ const geometryFileName = "geometries/Geometry_" + geometry.uniqueId + ".usda";
531
+ const { matrix, windingOrder, convertToRightHanded } = ExtractMeshInformations(mesh);
532
+ if (!(geometryFileName in files)) {
533
+ const meshObject = BuildMeshObject(geometry, localOptions, windingOrder, convertToRightHanded);
534
+ files[geometryFileName] = BuildUSDFileAsString(meshObject);
535
+ }
536
+ if (!(material.uniqueId in materialToExports)) {
537
+ materialToExports[material.uniqueId] = material;
538
+ }
539
+ output += BuildXform(mesh, matrix);
540
+ }
541
+ else {
542
+ Tools.Warn("USDZExportAsync does not support this material type: " + material.getClassName());
543
+ }
544
+ }
545
+ // Camera
546
+ if (scene.activeCamera && localOptions.exportCamera) {
547
+ output += BuildCamera(scene.activeCamera, localOptions);
548
+ }
549
+ // Close scene
550
+ output += BuildSceneEnd();
551
+ // Materials
552
+ const textureToExports = {};
553
+ output += BuildMaterials(materialToExports, textureToExports, localOptions);
554
+ // Close root
555
+ output += BuildRootEnd();
556
+ // Compress
557
+ files[localOptions.modelFileName] = fflate.strToU8(output);
558
+ // Textures
559
+ for (const id in textureToExports) {
560
+ const texture = textureToExports[id];
561
+ const size = texture.getSize();
562
+ // eslint-disable-next-line no-await-in-loop
563
+ const textureData = await GetTextureDataAsync(texture);
564
+ // eslint-disable-next-line no-await-in-loop
565
+ const fileContent = await DumpTools.DumpDataAsync(size.width, size.height, textureData, "image/png", undefined, false, true);
566
+ files[`textures/Texture_${id}.png`] = new Uint8Array(fileContent).slice(); // This is to avoid getting a link and not a copy
567
+ }
568
+ // 64 byte alignment
569
+ // https://github.com/101arrowz/fflate/issues/39#issuecomment-777263109
570
+ let offset = 0;
571
+ for (const filename in files) {
572
+ const file = files[filename];
573
+ if (!file) {
574
+ continue;
575
+ }
576
+ const headerSize = 34 + filename.length;
577
+ offset += headerSize;
578
+ const offsetMod64 = offset & 63;
579
+ if (offsetMod64 !== 4) {
580
+ const padLength = 64 - offsetMod64;
581
+ const padding = new Uint8Array(padLength);
582
+ // eslint-disable-next-line @typescript-eslint/naming-convention
583
+ files[filename] = [file, { extra: { 12345: padding } }];
584
+ }
585
+ offset = file.length;
586
+ }
587
+ return fflate.zipSync(files, { level: 0 });
588
+ }
589
+ //# sourceMappingURL=usdzExporter.js.map