@babylonjs/serializers 8.10.0 → 8.11.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.
@@ -1,4 +1,4 @@
1
- import { TmpVectors, Quaternion, Matrix } from "@babylonjs/core/Maths/math.vector.js";
1
+ import { TmpVectors, Quaternion } from "@babylonjs/core/Maths/math.vector.js";
2
2
  import { Tools } from "@babylonjs/core/Misc/tools.js";
3
3
  import { VertexBuffer } from "@babylonjs/core/Buffers/buffer.js";
4
4
  import { TransformNode } from "@babylonjs/core/Meshes/transformNode.js";
@@ -9,7 +9,7 @@ import { Engine } from "@babylonjs/core/Engines/engine.js";
9
9
  import { EngineStore } from "@babylonjs/core/Engines/engineStore.js";
10
10
  import { GLTFMaterialExporter } from "./glTFMaterialExporter.js";
11
11
  import { GLTFData } from "./glTFData.js";
12
- import { ConvertToRightHandedPosition, ConvertToRightHandedRotation, DataArrayToUint8Array, GetAccessorType, GetAttributeType, GetMinMax, GetPrimitiveMode, IsNoopNode, IsTriangleFillMode, IsParentAddedByImporter, ConvertToRightHandedNode, RotateNode180Y, FloatsNeed16BitInteger, IsStandardVertexAttribute, IndicesArrayToTypedArray, GetVertexBufferInfo, } from "./glTFUtilities.js";
12
+ import { ConvertToRightHandedPosition, ConvertToRightHandedRotation, DataArrayToUint8Array, GetAccessorType, GetAttributeType, GetMinMax, GetPrimitiveMode, IsNoopNode, IsTriangleFillMode, IsChildCollapsible, FloatsNeed16BitInteger, IsStandardVertexAttribute, IndicesArrayToTypedArray, GetVertexBufferInfo, CollapseChildIntoParent, Rotate180Y, DefaultTranslation, DefaultScale, DefaultRotation, } from "./glTFUtilities.js";
13
13
  import { BufferManager } from "./bufferManager.js";
14
14
  import { Camera } from "@babylonjs/core/Cameras/camera.js";
15
15
  import { MultiMaterial } from "@babylonjs/core/Materials/multiMaterial.js";
@@ -22,6 +22,8 @@ import { BuildMorphTargetBuffers } from "./glTFMorphTargetsUtilities.js";
22
22
  import { LinesMesh } from "@babylonjs/core/Meshes/linesMesh.js";
23
23
  import { GreasedLineBaseMesh } from "@babylonjs/core/Meshes/GreasedLine/greasedLineBaseMesh.js";
24
24
  import { Color3, Color4 } from "@babylonjs/core/Maths/math.color.js";
