@@ -329,7 +329,7 @@ private bool ExportComponentAttributes (MeshInfo mesh, FbxMesh fbxMesh, int[] un
329
329
330
330
for ( int n = 0 ; n < unmergedTriangles . Length ; n ++ ) {
331
331
int unityTriangle = unmergedTriangles [ n ] ;
332
- fbxElementArray . Add ( ConvertToRightHanded ( mesh . Normals [ unityTriangle ] ) ) ;
332
+ fbxElementArray . Add ( ConvertToFbxVector4 ( mesh . Normals [ unityTriangle ] ) ) ;
333
333
}
334
334
335
335
fbxLayer . SetNormals ( fbxLayerElement ) ;
@@ -348,7 +348,7 @@ private bool ExportComponentAttributes (MeshInfo mesh, FbxMesh fbxMesh, int[] un
348
348
349
349
for ( int n = 0 ; n < unmergedTriangles . Length ; n ++ ) {
350
350
int unityTriangle = unmergedTriangles [ n ] ;
351
- fbxElementArray . Add ( ConvertToRightHanded ( mesh . Binormals [ unityTriangle ] ) ) ;
351
+ fbxElementArray . Add ( ConvertToFbxVector4 ( mesh . Binormals [ unityTriangle ] ) ) ;
352
352
}
353
353
fbxLayer . SetBinormals ( fbxLayerElement ) ;
354
354
}
@@ -366,7 +366,7 @@ private bool ExportComponentAttributes (MeshInfo mesh, FbxMesh fbxMesh, int[] un
366
366
367
367
for ( int n = 0 ; n < unmergedTriangles . Length ; n ++ ) {
368
368
int unityTriangle = unmergedTriangles [ n ] ;
369
- fbxElementArray . Add ( ConvertToRightHanded (
369
+ fbxElementArray . Add ( ConvertToFbxVector4 (
370
370
new Vector3 (
371
371
mesh . Tangents [ unityTriangle ] [ 0 ] ,
372
372
mesh . Tangents [ unityTriangle ] [ 1 ] ,
@@ -507,7 +507,7 @@ private bool ExportBlendShapes(MeshInfo mesh, FbxMesh fbxMesh, FbxScene fbxScene
507
507
{
508
508
int ni = ControlPointToIndex [ basePoints [ vi ] ] ;
509
509
var v = basePoints [ vi ] + deltaPoints [ vi ] ;
510
- fbxShape . SetControlPointAt ( ConvertToRightHanded ( v , UnitScaleFactor ) , ni ) ;
510
+ fbxShape . SetControlPointAt ( ConvertToFbxVector4 ( v , UnitScaleFactor ) , ni ) ;
511
511
}
512
512
513
513
// normals
@@ -522,7 +522,7 @@ private bool ExportBlendShapes(MeshInfo mesh, FbxMesh fbxMesh, FbxScene fbxScene
522
522
{
523
523
int vi = unmergedTriangles [ ii ] ;
524
524
var n = baseNormals [ vi ] + deltaNormals [ vi ] ;
525
- dstNormals . SetAt ( ii , ConvertToRightHanded ( n ) ) ;
525
+ dstNormals . SetAt ( ii , ConvertToFbxVector4 ( n ) ) ;
526
526
}
527
527
}
528
528
@@ -538,7 +538,7 @@ private bool ExportBlendShapes(MeshInfo mesh, FbxMesh fbxMesh, FbxScene fbxScene
538
538
{
539
539
int vi = unmergedTriangles [ ii ] ;
540
540
var t = ( Vector3 ) baseTangents [ vi ] + deltaTangents [ vi ] ;
541
- dstTangents . SetAt ( ii , ConvertToRightHanded ( t ) ) ;
541
+ dstTangents . SetAt ( ii , ConvertToFbxVector4 ( t ) ) ;
542
542
}
543
543
}
544
544
}
@@ -555,11 +555,11 @@ private bool ExportBlendShapes(MeshInfo mesh, FbxMesh fbxMesh, FbxScene fbxScene
555
555
///
556
556
/// Remember you also need to flip the winding order on your polygons.
557
557
/// </summary>
558
- internal static FbxVector4 ConvertToRightHanded ( Vector3 leftHandedVector , float unitScale = 1f )
558
+ internal static FbxVector4 ConvertToFbxVector4 ( Vector3 leftHandedVector , float unitScale = 1f )
559
559
{
560
560
// negating the x component of the vector converts it from left to right handed coordinates
561
561
return unitScale * new FbxVector4 (
562
- - leftHandedVector [ 0 ] ,
562
+ leftHandedVector [ 0 ] ,
563
563
leftHandedVector [ 1 ] ,
564
564
leftHandedVector [ 2 ] ) ;
565
565
}
@@ -813,7 +813,7 @@ bool ExportMesh (MeshInfo meshInfo, FbxNode fbxNode)
813
813
foreach ( var kvp in ControlPointToIndex ) {
814
814
var controlPoint = kvp . Key ;
815
815
var index = kvp . Value ;
816
- fbxMesh . SetControlPointAt ( ConvertToRightHanded ( controlPoint , UnitScaleFactor ) , index ) ;
816
+ fbxMesh . SetControlPointAt ( ConvertToFbxVector4 ( controlPoint , UnitScaleFactor ) , index ) ;
817
817
}
818
818
}
819
819
@@ -830,12 +830,14 @@ bool ExportMesh (MeshInfo meshInfo, FbxNode fbxNode)
830
830
case MeshTopology . Triangles :
831
831
polySize = 3 ;
832
832
// flip winding order so that Maya and Unity import it properly
833
- vertOrder = new int [ ] { 0 , 2 , 1 } ;
833
+ //vertOrder = new int[] { 0, 2, 1 };
834
+ vertOrder = new int [ ] { 0 , 1 , 2 } ;
834
835
break ;
835
836
case MeshTopology . Quads :
836
837
polySize = 4 ;
837
838
// flip winding order so that Maya and Unity import it properly
838
- vertOrder = new int [ ] { 0 , 3 , 2 , 1 } ;
839
+ //vertOrder = new int[] { 0, 3, 2, 1 };
840
+ vertOrder = new int [ ] { 0 , 1 , 2 , 3 } ;
839
841
break ;
840
842
case MeshTopology . Lines :
841
843
throw new System . NotImplementedException ( ) ;
@@ -1139,39 +1141,7 @@ private bool ExportBindPose (SkinnedMeshRenderer skinnedMesh, FbxNode fbxMeshNod
1139
1141
1140
1142
return true ;
1141
1143
}
1142
-
1143
- /// <summary>
1144
- /// Takes a Quaternion and returns a Euler with XYZ rotation order.
1145
- /// Also converts from left (Unity) to righthanded (Maya) coordinates.
1146
- ///
1147
- /// Note: Cannot simply use the FbxQuaternion.DecomposeSphericalXYZ()
1148
- /// function as this returns the angle in spherical coordinates
1149
- /// instead of Euler angles, which Maya does not import properly.
1150
- /// </summary>
1151
- /// <returns>Euler with XYZ rotation order.</returns>
1152
- internal static FbxDouble3 ConvertQuaternionToXYZEuler ( Quaternion q )
1153
- {
1154
- FbxQuaternion quat = new FbxQuaternion ( q . x , q . y , q . z , q . w ) ;
1155
- FbxAMatrix m = new FbxAMatrix ( ) ;
1156
- m . SetQ ( quat ) ;
1157
- var vector4 = m . GetR ( ) ;
1158
-
1159
- // Negate the y and z values of the rotation to convert
1160
- // from Unity to Maya coordinates (left to righthanded).
1161
- return new FbxDouble3 ( vector4 . X , - vector4 . Y , - vector4 . Z ) ;
1162
- }
1163
-
1164
- internal static FbxVector4 ConvertQuaternionToXYZEuler ( FbxQuaternion quat )
1165
- {
1166
- FbxAMatrix m = new FbxAMatrix ( ) ;
1167
- m . SetQ ( quat ) ;
1168
- var vector4 = m . GetR ( ) ;
1169
-
1170
- // Negate the y and z values of the rotation to convert
1171
- // from Unity to Maya coordinates (left to righthanded).
1172
- return new FbxVector4 ( vector4 . X , - vector4 . Y , - vector4 . Z , vector4 . W ) ;
1173
- }
1174
-
1144
+
1175
1145
internal static FbxDouble3 ToFbxDouble3 ( Vector3 v )
1176
1146
{
1177
1147
return new FbxDouble3 ( v . x , v . y , v . z ) ;
@@ -1187,13 +1157,6 @@ internal static FbxVector4 ToFbxVector4(FbxDouble3 v)
1187
1157
return new FbxVector4 ( v . X , v . Y , v . Z ) ;
1188
1158
}
1189
1159
1190
- internal static FbxDouble3 ConvertToRightHandedEuler ( Vector3 rot )
1191
- {
1192
- rot . y *= - 1 ;
1193
- rot . z *= - 1 ;
1194
- return ToFbxDouble3 ( rot ) ;
1195
- }
1196
-
1197
1160
/// <summary>
1198
1161
/// Euler to quaternion without axis conversion.
1199
1162
/// </summary>
@@ -1227,7 +1190,7 @@ internal bool ExportTransform (UnityEngine.Transform unityTransform, FbxNode fbx
1227
1190
// Fixed by exporting the rotations as eulers with XYZ rotation order.
1228
1191
// Can't just set the rotation order to ZXY on export as Maya incorrectly imports the
1229
1192
// rotation. Appears to first convert to XYZ rotation then set rotation order to ZXY.
1230
- fbxNode . SetRotationOrder ( FbxNode . EPivotSet . eSourcePivot , FbxEuler . EOrder . eOrderXYZ ) ;
1193
+ fbxNode . SetRotationOrder ( FbxNode . EPivotSet . eSourcePivot , FbxEuler . EOrder . eOrderZXY ) ;
1231
1194
1232
1195
UnityEngine . Vector3 unityTranslate ;
1233
1196
FbxDouble3 fbxRotate ;
@@ -1241,18 +1204,18 @@ internal bool ExportTransform (UnityEngine.Transform unityTransform, FbxNode fbx
1241
1204
break ;
1242
1205
case TransformExportType . Global :
1243
1206
unityTranslate = GetRecenteredTranslation ( unityTransform , newCenter ) ;
1244
- fbxRotate = ConvertQuaternionToXYZEuler ( unityTransform . rotation ) ;
1207
+ fbxRotate = ToFbxDouble3 ( unityTransform . eulerAngles ) ;
1245
1208
unityScale = unityTransform . lossyScale ;
1246
1209
break ;
1247
1210
default : /*case TransformExportType.Local*/
1248
1211
unityTranslate = unityTransform . localPosition ;
1249
- fbxRotate = ConvertQuaternionToXYZEuler ( unityTransform . localRotation ) ;
1212
+ fbxRotate = ToFbxDouble3 ( unityTransform . localEulerAngles ) ;
1250
1213
unityScale = unityTransform . localScale ;
1251
1214
break ;
1252
1215
}
1253
1216
1254
1217
// Transfer transform data from Unity to Fbx
1255
- var fbxTranslate = ConvertToRightHanded ( unityTranslate , UnitScaleFactor ) ;
1218
+ var fbxTranslate = ConvertToFbxVector4 ( unityTranslate , UnitScaleFactor ) ;
1256
1219
var fbxScale = new FbxDouble3 ( unityScale . x , unityScale . y , unityScale . z ) ;
1257
1220
1258
1221
// set the local position of fbxNode
@@ -1520,11 +1483,11 @@ private bool ExportPositionConstraint(IConstraint uniConstraint, FbxScene fbxSce
1520
1483
fbxPosConstraint . AffectY . Set ( ( uniAffectedAxes & Axis . Y ) == Axis . Y ) ;
1521
1484
fbxPosConstraint . AffectZ . Set ( ( uniAffectedAxes & Axis . Z ) == Axis . Z ) ;
1522
1485
1523
- var fbxTranslationOffset = ConvertToRightHanded ( uniPosConstraint . translationOffset , UnitScaleFactor ) ;
1486
+ var fbxTranslationOffset = ConvertToFbxVector4 ( uniPosConstraint . translationOffset , UnitScaleFactor ) ;
1524
1487
fbxPosConstraint . Translation . Set ( ToFbxDouble3 ( fbxTranslationOffset ) ) ;
1525
1488
1526
1489
// rest position is the position of the fbx node
1527
- var fbxRestTranslation = ConvertToRightHanded ( uniPosConstraint . translationAtRest , UnitScaleFactor ) ;
1490
+ var fbxRestTranslation = ConvertToFbxVector4 ( uniPosConstraint . translationAtRest , UnitScaleFactor ) ;
1528
1491
// set the local position of fbxNode
1529
1492
fbxNode . LclTranslation . Set ( ToFbxDouble3 ( fbxRestTranslation ) ) ;
1530
1493
return true ;
@@ -1553,13 +1516,12 @@ private bool ExportRotationConstraint(IConstraint uniConstraint, FbxScene fbxSce
1553
1516
1554
1517
// Not converting rotation offset to XYZ euler as it gives the incorrect result in both Maya and Unity.
1555
1518
var uniRotationOffset = uniRotConstraint . rotationOffset ;
1556
- var fbxRotationOffset = ConvertToRightHandedEuler ( uniRotationOffset ) ;
1519
+ var fbxRotationOffset = ToFbxDouble3 ( uniRotationOffset ) ;
1557
1520
1558
1521
fbxRotConstraint . Rotation . Set ( fbxRotationOffset ) ;
1559
1522
1560
1523
// rest rotation is the rotation of the fbx node
1561
- var uniRestRotationQuat = Quaternion . Euler ( uniRotConstraint . rotationAtRest ) ;
1562
- var fbxRestRotation = ConvertQuaternionToXYZEuler ( uniRestRotationQuat ) ;
1524
+ var fbxRestRotation = ToFbxDouble3 ( uniRotConstraint . rotationAtRest ) ;
1563
1525
// set the local rotation of fbxNode
1564
1526
fbxNode . LclRotation . Set ( fbxRestRotation ) ;
1565
1527
return true ;
@@ -1620,12 +1582,11 @@ private bool ExportAimConstraint(IConstraint uniConstraint, FbxScene fbxScene, F
1620
1582
fbxAimConstraint . AffectZ . Set ( ( uniAffectedAxes & Axis . Z ) == Axis . Z ) ;
1621
1583
1622
1584
var uniRotationOffset = uniAimConstraint . rotationOffset ;
1623
- var fbxRotationOffset = ConvertToRightHandedEuler ( uniRotationOffset ) ;
1585
+ var fbxRotationOffset = ToFbxDouble3 ( uniRotationOffset ) ;
1624
1586
fbxAimConstraint . RotationOffset . Set ( fbxRotationOffset ) ;
1625
1587
1626
1588
// rest rotation is the rotation of the fbx node
1627
- var uniRestRotationQuat = Quaternion . Euler ( uniAimConstraint . rotationAtRest ) ;
1628
- var fbxRestRotation = ConvertQuaternionToXYZEuler ( uniRestRotationQuat ) ;
1589
+ var fbxRestRotation = ToFbxDouble3 ( uniAimConstraint . rotationAtRest ) ;
1629
1590
// set the local rotation of fbxNode
1630
1591
fbxNode . LclRotation . Set ( fbxRestRotation ) ;
1631
1592
@@ -1652,7 +1613,7 @@ private bool ExportAimConstraint(IConstraint uniConstraint, FbxScene fbxScene, F
1652
1613
}
1653
1614
fbxAimConstraint . WorldUpType . Set ( ( int ) fbxWorldUpType ) ;
1654
1615
1655
- var uniAimVector = ConvertToRightHanded ( uniAimConstraint . aimVector ) ;
1616
+ var uniAimVector = ConvertToFbxVector4 ( uniAimConstraint . aimVector ) ;
1656
1617
fbxAimConstraint . AimVector . Set ( ToFbxDouble3 ( uniAimVector ) ) ;
1657
1618
fbxAimConstraint . UpVector . Set ( ToFbxDouble3 ( uniAimConstraint . upVector ) ) ;
1658
1619
fbxAimConstraint . WorldUpVector . Set ( ToFbxDouble3 ( uniAimConstraint . worldUpVector ) ) ;
@@ -1687,10 +1648,10 @@ private bool ExportParentConstraint(IConstraint uniConstraint, FbxScene fbxScene
1687
1648
1688
1649
fbxParentConstraint . AddConstraintSource ( uniSource . node , uniSource . weight ) ;
1689
1650
1690
- var fbxTranslationOffset = ConvertToRightHanded ( uniTranslationOffset , UnitScaleFactor ) ;
1651
+ var fbxTranslationOffset = ConvertToFbxVector4 ( uniTranslationOffset , UnitScaleFactor ) ;
1691
1652
fbxParentConstraint . SetTranslationOffset ( uniSource . node , fbxTranslationOffset ) ;
1692
1653
1693
- var fbxRotationOffset = ToFbxVector4 ( ConvertToRightHandedEuler ( uniRotationOffset ) ) ;
1654
+ var fbxRotationOffset = ToFbxVector4 ( ToFbxDouble3 ( uniRotationOffset ) ) ;
1694
1655
fbxParentConstraint . SetRotationOffset ( uniSource . node , fbxRotationOffset ) ;
1695
1656
}
1696
1657
ExportCommonConstraintProperties ( uniParentConstraint , fbxParentConstraint , fbxNode ) ;
@@ -1706,13 +1667,12 @@ private bool ExportParentConstraint(IConstraint uniConstraint, FbxScene fbxScene
1706
1667
fbxParentConstraint . AffectRotationZ . Set ( ( uniRotationAxes & Axis . Z ) == Axis . Z ) ;
1707
1668
1708
1669
// rest position is the position of the fbx node
1709
- var fbxRestTranslation = ConvertToRightHanded ( uniParentConstraint . translationAtRest , UnitScaleFactor ) ;
1670
+ var fbxRestTranslation = ConvertToFbxVector4 ( uniParentConstraint . translationAtRest , UnitScaleFactor ) ;
1710
1671
// set the local position of fbxNode
1711
1672
fbxNode . LclTranslation . Set ( ToFbxDouble3 ( fbxRestTranslation ) ) ;
1712
1673
1713
1674
// rest rotation is the rotation of the fbx node
1714
- var uniRestRotationQuat = Quaternion . Euler ( uniParentConstraint . rotationAtRest ) ;
1715
- var fbxRestRotation = ConvertQuaternionToXYZEuler ( uniRestRotationQuat ) ;
1675
+ var fbxRestRotation = ToFbxDouble3 ( uniParentConstraint . rotationAtRest ) ;
1716
1676
// set the local rotation of fbxNode
1717
1677
fbxNode . LclRotation . Set ( fbxRestRotation ) ;
1718
1678
return true ;
@@ -2016,11 +1976,6 @@ public UnityToMayaConvertSceneHelper(string uniPropertyName)
2016
1976
System . StringComparison cc = System . StringComparison . CurrentCulture ;
2017
1977
2018
1978
bool partT = uniPropertyName . StartsWith ( "m_LocalPosition." , cc ) || uniPropertyName . StartsWith ( "m_TranslationOffset" , cc ) ;
2019
- bool partTx = uniPropertyName . EndsWith ( "Position.x" , cc ) || uniPropertyName . EndsWith ( "T.x" , cc ) || ( uniPropertyName . StartsWith ( "m_TranslationOffset" ) && uniPropertyName . EndsWith ( ".x" , cc ) ) ;
2020
- bool partRyz = uniPropertyName . StartsWith ( "m_RotationOffset" , cc ) && ( uniPropertyName . EndsWith ( ".y" ) || uniPropertyName . EndsWith ( ".z" ) ) ;
2021
-
2022
- convertLtoR |= partTx ;
2023
- convertLtoR |= partRyz ;
2024
1979
2025
1980
convertDistance |= partT ;
2026
1981
convertDistance |= uniPropertyName . StartsWith ( "m_Intensity" , cc ) ;
@@ -2032,9 +1987,6 @@ public UnityToMayaConvertSceneHelper(string uniPropertyName)
2032
1987
if ( convertDistance )
2033
1988
unitScaleFactor = ModelExporter . UnitScaleFactor ;
2034
1989
2035
- if ( convertLtoR )
2036
- unitScaleFactor = - unitScaleFactor ;
2037
-
2038
1990
if ( convertToRadian )
2039
1991
{
2040
1992
unitScaleFactor *= ( Mathf . PI / 180 ) ;
@@ -2891,14 +2843,14 @@ private bool ExportBoneTransform(
2891
2843
2892
2844
// Export bones with zero rotation, using a pivot instead to set the rotation
2893
2845
// so that the bones are easier to animate and the rotation shows up as the "joint orientation" in Maya.
2894
- fbxNode . LclTranslation . Set ( new FbxDouble3 ( - translation . X * UnitScaleFactor , translation . Y * UnitScaleFactor , translation . Z * UnitScaleFactor ) ) ;
2846
+ fbxNode . LclTranslation . Set ( new FbxDouble3 ( translation . X * UnitScaleFactor , translation . Y * UnitScaleFactor , translation . Z * UnitScaleFactor ) ) ;
2895
2847
fbxNode . LclRotation . Set ( new FbxDouble3 ( 0 , 0 , 0 ) ) ;
2896
2848
fbxNode . LclScaling . Set ( new FbxDouble3 ( scale . X , scale . Y , scale . Z ) ) ;
2897
2849
2898
2850
// TODO (UNI-34294): add detailed comment about why we export rotation as pre-rotation
2899
2851
fbxNode . SetRotationActive ( true ) ;
2900
2852
fbxNode . SetPivotState ( FbxNode . EPivotSet . eSourcePivot , FbxNode . EPivotState . ePivotReference ) ;
2901
- fbxNode . SetPreRotation ( FbxNode . EPivotSet . eSourcePivot , new FbxVector4 ( rotation . X , - rotation . Y , - rotation . Z ) ) ;
2853
+ fbxNode . SetPreRotation ( FbxNode . EPivotSet . eSourcePivot , new FbxVector4 ( rotation . X , rotation . Y , rotation . Z ) ) ;
2902
2854
2903
2855
return true ;
2904
2856
}
@@ -3392,7 +3344,10 @@ internal int ExportAll (
3392
3344
// The Maya axis system has Y up, Z forward, X to the left (right handed system with odd parity).
3393
3345
// We need to export right-handed for Maya because ConvertScene can't switch handedness:
3394
3346
// https://forums.autodesk.com/t5/fbx-forum/get-confused-with-fbxaxissystem-convertscene/td-p/4265472
3395
- fbxSettings . SetAxisSystem ( FbxAxisSystem . MayaYUp ) ;
3347
+ fbxSettings . SetAxisSystem ( new FbxAxisSystem (
3348
+ FbxAxisSystem . EUpVector . eYAxis ,
3349
+ ( FbxAxisSystem . EFrontVector ) ( - ( ( int ) FbxAxisSystem . EFrontVector . eParityOdd ) ) ,
3350
+ FbxAxisSystem . ECoordSystem . eLeftHanded ) ) ;
3396
3351
3397
3352
// export set of object
3398
3353
FbxNode fbxRootNode = fbxScene . GetRootNode ( ) ;
@@ -3476,6 +3431,8 @@ internal int ExportAll (
3476
3431
// Set the scene's default camera.
3477
3432
SetDefaultCamera ( fbxScene ) ;
3478
3433
3434
+ FbxAxisSystem . MayaYUp . DeepConvertScene ( fbxScene ) ;
3435
+
3479
3436
// Export the scene to the file.
3480
3437
status = fbxExporter . Export ( fbxScene ) ;
3481
3438
0 commit comments