@@ -426,6 +426,86 @@ private static bool ExportUVs(FbxMesh fbxMesh, MeshInfo mesh, int[] unmergedTria
426
426
return k > 0 ;
427
427
}
428
428
429
+ /// <summary>
430
+ /// Export the mesh's blend shapes.
431
+ /// </summary>
432
+ private bool ExportBlendShapes ( MeshInfo mesh , FbxMesh fbxMesh , FbxScene fbxScene , int [ ] unmergedTriangles )
433
+ {
434
+ var umesh = mesh . mesh ;
435
+ if ( umesh . blendShapeCount == 0 )
436
+ return false ;
437
+
438
+ var fbxBlendShape = FbxBlendShape . Create ( fbxScene , umesh . name + "_BlendShape" ) ;
439
+ fbxMesh . AddDeformer ( fbxBlendShape ) ;
440
+
441
+ var numVertices = umesh . vertexCount ;
442
+ var basePoints = umesh . vertices ;
443
+ var baseNormals = umesh . normals ;
444
+ var baseTangents = umesh . tangents ;
445
+ var deltaPoints = new Vector3 [ numVertices ] ;
446
+ var deltaNormals = new Vector3 [ numVertices ] ;
447
+ var deltaTangents = new Vector3 [ numVertices ] ;
448
+
449
+ for ( int bi = 0 ; bi < umesh . blendShapeCount ; ++ bi )
450
+ {
451
+ var bsName = umesh . GetBlendShapeName ( bi ) ;
452
+ var numFrames = umesh . GetBlendShapeFrameCount ( bi ) ;
453
+ var fbxChannel = FbxBlendShapeChannel . Create ( fbxScene , bsName ) ;
454
+ fbxBlendShape . AddBlendShapeChannel ( fbxChannel ) ;
455
+
456
+ for ( int fi = 0 ; fi < numFrames ; ++ fi )
457
+ {
458
+ var weight = umesh . GetBlendShapeFrameWeight ( bi , fi ) ;
459
+ umesh . GetBlendShapeFrameVertices ( bi , fi , deltaPoints , deltaNormals , deltaTangents ) ;
460
+
461
+ var fbxShape = FbxShape . Create ( fbxScene , "" ) ;
462
+ fbxChannel . AddTargetShape ( fbxShape , weight ) ;
463
+
464
+ // control points
465
+ fbxShape . InitControlPoints ( ControlPointToIndex . Count ( ) ) ;
466
+ for ( int vi = 0 ; vi < numVertices ; ++ vi )
467
+ {
468
+ int ni = ControlPointToIndex [ basePoints [ vi ] ] ;
469
+ var v = basePoints [ vi ] + deltaPoints [ vi ] ;
470
+ fbxShape . SetControlPointAt ( ConvertToRightHanded ( v , UnitScaleFactor ) , ni ) ;
471
+ }
472
+
473
+ // normals
474
+ if ( mesh . HasValidNormals ( ) )
475
+ {
476
+ var elemNormals = fbxShape . CreateElementNormal ( ) ;
477
+ elemNormals . SetMappingMode ( FbxLayerElement . EMappingMode . eByPolygonVertex ) ;
478
+ elemNormals . SetReferenceMode ( FbxLayerElement . EReferenceMode . eDirect ) ;
479
+ var dstNormals = elemNormals . GetDirectArray ( ) ;
480
+ dstNormals . SetCount ( unmergedTriangles . Length ) ;
481
+ for ( int ii = 0 ; ii < unmergedTriangles . Length ; ++ ii )
482
+ {
483
+ int vi = unmergedTriangles [ ii ] ;
484
+ var n = baseNormals [ vi ] + deltaNormals [ vi ] ;
485
+ dstNormals . SetAt ( ii , ConvertToRightHanded ( n ) ) ;
486
+ }
487
+ }
488
+
489
+ // tangents
490
+ if ( mesh . HasValidTangents ( ) )
491
+ {
492
+ var elemTangents = fbxShape . CreateElementTangent ( ) ;
493
+ elemTangents . SetMappingMode ( FbxLayerElement . EMappingMode . eByPolygonVertex ) ;
494
+ elemTangents . SetReferenceMode ( FbxLayerElement . EReferenceMode . eDirect ) ;
495
+ var dstTangents = elemTangents . GetDirectArray ( ) ;
496
+ dstTangents . SetCount ( unmergedTriangles . Length ) ;
497
+ for ( int ii = 0 ; ii < unmergedTriangles . Length ; ++ ii )
498
+ {
499
+ int vi = unmergedTriangles [ ii ] ;
500
+ var t = ( Vector3 ) baseTangents [ vi ] + deltaTangents [ vi ] ;
501
+ dstTangents . SetAt ( ii , ConvertToRightHanded ( t ) ) ;
502
+ }
503
+ }
504
+ }
505
+ }
506
+ return true ;
507
+ }
508
+
429
509
/// <summary>
430
510
/// Takes in a left-handed UnityEngine.Vector3 denoting a normal,
431
511
/// returns a right-handed FbxVector4.
@@ -754,6 +834,9 @@ bool ExportMesh (MeshInfo meshInfo, FbxNode fbxNode)
754
834
// Set up normals, etc.
755
835
ExportComponentAttributes ( meshInfo , fbxMesh , unmergedPolygons . ToArray ( ) ) ;
756
836
837
+ // Set up blend shapes.
838
+ ExportBlendShapes ( meshInfo , fbxMesh , fbxScene , unmergedPolygons . ToArray ( ) ) ;
839
+
757
840
// set the fbxNode containing the mesh
758
841
fbxNode . SetNodeAttribute ( fbxMesh ) ;
759
842
fbxNode . SetShadingMode ( FbxNode . EShadingMode . eWireFrame ) ;
@@ -781,31 +864,28 @@ SkinnedMeshRenderer unitySkin
781
864
Debug . Log ( string . Format ( "exporting {0} {1}" , "Skin" , fbxNode . GetName ( ) ) ) ;
782
865
783
866
784
- Dictionary < SkinnedMeshRenderer , Transform [ ] > skinnedMeshToBonesMap ;
785
- // export skeleton
786
- if ( ! ExportSkeleton ( unitySkin , fbxScene , out skinnedMeshToBonesMap ) ) {
787
- Debug . LogWarning ( "failed to export skeleton" ) ;
788
- return false ;
789
- }
790
-
791
- var meshInfo = new MeshInfo ( unitySkin . sharedMesh , unitySkin . sharedMaterials ) ;
867
+ var meshInfo = new MeshInfo ( unitySkin . sharedMesh , unitySkin . sharedMaterials ) ;
792
868
793
- // export skin mesh
794
869
FbxMesh fbxMesh = null ;
795
- if ( ExportMesh ( meshInfo , fbxNode ) ) {
796
- fbxMesh = fbxNode . GetMesh ( ) ;
870
+ if ( ExportMesh ( meshInfo , fbxNode ) )
871
+ {
872
+ fbxMesh = fbxNode . GetMesh ( ) ;
797
873
}
798
-
799
- if ( fbxMesh == null ) {
800
- Debug . LogError ( "Could not find mesh" ) ;
874
+ if ( fbxMesh == null )
875
+ {
876
+ Debug . LogError ( "Could not find mesh" ) ;
801
877
return false ;
802
878
}
803
879
804
- // bind mesh to skeleton
805
- ExportSkin ( unitySkin , meshInfo , fbxScene , fbxMesh , fbxNode ) ;
880
+ Dictionary < SkinnedMeshRenderer , Transform [ ] > skinnedMeshToBonesMap ;
881
+ // export skeleton
882
+ if ( ExportSkeleton ( unitySkin , fbxScene , out skinnedMeshToBonesMap ) ) {
883
+ // bind mesh to skeleton
884
+ ExportSkin ( unitySkin , meshInfo , fbxScene , fbxMesh , fbxNode ) ;
806
885
807
- // add bind pose
808
- ExportBindPose ( unitySkin , fbxNode , fbxScene , skinnedMeshToBonesMap ) ;
886
+ // add bind pose
887
+ ExportBindPose ( unitySkin , fbxNode , fbxScene , skinnedMeshToBonesMap ) ;
888
+ }
809
889
810
890
return true ;
811
891
}
0 commit comments