@babylonjs/serializers 7.41.0 → 7.42.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,6 +1,5 @@
1
1
  import type { ITextureInfo } from "babylonjs-gltf2interface";
2
2
  import type { Texture } from "@babylonjs/core/Materials/Textures/texture.js";
3
- import type { Nullable } from "@babylonjs/core/types.js";
4
3
  import type { IGLTFExporterExtensionV2 } from "../glTFExporterExtension";
5
4
  /**
6
5
  * @internal
@@ -19,5 +18,4 @@ export declare class KHR_texture_transform implements IGLTFExporterExtensionV2 {
19
18
  /** @internal */
20
19
  get wasUsed(): boolean;
21
20
  postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: Texture): void;
22
- preExportTextureAsync(context: string, babylonTexture: Texture): Promise<Nullable<Texture>>;
23
21
  }
@@ -3,6 +3,7 @@ import { GLTFExporter } from "../glTFExporter.js";
3
3
  const NAME = "KHR_texture_transform";
4
4
  /**
5
5
  * Computes the adjusted offset for a rotation centered about the origin.
6
+ * This does not work when scaling is involved; investigation is needed.
6
7
  * @internal
7
8
  */
8
9
  function AdjustOffsetForRotationCenter(babylonTexture) {
@@ -34,59 +35,53 @@ export class KHR_texture_transform {
34
35
  return this._wasUsed;
35
36
  }
36
37
  postExportTexture(context, textureInfo, babylonTexture) {
37
- const canUseExtension = babylonTexture && babylonTexture.uAng === 0 && babylonTexture.vAng === 0;
38
- if (canUseExtension) {
39
- const textureTransform = {};
40
- let transformIsRequired = false;
41
- if (babylonTexture.uOffset !== 0 || babylonTexture.vOffset !== 0) {
42
- textureTransform.offset = [babylonTexture.uOffset, babylonTexture.vOffset];
43
- transformIsRequired = true;
44
- }
45
- if (babylonTexture.uScale !== 1 || babylonTexture.vScale !== 1) {
46
- textureTransform.scale = [babylonTexture.uScale, babylonTexture.vScale];
47
- transformIsRequired = true;
48
- }
49
- if (babylonTexture.wAng !== 0) {
50
- textureTransform.rotation = -babylonTexture.wAng;
51
- transformIsRequired = true;
52
- if (babylonTexture.uRotationCenter !== 0 || babylonTexture.vRotationCenter !== 0) {
53
- textureTransform.offset = AdjustOffsetForRotationCenter(babylonTexture);
38
+ const scene = babylonTexture.getScene();
39
+ if (!scene) {
40
+ Tools.Warn(`${context}: "scene" is not defined for Babylon texture ${babylonTexture.name}! Not exporting with ${NAME}.`);
41
+ return;
42
+ }
43
+ /*
44
+ * The KHR_texture_transform schema only supports w rotation around the origin.
45
+ * See https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform#gltf-schema-updates.
46
+ */
47
+ if (babylonTexture.uAng !== 0 || babylonTexture.vAng !== 0) {
48
+ Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation in the u or v axis is not supported in glTF.`);
49
+ return;
50
+ }
51
+ const textureTransform = {};
52
+ let transformIsRequired = false;
53
+ if (babylonTexture.uOffset !== 0 || babylonTexture.vOffset !== 0) {
54
+ textureTransform.offset = [babylonTexture.uOffset, babylonTexture.vOffset];
55
+ transformIsRequired = true;
56
+ }
57
+ if (babylonTexture.uScale !== 1 || babylonTexture.vScale !== 1) {
58
+ textureTransform.scale = [babylonTexture.uScale, babylonTexture.vScale];
59
+ transformIsRequired = true;
60
+ }
61
+ if (babylonTexture.wAng !== 0) {
62
+ if (babylonTexture.uRotationCenter !== 0 || babylonTexture.vRotationCenter !== 0) {
63
+ if (babylonTexture.uScale !== 1 || babylonTexture.vScale !== 1) {
64
+ Tools.Warn(`${context}: Texture ${babylonTexture.name} with scaling and a rotation not centered at the origin cannot be exported with ${NAME}`);
65
+ return;
54
66
  }
67
+ Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation not centered at the origin will be exported with an adjusted texture offset for ${NAME}.`);
68
+ textureTransform.offset = AdjustOffsetForRotationCenter(babylonTexture);
55
69
  }
56
- if (babylonTexture.coordinatesIndex !== 0) {
57
- textureTransform.texCoord = babylonTexture.coordinatesIndex;
58
- transformIsRequired = true;
59
- }
60
- if (!transformIsRequired) {
61
- return;
62
- }
63
- this._wasUsed = true;
64
- if (!textureInfo.extensions) {
65
- textureInfo.extensions = {};
66
- }
67
- textureInfo.extensions[NAME] = textureTransform;
70
+ textureTransform.rotation = -babylonTexture.wAng;
71
+ transformIsRequired = true;
68
72
  }
69
- }
70
- preExportTextureAsync(context, babylonTexture) {
71
- return new Promise((resolve, reject) => {
72
- const scene = babylonTexture.getScene();
73
- if (!scene) {
74
- reject(`${context}: "scene" is not defined for Babylon texture ${babylonTexture.name}!`);
75
- return;
76
- }
77
- /*
78
- * The KHR_texture_transform schema only supports w rotation around the origin.
79
- * See https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform#gltf-schema-updates.
80
- */
81
- if (babylonTexture.uAng !== 0 || babylonTexture.vAng !== 0) {
82
- Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation in the u or v axis is not supported in glTF.`);
83
- resolve(null);
84
- }
85
- if (babylonTexture.wAng !== 0 && (babylonTexture.uRotationCenter !== 0 || babylonTexture.vRotationCenter !== 0)) {
86
- Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation not centered at the origin will be exported with an adjusted texture offset.`);
87
- }
88
- resolve(babylonTexture);
89
- });
73
+ if (babylonTexture.coordinatesIndex !== 0) {
74
+ textureTransform.texCoord = babylonTexture.coordinatesIndex;
75
+ transformIsRequired = true;
76
+ }
77
+ if (!transformIsRequired) {
78
+ return;
79
+ }
80
+ this._wasUsed = true;
81
+ if (!textureInfo.extensions) {
82
+ textureInfo.extensions = {};
83
+ }
84
+ textureInfo.extensions[NAME] = textureTransform;
90
85
  }
91
86
  }
