@@ -104,15 +104,41 @@ private GLTFMesh ExportMesh(BabylonMesh babylonMesh, GLTF gltf, BabylonScene bab
104104 {
105105 // In babylon, the 4 bones indices are stored in a single int
106106 // Each bone index is 8-bit offset from the next
107+ ushort [ ] unpackBabylonBonesToArray ( uint babylonBoneIndices )
108+ {
109+ uint bone3 = babylonBoneIndices >> 24 ;
110+ uint bone2 = ( babylonBoneIndices << 8 ) >> 24 ;
111+ uint bone1 = ( babylonBoneIndices << 16 ) >> 24 ;
112+ uint bone0 = ( babylonBoneIndices << 24 ) >> 24 ;
113+ babylonBoneIndices -= bone0 << 0 ;
114+ return new ushort [ ] { ( ushort ) bone0 , ( ushort ) bone1 , ( ushort ) bone2 , ( ushort ) bone3 } ;
115+ }
116+
107117 uint bonesIndicesMerged = ( uint ) meshData . matricesIndices [ indexVertex ] ;
108- uint bone3 = bonesIndicesMerged >> 24 ;
109- uint bone2 = ( bonesIndicesMerged << 8 ) >> 24 ;
110- uint bone1 = ( bonesIndicesMerged << 16 ) >> 24 ;
111- uint bone0 = ( bonesIndicesMerged << 24 ) >> 24 ;
112- bonesIndicesMerged -= bone0 << 0 ;
113- var bonesIndicesArray = new ushort [ ] { ( ushort ) bone0 , ( ushort ) bone1 , ( ushort ) bone2 , ( ushort ) bone3 } ;
114- globalVertex . BonesIndices = bonesIndicesArray ;
118+ globalVertex . BonesIndices = unpackBabylonBonesToArray ( bonesIndicesMerged ) ;
115119 globalVertex . BonesWeights = ArrayExtension . SubArrayFromEntity ( meshData . matricesWeights , indexVertex , 4 ) ;
120+ void clearBoneUnusedIndices ( ushort [ ] indices , float [ ] weights )
121+ {
122+ for ( int i = 0 ; i < indices . Length ; ++ i )
123+ {
124+ // Zero out indices of unused joint weights to avoid ACCESSOR_JOINTS_USED_ZERO_WEIGHT.
125+ if ( MathUtilities . IsAlmostEqualTo ( weights [ i ] , 0 , float . Epsilon ) )
126+ {
127+ indices [ i ] = 0 ;
128+ }
129+ }
130+ }
131+
132+ clearBoneUnusedIndices ( globalVertex . BonesIndices , globalVertex . BonesWeights ) ;
133+
134+ if ( hasBonesExtra )
135+ {
136+ uint bonesIndicesExtraMerged = ( uint ) meshData . matricesIndicesExtra [ indexVertex ] ;
137+ globalVertex . BonesIndicesExtra = unpackBabylonBonesToArray ( bonesIndicesExtraMerged ) ;
138+ globalVertex . BonesWeightsExtra = ArrayExtension . SubArrayFromEntity ( meshData . matricesWeightsExtra , indexVertex , 4 ) ;
139+
140+ clearBoneUnusedIndices ( globalVertex . BonesIndicesExtra , globalVertex . BonesWeightsExtra ) ;
141+ }
116142 }
117143
118144 globalVertices . Add ( globalVertex ) ;
@@ -367,6 +393,11 @@ private GLTFMesh ExportMesh(BabylonMesh babylonMesh, GLTF gltf, BabylonScene bab
367393
368394 meshPrimitive . attributes . Add ( GLTFMeshPrimitive . Attribute . JOINTS_0 . ToString ( ) , tmpGltfMeshPrimitive . attributes [ GLTFMeshPrimitive . Attribute . JOINTS_0 . ToString ( ) ] ) ;
369395 meshPrimitive . attributes . Add ( GLTFMeshPrimitive . Attribute . WEIGHTS_0 . ToString ( ) , tmpGltfMeshPrimitive . attributes [ GLTFMeshPrimitive . Attribute . WEIGHTS_0 . ToString ( ) ] ) ;
396+ if ( hasBonesExtra )
397+ {
398+ meshPrimitive . attributes . Add ( GLTFMeshPrimitive . Attribute . JOINTS_1 . ToString ( ) , tmpGltfMeshPrimitive . attributes [ GLTFMeshPrimitive . Attribute . JOINTS_1 . ToString ( ) ] ) ;
399+ meshPrimitive . attributes . Add ( GLTFMeshPrimitive . Attribute . WEIGHTS_1 . ToString ( ) , tmpGltfMeshPrimitive . attributes [ GLTFMeshPrimitive . Attribute . WEIGHTS_1 . ToString ( ) ] ) ;
400+ }
370401 sharedSkinnedMeshesByOriginal [ tmpGltfMesh ] . Add ( gltfMesh ) ;
371402 }
372403 else
@@ -387,6 +418,23 @@ private GLTFMesh ExportMesh(BabylonMesh babylonMesh, GLTF gltf, BabylonScene bab
387418 joints . ForEach ( n => accessorJoints . bytesList . AddRange ( BitConverter . GetBytes ( n ) ) ) ;
388419 accessorJoints . count = globalVerticesSubMesh . Count ;
389420
421+ if ( hasBonesExtra )
422+ {
423+ // --- Joints Extra ---
424+ var accessorJointsExtra = GLTFBufferService . Instance . CreateAccessor (
425+ gltf ,
426+ GLTFBufferService . Instance . GetBufferViewUnsignedShortVec4 ( gltf , buffer ) ,
427+ "accessorJointsExtra" ,
428+ GLTFAccessor . ComponentType . UNSIGNED_SHORT ,
429+ GLTFAccessor . TypeEnum . VEC4
430+ ) ;
431+ meshPrimitive . attributes . Add ( GLTFMeshPrimitive . Attribute . JOINTS_1 . ToString ( ) , accessorJointsExtra . index ) ;
432+ // Populate accessor
433+ List < ushort > jointsExtra = globalVerticesSubMesh . SelectMany ( v => new [ ] { v . BonesIndicesExtra [ 0 ] , v . BonesIndicesExtra [ 1 ] , v . BonesIndicesExtra [ 2 ] , v . BonesIndicesExtra [ 3 ] } ) . ToList ( ) ;
434+ jointsExtra . ForEach ( n => accessorJointsExtra . bytesList . AddRange ( BitConverter . GetBytes ( n ) ) ) ;
435+ accessorJointsExtra . count = globalVerticesSubMesh . Count ;
436+ }
437+
390438 // --- Weights ---
391439 var accessorWeights = GLTFBufferService . Instance . CreateAccessor (
392440 gltf ,
@@ -400,6 +448,23 @@ private GLTFMesh ExportMesh(BabylonMesh babylonMesh, GLTF gltf, BabylonScene bab
400448 List < float > weightBones = globalVerticesSubMesh . SelectMany ( v => new [ ] { v . BonesWeights [ 0 ] , v . BonesWeights [ 1 ] , v . BonesWeights [ 2 ] , v . BonesWeights [ 3 ] } ) . ToList ( ) ;
401449 weightBones . ForEach ( n => accessorWeights . bytesList . AddRange ( BitConverter . GetBytes ( n ) ) ) ;
402450 accessorWeights . count = globalVerticesSubMesh . Count ;
451+
452+ if ( hasBonesExtra )
453+ {
454+ // --- Weights Extra ---
455+ var accessorWeightsExtra = GLTFBufferService . Instance . CreateAccessor (
456+ gltf ,
457+ GLTFBufferService . Instance . GetBufferViewFloatVec4 ( gltf , buffer ) ,
458+ "accessorWeightsExtra" ,
459+ GLTFAccessor . ComponentType . FLOAT ,
460+ GLTFAccessor . TypeEnum . VEC4
461+ ) ;
462+ meshPrimitive . attributes . Add ( GLTFMeshPrimitive . Attribute . WEIGHTS_1 . ToString ( ) , accessorWeightsExtra . index ) ;
463+ // Populate accessor
464+ List < float > weightBonesExtra = globalVerticesSubMesh . SelectMany ( v => new [ ] { v . BonesWeightsExtra [ 0 ] , v . BonesWeightsExtra [ 1 ] , v . BonesWeightsExtra [ 2 ] , v . BonesWeightsExtra [ 3 ] } ) . ToList ( ) ;
465+ weightBonesExtra . ForEach ( n => accessorWeightsExtra . bytesList . AddRange ( BitConverter . GetBytes ( n ) ) ) ;
466+ accessorWeightsExtra . count = globalVerticesSubMesh . Count ;
467+ }
403468 }
404469 }
405470
0 commit comments