25
+ import { TargetCamera } from "@babylonjs/core/Cameras/targetCamera.js";
26
+ import { Epsilon } from "@babylonjs/core/Maths/math.constants.js";
25
27
  class ExporterState {
26
28
  constructor(convertToRightHanded, wasAddedByNoopNode) {
27
29
  // Babylon indices array, start, count, offset, flip -> glTF accessor index
@@ -463,48 +465,48 @@ export class GLTFExporter {
463
465
  return container;
464
466
  }
465
467
  _setNodeTransformation(node, babylonTransformNode, convertToRightHanded) {
466
- if (!babylonTransformNode.getPivotPoint().equalsToFloats(0, 0, 0)) {
468
+ if (!babylonTransformNode.getPivotPoint().equalsWithEpsilon(DefaultTranslation, Epsilon)) {
467
469
  Tools.Warn("Pivot points are not supported in the glTF serializer");
468
470
  }
469
- if (!babylonTransformNode.position.equalsToFloats(0, 0, 0)) {
471
+ if (!babylonTransformNode.position.equalsWithEpsilon(DefaultTranslation, Epsilon)) {
470
472
  const translation = TmpVectors.Vector3[0].copyFrom(babylonTransformNode.position);
471
473
  if (convertToRightHanded) {
472
474
  ConvertToRightHandedPosition(translation);
473
475
  }
474
476
  node.translation = translation.asArray();
475
477
  }
476
- if (!babylonTransformNode.scaling.equalsToFloats(1, 1, 1)) {
478
+ if (!babylonTransformNode.scaling.equalsWithEpsilon(DefaultScale, Epsilon)) {
477
479
  node.scale = babylonTransformNode.scaling.asArray();
478
480
  }
479
- const rotationQuaternion = Quaternion.FromEulerAngles(babylonTransformNode.rotation.x, babylonTransformNode.rotation.y, babylonTransformNode.rotation.z);
480
- if (babylonTransformNode.rotationQuaternion) {
481
- rotationQuaternion.multiplyInPlace(babylonTransformNode.rotationQuaternion);
482
- }
483
- if (!Quaternion.IsIdentity(rotationQuaternion)) {
481
+ const rotationQuaternion = babylonTransformNode.rotationQuaternion ||
482
+ Quaternion.FromEulerAngles(babylonTransformNode.rotation.x, babylonTransformNode.rotation.y, babylonTransformNode.rotation.z);
483
+ if (!rotationQuaternion.equalsWithEpsilon(DefaultRotation, Epsilon)) {
484
484
  if (convertToRightHanded) {
485
485
  ConvertToRightHandedRotation(rotationQuaternion);
486
486
  }
487
487
  node.rotation = rotationQuaternion.normalize().asArray();
488
488
  }
489
489
  }
490
- _setCameraTransformation(node, babylonCamera, convertToRightHanded, parent) {
491
- const translation = TmpVectors.Vector3[0];
492
- const rotation = TmpVectors.Quaternion[0];
493
- if (parent !== null) {
494
- // Camera.getWorldMatrix returns global coordinates. GLTF node must use local coordinates. If camera has parent we need to use local translation/rotation.
495
- const parentWorldMatrix = Matrix.Invert(parent.getWorldMatrix());
496
- const cameraWorldMatrix = babylonCamera.getWorldMatrix();
497
- const cameraLocal = cameraWorldMatrix.multiply(parentWorldMatrix);
498
- cameraLocal.decompose(undefined, rotation, translation);
490
+ _setCameraTransformation(node, babylonCamera, convertToRightHanded) {
491
+ if (!babylonCamera.position.equalsWithEpsilon(DefaultTranslation, Epsilon)) {
492
+ const translation = TmpVectors.Vector3[0].copyFrom(babylonCamera.position);
493
+ if (convertToRightHanded) {
494
+ ConvertToRightHandedPosition(translation);
495
+ }
496
+ node.translation = translation.asArray();
499
497
  }
500
- else {
501
- babylonCamera.getWorldMatrix().decompose(undefined, rotation, translation);
498
+ const rotationQuaternion = babylonCamera.rotationQuaternion || Quaternion.FromEulerAngles(babylonCamera.rotation.x, babylonCamera.rotation.y, babylonCamera.rotation.z);
499
+ if (convertToRightHanded) {
500
+ ConvertToRightHandedRotation(rotationQuaternion);
502
501
  }
503
- if (!translation.equalsToFloats(0, 0, 0)) {
504
- node.translation = translation.asArray();
502
+ // Left-handed scenes have cameras that always face Z+ (opposite of glTF's Z-).
503
+ // Use scene coordinate system rather than convertToRightHanded, since some
504
+ // cameras may not need convertToRightHanded but still need correction to face Z-.
505
+ if (!this._babylonScene.useRightHandedSystem) {
506
+ Rotate180Y(rotationQuaternion);
505
507
  }
506
- if (!Quaternion.IsIdentity(rotation)) {
507
- node.rotation = rotation.asArray();
508
+ if (!rotationQuaternion.equalsWithEpsilon(DefaultRotation, Epsilon)) {
509
+ node.rotation = rotationQuaternion.asArray();
508
510
  }
509
511
  }
510
512
  // Export babylon cameras to glTF cameras
@@ -953,27 +955,24 @@ export class GLTFExporter {
953
955
  }
954
956
  }
955
957
  }
956
- if (babylonNode instanceof Camera) {
958
+ if (babylonNode instanceof TargetCamera) {
957
959
  const gltfCamera = this._camerasMap.get(babylonNode);
958
960
  if (gltfCamera) {
959
961
  if (this._nodesCameraMap.get(gltfCamera) === undefined) {
960
962
  this._nodesCameraMap.set(gltfCamera, []);
961
963
  }
964
+ this._setCameraTransformation(node, babylonNode, state.convertToRightHanded);
965
+ // If a parent node exists and can be collapsed, merge their transformations and mark the parent as the camera-containing node.
962
966
  const parentBabylonNode = babylonNode.parent;
963
- this._setCameraTransformation(node, babylonNode, state.convertToRightHanded, parentBabylonNode);
964
- // If a camera has a node that was added by the GLTF importer, we can just use the parent node transform as the "camera" transform.
965
- if (parentBabylonNode && IsParentAddedByImporter(babylonNode, parentBabylonNode)) {
967
+ if (parentBabylonNode !== null && IsChildCollapsible(babylonNode, parentBabylonNode)) {
966
968
  const parentNodeIndex = this._nodeMap.get(parentBabylonNode);
967
- if (parentNodeIndex) {
969
+ if (parentNodeIndex !== undefined) {
968
970
  const parentNode = this._nodes[parentNodeIndex];
971
+ CollapseChildIntoParent(node, parentNode);
969
972
  this._nodesCameraMap.get(gltfCamera)?.push(parentNode);
970
- return null; // Skip exporting this node
973
+ return null; // Skip exporting the original child node
971
974
  }
972
975
  }
973
- if (state.convertToRightHanded) {
974
- ConvertToRightHandedNode(node);
975
- RotateNode180Y(node);
976
- }
977
976
  this._nodesCameraMap.get(gltfCamera)?.push(node);
978
977
  }
979
978
  }
@@ -1108,7 +1107,7 @@ export class GLTFExporter {
1108
1107
  const colorWhite = Color3.White();
1109
1108
  const alpha = babylonLinesMesh.material?.alpha ?? 1;
1110
1109
  const color = babylonLinesMesh.greasedLineMaterial?.color ?? colorWhite;
1111
- if (!color.equals(colorWhite) || alpha < 1) {
1110
+ if (!color.equalsWithEpsilon(colorWhite, Epsilon) || alpha < 1) {
1112
1111
  material.pbrMetallicRoughness = {
1113
1112
  baseColorFactor: [...color.asArray(), alpha],
1114
1113
  };
@@ -1122,7 +1121,7 @@ export class GLTFExporter {
1122
1121
  name: babylonMaterial.name,
1123
1122
  };
1124
1123
  const babylonLinesMesh = babylonMesh;
1125
- if (!babylonLinesMesh.color.equals(Color3.White()) || babylonLinesMesh.alpha < 1) {
1124
+ if (!babylonLinesMesh.color.equalsWithEpsilon(Color3.White(), Epsilon) || babylonLinesMesh.alpha < 1) {
1126
1125
  material.pbrMetallicRoughness = {
1127
1126
  baseColorFactor: [...babylonLinesMesh.color.asArray(), babylonLinesMesh.alpha],
1128
1127
  };