92
87
  GLTFExporter.RegisterExtension(NAME, () => new KHR_texture_transform());
@@ -1 +1 @@
1
- {"version":3,"file":"KHR_texture_transform.js","sourceRoot":"","sources":["../../../../../../dev/serializers/src/glTF/2.0/Extensions/KHR_texture_transform.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ITextureInfo, IKHRTextureTransform } from \"babylonjs-gltf2interface\";\r\nimport { Tools } from \"core/Misc/tools\";\r\nimport type { Texture } from \"core/Materials/Textures/texture\";\r\nimport type { Nullable } from \"core/types\";\r\nimport type { IGLTFExporterExtensionV2 } from \"../glTFExporterExtension\";\r\nimport { GLTFExporter } from \"../glTFExporter\";\r\n\r\nconst NAME = \"KHR_texture_transform\";\r\n\r\n/**\r\n * Computes the adjusted offset for a rotation centered about the origin.\r\n * @internal\r\n */\r\nfunction AdjustOffsetForRotationCenter(babylonTexture: Texture): [number, number] {\r\n const { uOffset, vOffset, uRotationCenter, vRotationCenter, wAng } = babylonTexture;\r\n const cosAngle = Math.cos(-wAng);\r\n const sinAngle = Math.sin(-wAng);\r\n const deltaU = uRotationCenter * (1 - cosAngle) - vRotationCenter * sinAngle;\r\n const deltaV = vRotationCenter * (1 - cosAngle) + uRotationCenter * sinAngle;\r\n return [uOffset + deltaU, vOffset + deltaV];\r\n}\r\n\r\n/**\r\n * @internal\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_texture_transform implements IGLTFExporterExtensionV2 {\r\n /** Name of this extension */\r\n public readonly name = NAME;\r\n\r\n /** Defines whether this extension is enabled */\r\n public enabled = true;\r\n\r\n /** Defines whether this extension is required */\r\n public required = false;\r\n\r\n /** Reference to the glTF exporter */\r\n private _wasUsed = false;\r\n\r\n constructor() {}\r\n\r\n public dispose() {}\r\n\r\n /** @internal */\r\n public get wasUsed() {\r\n return this._wasUsed;\r\n }\r\n\r\n public postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: Texture): void {\r\n const canUseExtension = babylonTexture && babylonTexture.uAng === 0 && babylonTexture.vAng === 0;\r\n\r\n if (canUseExtension) {\r\n const textureTransform: IKHRTextureTransform = {};\r\n let transformIsRequired = false;\r\n\r\n if (babylonTexture.uOffset !== 0 || babylonTexture.vOffset !== 0) {\r\n textureTransform.offset = [babylonTexture.uOffset, babylonTexture.vOffset];\r\n transformIsRequired = true;\r\n }\r\n\r\n if (babylonTexture.uScale !== 1 || babylonTexture.vScale !== 1) {\r\n textureTransform.scale = [babylonTexture.uScale, babylonTexture.vScale];\r\n transformIsRequired = true;\r\n }\r\n\r\n if (babylonTexture.wAng !== 0) {\r\n textureTransform.rotation = -babylonTexture.wAng;\r\n transformIsRequired = true;\r\n\r\n if (babylonTexture.uRotationCenter !== 0 || babylonTexture.vRotationCenter !== 0) {\r\n textureTransform.offset = AdjustOffsetForRotationCenter(babylonTexture);\r\n }\r\n }\r\n\r\n if (babylonTexture.coordinatesIndex !== 0) {\r\n textureTransform.texCoord = babylonTexture.coordinatesIndex;\r\n transformIsRequired = true;\r\n }\r\n\r\n if (!transformIsRequired) {\r\n return;\r\n }\r\n\r\n this._wasUsed = true;\r\n if (!textureInfo.extensions) {\r\n textureInfo.extensions = {};\r\n }\r\n textureInfo.extensions[NAME] = textureTransform;\r\n }\r\n }\r\n\r\n public preExportTextureAsync(context: string, babylonTexture: Texture): Promise<Nullable<Texture>> {\r\n return new Promise((resolve, reject) => {\r\n const scene = babylonTexture.getScene();\r\n if (!scene) {\r\n reject(`${context}: \"scene\" is not defined for Babylon texture ${babylonTexture.name}!`);\r\n return;\r\n }\r\n\r\n /*\r\n * The KHR_texture_transform schema only supports w rotation around the origin.\r\n * See https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform#gltf-schema-updates.\r\n */\r\n if (babylonTexture.uAng !== 0 || babylonTexture.vAng !== 0) {\r\n Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation in the u or v axis is not supported in glTF.`);\r\n resolve(null);\r\n }\r\n if (babylonTexture.wAng !== 0 && (babylonTexture.uRotationCenter !== 0 || babylonTexture.vRotationCenter !== 0)) {\r\n Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation not centered at the origin will be exported with an adjusted texture offset.`);\r\n }\r\n resolve(babylonTexture);\r\n });\r\n }\r\n}\r\n\r\nGLTFExporter.RegisterExtension(NAME, () => new KHR_texture_transform());\r\n"]}
1
+ {"version":3,"file":"KHR_texture_transform.js","sourceRoot":"","sources":["../../../../../../dev/serializers/src/glTF/2.0/Extensions/KHR_texture_transform.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ITextureInfo, IKHRTextureTransform } from \"babylonjs-gltf2interface\";\r\nimport { Tools } from \"core/Misc/tools\";\r\nimport type { Texture } from \"core/Materials/Textures/texture\";\r\nimport type { IGLTFExporterExtensionV2 } from \"../glTFExporterExtension\";\r\nimport { GLTFExporter } from \"../glTFExporter\";\r\n\r\nconst NAME = \"KHR_texture_transform\";\r\n\r\n/**\r\n * Computes the adjusted offset for a rotation centered about the origin.\r\n * This does not work when scaling is involved; investigation is needed.\r\n * @internal\r\n */\r\nfunction AdjustOffsetForRotationCenter(babylonTexture: Texture): [number, number] {\r\n const { uOffset, vOffset, uRotationCenter, vRotationCenter, wAng } = babylonTexture;\r\n const cosAngle = Math.cos(-wAng);\r\n const sinAngle = Math.sin(-wAng);\r\n const deltaU = uRotationCenter * (1 - cosAngle) - vRotationCenter * sinAngle;\r\n const deltaV = vRotationCenter * (1 - cosAngle) + uRotationCenter * sinAngle;\r\n return [uOffset + deltaU, vOffset + deltaV];\r\n}\r\n\r\n/**\r\n * @internal\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class KHR_texture_transform implements IGLTFExporterExtensionV2 {\r\n /** Name of this extension */\r\n public readonly name = NAME;\r\n\r\n /** Defines whether this extension is enabled */\r\n public enabled = true;\r\n\r\n /** Defines whether this extension is required */\r\n public required = false;\r\n\r\n /** Reference to the glTF exporter */\r\n private _wasUsed = false;\r\n\r\n constructor() {}\r\n\r\n public dispose() {}\r\n\r\n /** @internal */\r\n public get wasUsed() {\r\n return this._wasUsed;\r\n }\r\n\r\n public postExportTexture?(context: string, textureInfo: ITextureInfo, babylonTexture: Texture): void {\r\n const scene = babylonTexture.getScene();\r\n if (!scene) {\r\n Tools.Warn(`${context}: \"scene\" is not defined for Babylon texture ${babylonTexture.name}! Not exporting with ${NAME}.`);\r\n return;\r\n }\r\n\r\n /*\r\n * The KHR_texture_transform schema only supports w rotation around the origin.\r\n * See https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_texture_transform#gltf-schema-updates.\r\n */\r\n if (babylonTexture.uAng !== 0 || babylonTexture.vAng !== 0) {\r\n Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation in the u or v axis is not supported in glTF.`);\r\n return;\r\n }\r\n\r\n const textureTransform: IKHRTextureTransform = {};\r\n let transformIsRequired = false;\r\n\r\n if (babylonTexture.uOffset !== 0 || babylonTexture.vOffset !== 0) {\r\n textureTransform.offset = [babylonTexture.uOffset, babylonTexture.vOffset];\r\n transformIsRequired = true;\r\n }\r\n\r\n if (babylonTexture.uScale !== 1 || babylonTexture.vScale !== 1) {\r\n textureTransform.scale = [babylonTexture.uScale, babylonTexture.vScale];\r\n transformIsRequired = true;\r\n }\r\n\r\n if (babylonTexture.wAng !== 0) {\r\n if (babylonTexture.uRotationCenter !== 0 || babylonTexture.vRotationCenter !== 0) {\r\n if (babylonTexture.uScale !== 1 || babylonTexture.vScale !== 1) {\r\n Tools.Warn(`${context}: Texture ${babylonTexture.name} with scaling and a rotation not centered at the origin cannot be exported with ${NAME}`);\r\n return;\r\n }\r\n Tools.Warn(`${context}: Texture ${babylonTexture.name} with rotation not centered at the origin will be exported with an adjusted texture offset for ${NAME}.`);\r\n textureTransform.offset = AdjustOffsetForRotationCenter(babylonTexture);\r\n }\r\n textureTransform.rotation = -babylonTexture.wAng;\r\n transformIsRequired = true;\r\n }\r\n\r\n if (babylonTexture.coordinatesIndex !== 0) {\r\n textureTransform.texCoord = babylonTexture.coordinatesIndex;\r\n transformIsRequired = true;\r\n }\r\n\r\n if (!transformIsRequired) {\r\n return;\r\n }\r\n\r\n this._wasUsed = true;\r\n if (!textureInfo.extensions) {\r\n textureInfo.extensions = {};\r\n }\r\n textureInfo.extensions[NAME] = textureTransform;\r\n }\r\n}\r\n\r\nGLTFExporter.RegisterExtension(NAME, () => new KHR_texture_transform());\r\n"]}
@@ -91,10 +91,15 @@ export declare class GLTFExporter {
91
91
  private _exportBuffers;
92
92
  /**
93
93
  * Processes a node to be exported to the glTF file
94
- * @returns A promise that resolves with the node index when the processing is complete, or null if the node should not be exported
94
+ * @returns A promise that resolves once the node has been exported
95
95
  * @internal
96
96
  */
97
97
  private _exportNodeAsync;
98
+ /**
99
+ * Creates a glTF node from a Babylon.js node. If skipped, returns null.
100
+ * @internal
101
+ */
102
+ private _createNodeAsync;
98
103
  private _exportIndices;
99
104
  private _exportVertexBuffer;
100
105
  private _exportMaterialAsync;
@@ -697,20 +697,12 @@ export class GLTFExporter {
697
697
  const nodes = new Array();
698
698
  this._exportBuffers(babylonRootNodes, state);
699
699
  for (const babylonNode of babylonRootNodes) {
700
- if (this._shouldExportNode(babylonNode)) {
701
- const nodeIndex = await this._exportNodeAsync(babylonNode, state);
702
- if (nodeIndex !== null) {
703
- nodes.push(nodeIndex);
704
- }
705
- }
700
+ await this._exportNodeAsync(babylonNode, nodes, state);
706
701
  }
707
702
  return nodes;
708
703
  }
709
704
  _collectBuffers(babylonNode, bufferToVertexBuffersMap, vertexBufferToMeshesMap, morphTargetsToMeshesMap, state) {
710
- if (!this._shouldExportNode(babylonNode)) {
711
- return;
712
- }
713
- if (babylonNode instanceof Mesh && babylonNode.geometry) {
705
+ if (this._shouldExportNode(babylonNode) && babylonNode instanceof Mesh && babylonNode.geometry) {
714
706
  const vertexBuffers = babylonNode.geometry.getVertexBuffers();
715
707
  if (vertexBuffers) {
716
708
  for (const kind in vertexBuffers) {
@@ -904,13 +896,62 @@ export class GLTFExporter {
904
896
  }
905
897
  /**
906
898
  * Processes a node to be exported to the glTF file
907
- * @returns A promise that resolves with the node index when the processing is complete, or null if the node should not be exported
899
+ * @returns A promise that resolves once the node has been exported
908
900
  * @internal
909
901
  */
910
- async _exportNodeAsync(babylonNode, state) {
902
+ async _exportNodeAsync(babylonNode, parentNodeChildren, state) {
911
903
  let nodeIndex = this._nodeMap.get(babylonNode);
912
904
  if (nodeIndex !== undefined) {
913
- return nodeIndex;
905
+ if (!parentNodeChildren.includes(nodeIndex)) {
906
+ parentNodeChildren.push(nodeIndex);
907
+ }
908
+ return;
909
+ }
910
+ const node = await this._createNodeAsync(babylonNode, state);
911
+ if (node) {
912
+ nodeIndex = this._nodes.length;
913
+ this._nodes.push(node);
914
+ this._nodeMap.set(babylonNode, nodeIndex);
915
+ state.pushExportedNode(babylonNode);
916
+ parentNodeChildren.push(nodeIndex);
917
+ // Process node's animations once the node has been added to nodeMap (TODO: This should be refactored)
918
+ const runtimeGLTFAnimation = {
919
+ name: "runtime animations",
920
+ channels: [],
921
+ samplers: [],
922
+ };
923
+ const idleGLTFAnimations = [];
924
+ if (!this._babylonScene.animationGroups.length) {
925
+ _GLTFAnimation._CreateMorphTargetAnimationFromMorphTargetAnimations(babylonNode, runtimeGLTFAnimation, idleGLTFAnimations, this._nodeMap, this._nodes, this._dataWriter, this._bufferViews, this._accessors, this._animationSampleRate, state.convertToRightHanded, this._options.shouldExportAnimation);
926
+ if (babylonNode.animations.length) {
927
+ _GLTFAnimation._CreateNodeAnimationFromNodeAnimations(babylonNode, runtimeGLTFAnimation, idleGLTFAnimations, this._nodeMap, this._nodes, this._dataWriter, this._bufferViews, this._accessors, this._animationSampleRate, state.convertToRightHanded, this._options.shouldExportAnimation);
928
+ }
929
+ }
930
+ if (runtimeGLTFAnimation.channels.length && runtimeGLTFAnimation.samplers.length) {
931
+ this._animations.push(runtimeGLTFAnimation);
932
+ }
933
+ idleGLTFAnimations.forEach((idleGLTFAnimation) => {
934
+ if (idleGLTFAnimation.channels.length && idleGLTFAnimation.samplers.length) {
935
+ this._animations.push(idleGLTFAnimation);
936
+ }
937
+ });
938
+ }
939
+ // Begin processing child nodes once parent has been added to the node list
940
+ const children = node ? [] : parentNodeChildren;
941
+ for (const babylonChildNode of babylonNode.getChildren()) {
942
+ await this._exportNodeAsync(babylonChildNode, children, state);
943
+ }
944
+ if (node && children.length) {
945
+ node.children = children;
946
+ }
947
+ }
948
+ /**
949
+ * Creates a glTF node from a Babylon.js node. If skipped, returns null.
950
+ * @internal
951
+ */
952
+ async _createNodeAsync(babylonNode, state) {
953
+ if (!this._shouldExportNode(babylonNode)) {
954
+ return null;
914
955
  }
915
956
  const node = {};
916
957
  if (babylonNode.name) {
@@ -951,57 +992,20 @@ export class GLTFExporter {
951
992
  return null; // Skip exporting this node
952
993
  }
953
994
  }
954
- else {
955
- if (state.convertToRightHanded) {
956
- ConvertToRightHandedNode(node);
957
- RotateNode180Y(node);
958
- }
959
- this._nodesCameraMap.get(gltfCamera)?.push(node);
995
+ if (state.convertToRightHanded) {
996
+ ConvertToRightHandedNode(node);
997
+ RotateNode180Y(node);
960
998
  }
999
+ this._nodesCameraMap.get(gltfCamera)?.push(node);
961
1000
  }
962
1001
  }
963
- // Apply extensions to the node. If this resolves to null, it means we should skip exporting this node (NOTE: This will also skip its children)
1002
+ // Apply extensions to the node. If this resolves to null, it means we should skip exporting this node
964
1003
  const processedNode = await this._extensionsPostExportNodeAsync("exportNodeAsync", node, babylonNode, this._nodeMap, state.convertToRightHanded);
965
1004
  if (!processedNode) {
966
1005
  Logger.Warn(`Not exporting node ${babylonNode.name}`);
967
1006
  return null;
968
1007
  }
969
- nodeIndex = this._nodes.length;
970
- this._nodes.push(node);
971
- this._nodeMap.set(babylonNode, nodeIndex);
972
- state.pushExportedNode(babylonNode);
973
- // Process node's animations once the node has been added to nodeMap (TODO: This should be refactored)
974
- const runtimeGLTFAnimation = {
975
- name: "runtime animations",
976
- channels: [],
977
- samplers: [],
978
- };
979
- const idleGLTFAnimations = [];
980
- if (!this._babylonScene.animationGroups.length) {
981
- _GLTFAnimation._CreateMorphTargetAnimationFromMorphTargetAnimations(babylonNode, runtimeGLTFAnimation, idleGLTFAnimations, this._nodeMap, this._nodes, this._dataWriter, this._bufferViews, this._accessors, this._animationSampleRate, state.convertToRightHanded, this._options.shouldExportAnimation);
982
- if (babylonNode.animations.length) {
983
- _GLTFAnimation._CreateNodeAnimationFromNodeAnimations(babylonNode, runtimeGLTFAnimation, idleGLTFAnimations, this._nodeMap, this._nodes, this._dataWriter, this._bufferViews, this._accessors, this._animationSampleRate, state.convertToRightHanded, this._options.shouldExportAnimation);
984
- }
985
- }
986
- if (runtimeGLTFAnimation.channels.length && runtimeGLTFAnimation.samplers.length) {
987
- this._animations.push(runtimeGLTFAnimation);
988
- }
989
- idleGLTFAnimations.forEach((idleGLTFAnimation) => {
990
- if (idleGLTFAnimation.channels.length && idleGLTFAnimation.samplers.length) {
991
- this._animations.push(idleGLTFAnimation);
992
- }
993
- });
994
- // Begin processing child nodes once parent has been added to the node list
995
- for (const babylonChildNode of babylonNode.getChildren()) {
996
- if (this._shouldExportNode(babylonChildNode)) {
997
- const childNodeIndex = await this._exportNodeAsync(babylonChildNode, state);
998
- if (childNodeIndex !== null) {
999
- node.children || (node.children = []);
1000
- node.children.push(childNodeIndex);
1001
- }
1002
- }
1003
- }
1004
- return nodeIndex;
1008
+ return node;
1005
1009
  }
1006
1010
  _exportIndices(indices, start, count, offset, fillMode, sideOrientation, state, primitive) {
1007
1011
  const is32Bits = AreIndices32Bits(indices, count);