@@ -13,7 +13,7 @@ partial class BabylonExporter
1313 // This dictionary is reset everytime a scene is exported
1414 private Dictionary < BabylonSkeleton , BabylonSkeletonExportData > alreadyExportedSkeletons = new Dictionary < BabylonSkeleton , BabylonSkeletonExportData > ( ) ;
1515
16- private GLTFSkin ExportSkin ( BabylonSkeleton babylonSkeleton , GLTF gltf , GLTFNode gltfNode )
16+ private GLTFSkin ExportSkin ( BabylonSkeleton babylonSkeleton , GLTF gltf , GLTFNode gltfNode , GLTFMesh gltfMesh )
1717 {
1818 RaiseMessage ( "GLTFExporter.Skin | Export skin of node '" + gltfNode . name + "' based on skeleton '" + babylonSkeleton . name + "'" , 2 ) ;
1919
@@ -41,97 +41,110 @@ private GLTFSkin ExportSkin(BabylonSkeleton babylonSkeleton, GLTF gltf, GLTFNode
4141 babylonBone . matrix = boneLocalMatrix . m ;
4242 }
4343 }
44- var babylonSkeletonExportData = alreadyExportedSkeletons [ babylonSkeleton ] ;
45-
46- // Skin
47- var nameSuffix = babylonSkeletonExportData . nb != 0 ? "_" + babylonSkeletonExportData . nb : "" ;
48- GLTFSkin gltfSkin = new GLTFSkin
49- {
50- name = babylonSkeleton . name + nameSuffix
51- } ;
52- gltfSkin . index = gltf . SkinsList . Count ;
53- gltf . SkinsList . Add ( gltfSkin ) ;
54- babylonSkeletonExportData . nb ++ ;
55-
56- var bones = new List < BabylonBone > ( babylonSkeleton . bones ) ;
57-
58- // Compute and store world matrix of each bone
59- var bonesWorldMatrices = new Dictionary < int , BabylonMatrix > ( ) ;
60- foreach ( var babylonBone in babylonSkeleton . bones )
61- {
62- if ( ! bonesWorldMatrices . ContainsKey ( babylonBone . index ) )
63- {
64- BabylonMatrix boneWorldMatrix = _getBoneWorldMatrix ( babylonBone , bones ) ;
65- bonesWorldMatrices . Add ( babylonBone . index , boneWorldMatrix ) ;
66- }
67- }
68-
69- // Buffer
70- var buffer = GLTFBufferService . Instance . GetBuffer ( gltf ) ;
71-
72- // Accessor - InverseBindMatrices
73- var accessorInverseBindMatrices = GLTFBufferService . Instance . CreateAccessor (
74- gltf ,
75- GLTFBufferService . Instance . GetBufferViewFloatMat4 ( gltf , buffer ) ,
76- "accessorInverseBindMatrices" ,
77- GLTFAccessor . ComponentType . FLOAT ,
78- GLTFAccessor . TypeEnum . MAT4
79- ) ;
80- gltfSkin . inverseBindMatrices = accessorInverseBindMatrices . index ;
81-
82- // World matrix of the node
83- var nodeWorldMatrix = _getNodeWorldMatrix ( gltfNode ) ;
84-
85- var gltfJoints = new List < int > ( ) ;
86-
87- foreach ( var babylonBone in babylonSkeleton . bones )
88- {
89- GLTFNode gltfBoneNode = null ;
90- if ( ! babylonSkeletonExportData . nodeByBone . ContainsKey ( babylonBone ) )
91- {
92- // Export bone as a new node
93- gltfBoneNode = _exportBone ( babylonBone , gltf , babylonSkeleton , bones ) ;
94- babylonSkeletonExportData . nodeByBone . Add ( babylonBone , gltfBoneNode ) ;
95- }
96- gltfBoneNode = babylonSkeletonExportData . nodeByBone [ babylonBone ] ;
97-
98- gltfJoints . Add ( gltfBoneNode . index ) ;
99-
100- // Set this bone as skeleton if it is a root
101- // Meaning of 'skeleton' here is the top root bone
102- if ( babylonBone . parentBoneIndex == - 1 )
103- {
104- gltfSkin . skeleton = gltfBoneNode . index ;
105- }
106-
107- // Compute inverseBindMatrice for this bone when attached to this node
108- var boneLocalMatrix = new BabylonMatrix ( ) ;
109- boneLocalMatrix . m = babylonBone . matrix ;
110- //printMatrix("boneLocalMatrix[" + babylonBone.name + "]", boneLocalMatrix);
111-
112- BabylonMatrix boneWorldMatrix = null ;
113- if ( babylonBone . parentBoneIndex == - 1 )
114- {
115- boneWorldMatrix = boneLocalMatrix ;
116- }
117- else
118- {
119- var parentWorldMatrix = bonesWorldMatrices [ babylonBone . parentBoneIndex ] ;
120- // Remove scale of parent
121- // This actually enable to take into account the scale of the bones, except for the root one
122- parentWorldMatrix = _removeScale ( parentWorldMatrix ) ;
123-
124- boneWorldMatrix = boneLocalMatrix * parentWorldMatrix ;
125- }
126- //printMatrix("boneWorldMatrix[" + babylonBone.name + "]", boneWorldMatrix);
127-
128- var inverseBindMatrices = nodeWorldMatrix * BabylonMatrix . Invert ( boneWorldMatrix ) ;
129-
130- // Populate accessor
131- List < float > matrix = new List < float > ( inverseBindMatrices . m ) ;
132- matrix . ForEach ( n => accessorInverseBindMatrices . bytesList . AddRange ( BitConverter . GetBytes ( n ) ) ) ;
133- accessorInverseBindMatrices . count ++ ;
134- }
44+ var babylonSkeletonExportData = alreadyExportedSkeletons [ babylonSkeleton ] ;
45+
46+ // Skin
47+
48+ // if this mesh is sharing a skin with another mesh, use the already exported skin
49+ var sharedSkinnedMeshesByOriginalPair = sharedSkinnedMeshesByOriginal . Where ( skinSharingMeshPair => skinSharingMeshPair . Value . Contains ( gltfMesh ) ) . Select ( kvp => ( KeyValuePair < GLTFMesh , List < GLTFMesh > > ? ) kvp ) . FirstOrDefault ( ) ;
50+ if ( sharedSkinnedMeshesByOriginalPair != null )
51+ {
52+ RaiseMessage ( "GLTFExporter.Skin | Sharing skinning information from mesh '" + sharedSkinnedMeshesByOriginalPair . Value . Key . name + "'" , 3 ) ;
53+ var skeletonExportData = alreadyExportedSkeletons [ babylonSkeleton ] ;
54+ gltfNode . skin = skeletonExportData . skinIndex ;
55+ return gltf . skins [ ( int ) gltfNode . skin ] ;
56+ }
57+
58+ // otherwise create a new GLTFSkin
59+ var nameSuffix = babylonSkeletonExportData . nb != 0 ? "_" + babylonSkeletonExportData . nb : "" ;
60+ GLTFSkin gltfSkin = new GLTFSkin
61+ {
62+ name = babylonSkeleton . name + nameSuffix
63+ } ;
64+ gltfSkin . index = gltf . SkinsList . Count ;
65+ gltf . SkinsList . Add ( gltfSkin ) ;
66+ babylonSkeletonExportData . nb ++ ;
67+ babylonSkeletonExportData . skinIndex = gltfSkin . index ;
68+
69+ var bones = new List < BabylonBone > ( babylonSkeleton . bones ) ;
70+
71+ // Compute and store world matrix of each bone
72+ var bonesWorldMatrices = new Dictionary < int , BabylonMatrix > ( ) ;
73+ foreach ( var babylonBone in babylonSkeleton . bones )
74+ {
75+ if ( ! bonesWorldMatrices . ContainsKey ( babylonBone . index ) )
76+ {
77+ BabylonMatrix boneWorldMatrix = _getBoneWorldMatrix ( babylonBone , bones ) ;
78+ bonesWorldMatrices . Add ( babylonBone . index , boneWorldMatrix ) ;
79+ }
80+ }
81+
82+ // Buffer
83+ var buffer = GLTFBufferService . Instance . GetBuffer ( gltf ) ;
84+
85+ // Accessor - InverseBindMatrices
86+ var accessorInverseBindMatrices = GLTFBufferService . Instance . CreateAccessor (
87+ gltf ,
88+ GLTFBufferService . Instance . GetBufferViewFloatMat4 ( gltf , buffer ) ,
89+ "accessorInverseBindMatrices" ,
90+ GLTFAccessor . ComponentType . FLOAT ,
91+ GLTFAccessor . TypeEnum . MAT4
92+ ) ;
93+ gltfSkin . inverseBindMatrices = accessorInverseBindMatrices . index ;
94+
95+ // World matrix of the node
96+ var nodeWorldMatrix = _getNodeWorldMatrix ( gltfNode ) ;
97+
98+ var gltfJoints = new List < int > ( ) ;
99+
100+ foreach ( var babylonBone in babylonSkeleton . bones )
101+ {
102+ GLTFNode gltfBoneNode = null ;
103+ if ( ! babylonSkeletonExportData . nodeByBone . ContainsKey ( babylonBone ) )
104+ {
105+ // Export bone as a new node
106+ gltfBoneNode = _exportBone ( babylonBone , gltf , babylonSkeleton , bones ) ;
107+ babylonSkeletonExportData . nodeByBone . Add ( babylonBone , gltfBoneNode ) ;
108+ }
109+ gltfBoneNode = babylonSkeletonExportData . nodeByBone [ babylonBone ] ;
110+
111+ gltfJoints . Add ( gltfBoneNode . index ) ;
112+
113+ // Set this bone as skeleton if it is a root
114+ // Meaning of 'skeleton' here is the top root bone
115+ if ( babylonBone . parentBoneIndex == - 1 )
116+ {
117+ gltfSkin . skeleton = gltfBoneNode . index ;
118+ }
119+
120+ // Compute inverseBindMatrice for this bone when attached to this node
121+ var boneLocalMatrix = new BabylonMatrix ( ) ;
122+ boneLocalMatrix . m = babylonBone . matrix ;
123+ //printMatrix("boneLocalMatrix[" + babylonBone.name + "]", boneLocalMatrix);
124+
125+ BabylonMatrix boneWorldMatrix = null ;
126+ if ( babylonBone . parentBoneIndex == - 1 )
127+ {
128+ boneWorldMatrix = boneLocalMatrix ;
129+ }
130+ else
131+ {
132+ var parentWorldMatrix = bonesWorldMatrices [ babylonBone . parentBoneIndex ] ;
133+ // Remove scale of parent
134+ // This actually enable to take into account the scale of the bones, except for the root one
135+ parentWorldMatrix = _removeScale ( parentWorldMatrix ) ;
136+
137+ boneWorldMatrix = boneLocalMatrix * parentWorldMatrix ;
138+ }
139+ //printMatrix("boneWorldMatrix[" + babylonBone.name + "]", boneWorldMatrix);
140+
141+ var inverseBindMatrices = nodeWorldMatrix * BabylonMatrix . Invert ( boneWorldMatrix ) ;
142+
143+ // Populate accessor
144+ List < float > matrix = new List < float > ( inverseBindMatrices . m ) ;
145+ matrix . ForEach ( n => accessorInverseBindMatrices . bytesList . AddRange ( BitConverter . GetBytes ( n ) ) ) ;
146+ accessorInverseBindMatrices . count ++ ;
147+ }
135148 gltfSkin . joints = gltfJoints . ToArray ( ) ;
136149
137150 return gltfSkin ;
@@ -261,6 +274,11 @@ private class BabylonSkeletonExportData
261274 /// </summary>
262275 public int nb = 0 ;
263276
277+ /// <summary>
278+ /// Which skin index is used for this skeleton
279+ /// </summary>
280+ public int skinIndex = - 1 ;
281+
264282 /// <summary>
265283 /// Each glTF bone is binded to a babylon bone
266284 /// </summary>
0 commit comments