@@ -50,13 +50,13 @@ private List<IIGameNode> GetBones(IIGameSkin skin)
5050 /// <returns>
5151 /// All nodes needed for the skeleton hierarchy
5252 /// </returns>
53- private Dictionary < IIGameSkin , List < IIGameNode > > relevantNodesBySkin = new Dictionary < IIGameSkin , List < IIGameNode > > ( ) ;
54- private List < IIGameNode > GetSkinnedBones ( IIGameSkin skin )
53+ private Dictionary < IIGameSkin , Tuple < List < IIGameNode > , float [ ] > > relevantNodesBySkin = new Dictionary < IIGameSkin , Tuple < List < IIGameNode > , float [ ] > > ( ) ;
54+ private Tuple < List < IIGameNode > , float [ ] > GetSkinnedBones ( IIGameSkin skin )
5555 {
5656
5757 if ( skin == null )
5858 {
59- return new List < IIGameNode > ( ) ;
59+ return new Tuple < List < IIGameNode > , float [ ] > ( new List < IIGameNode > ( ) , null ) ;
6060 }
6161
6262 int logRank = 2 ;
@@ -72,14 +72,14 @@ private List<IIGameNode> GetSkinnedBones(IIGameSkin skin)
7272 if ( bones . Count == 0 )
7373 {
7474 RaiseWarning ( "Skin has no bones." , logRank ) ;
75- return new List < IIGameNode > ( ) ;
75+ return new Tuple < List < IIGameNode > , float [ ] > ( new List < IIGameNode > ( ) , null ) ;
7676 }
7777
7878 if ( bones . Contains ( null ) )
7979 {
8080 RaiseError ( "Skin has bones that are outside of the exported hierarchy." , logRank ) ;
8181 RaiseError ( "The skin cannot be exported" , logRank ) ;
82- return new List < IIGameNode > ( ) ;
82+ return new Tuple < List < IIGameNode > , float [ ] > ( new List < IIGameNode > ( ) , null ) ;
8383 }
8484
8585 List < IIGameNode > allHierarchyNodes = null ;
@@ -90,18 +90,31 @@ private List<IIGameNode> GetSkinnedBones(IIGameSkin skin)
9090 RaiseError ( $ "More than one root node for the skin. The skeleton bones need to be part of the same hierarchy.", logRank ) ;
9191 RaiseError ( $ "The skin cannot be exported", logRank ) ;
9292
93- return new List < IIGameNode > ( ) ;
93+ return new Tuple < List < IIGameNode > , float [ ] > ( new List < IIGameNode > ( ) , null ) ;
9494 }
9595
96- // Babylon format assumes skeleton root is at origin, add any additional node parents from the lowest common ancestor to the scene root to the skeleton hierarchy.
9796 allHierarchyNodes . Add ( lowestCommonAncestor ) ;
97+
98+ float [ ] rootTransformation = null ;
99+
100+ // Babylon format assumes skeleton root is at origin, add any additional node parents from the lowest common ancestor to the scene root to the skeleton hierarchy.
98101 if ( lowestCommonAncestor . NodeParent != null )
99102 {
100- do {
103+ do
104+ {
105+ // we need to check if the ancestor has the current skin as child (anywhere down the hierarchy)
106+ // in this case, we stop to stack commonAncestor and we set the root transformation Matrix as Local.
107+ if ( HasSkinAsChild ( lowestCommonAncestor . NodeParent , skin ) )
108+ {
109+ rootTransformation = lowestCommonAncestor . GetLocalTM ( 0 ) . ToArray ( ) ;
110+ break ;
111+ }
101112 lowestCommonAncestor = lowestCommonAncestor . NodeParent ;
102113 allHierarchyNodes . Add ( lowestCommonAncestor ) ;
103- } while ( lowestCommonAncestor . NodeParent != null ) ;
104- }
114+ } while ( lowestCommonAncestor . NodeParent != null ) ;
115+ }
116+
117+ rootTransformation = rootTransformation ?? lowestCommonAncestor . GetWorldTM ( 0 ) . ToArray ( ) ;
105118
106119 // starting from the root, sort the nodes by depth first (add the children before the siblings)
107120 List < IIGameNode > sorted = new List < IIGameNode > ( ) ;
@@ -133,10 +146,11 @@ private List<IIGameNode> GetSkinnedBones(IIGameSkin skin)
133146 }
134147 }
135148 }
149+ var result = new Tuple < List < IIGameNode > , float [ ] > ( sorted , rootTransformation ) ;
150+
151+ relevantNodesBySkin . Add ( skin , result ) ; // Stock the result for optimization
136152
137- relevantNodesBySkin . Add ( skin , sorted ) ; // Stock the result for optimization
138-
139- return sorted ;
153+ return result ;
140154 }
141155
142156 private IIGameNode GetLowestCommonAncestor ( List < IIGameNode > nodes , ref List < IIGameNode > allHierarchyNodes )
@@ -169,6 +183,32 @@ private IIGameNode GetLowestCommonAncestor(List<IIGameNode> nodes, ref List<IIGa
169183 return commonAncestor ;
170184 }
171185
186+ // fetch recursively the childrens to see if any of it, reference the skin.
187+ // the fetch stop at the first node passing the test.
188+ // down search is deep first.
189+ private bool HasSkinAsChild ( IIGameNode node , IIGameSkin skin )
190+ {
191+ if ( skin == null )
192+ {
193+ return false ;
194+ }
195+
196+ if ( node . IGameObject . IGameSkin != null && skin . Equals ( node . IGameObject . IGameSkin ) )
197+ {
198+ return true ;
199+ }
200+
201+ for ( var i = 0 ; i != node . ChildCount ; i ++ )
202+ {
203+ var n = node . GetNodeChild ( i ) ;
204+ if ( HasSkinAsChild ( n , skin ) ) {
205+ return true ;
206+ }
207+ }
208+ return false ;
209+ }
210+
211+
172212 private IIGameNode GetLowestCommonAncestor ( IIGameNode nodeA , IIGameNode nodeB , List < IIGameNode > nodeHierarchyA = null , List < IIGameNode > nodeHierarchyB = null )
173213 {
174214 if ( nodeA == nodeB || nodeB == null ) return nodeA ;
@@ -272,7 +312,7 @@ private List<int> GetNodeIndices(IIGameSkin skin)
272312 }
273313
274314 List < int > nodeIndex = new List < int > ( ) ;
275- List < IIGameNode > revelantNodes = GetSkinnedBones ( skin ) ;
315+ List < IIGameNode > revelantNodes = GetSkinnedBones ( skin ) . Item1 ;
276316
277317 for ( int index = 0 ; index < revelantNodes . Count ; index ++ )
278318 {
@@ -316,9 +356,11 @@ private BabylonBone[] ExportBones(IIGameSkin skin)
316356 {
317357 List < BabylonBone > bones = new List < BabylonBone > ( ) ;
318358 List < int > nodeIndices = GetNodeIndices ( skin ) ;
319- List < IIGameNode > revelantNodes = GetSkinnedBones ( skin ) ;
359+ Tuple < List < IIGameNode > , float [ ] > revelantNodes = GetSkinnedBones ( skin ) ;
360+
361+ var rootMatrix = revelantNodes . Item2 ;
320362
321- foreach ( IIGameNode node in revelantNodes )
363+ foreach ( IIGameNode node in revelantNodes . Item1 )
322364 {
323365 int parentIndex = ( node . NodeParent == null ) ? - 1 : nodeIndices . IndexOf ( node . NodeParent . NodeID ) ;
324366
@@ -331,7 +373,7 @@ private BabylonBone[] ExportBones(IIGameSkin skin)
331373 name = node . Name ,
332374 index = nodeIndices . IndexOf ( node . NodeID ) ,
333375 parentBoneIndex = parentIndex ,
334- matrix = ( parentIndex == - 1 ) ? node . GetWorldTM ( 0 ) . ToArray ( ) : node . GetLocalTM ( 0 ) . ToArray ( )
376+ matrix = ( parentIndex == - 1 ) ? rootMatrix : node . GetLocalTM ( 0 ) . ToArray ( )
335377 } ;
336378
337379 // Apply unit conversion factor to meter
0 commit comments