@@ -199,7 +199,7 @@ bool UsdMaya_ReadJob::Read(std::vector<MDagPath>* addedDagPaths)
199
199
// When we are called from PrimUpdaterManager we should already have
200
200
// a computation scope. If we are called from elsewhere don't show any
201
201
// progress bar here.
202
- MayaUsd::ProgressBarScope progressBar (17 );
202
+ MayaUsd::ProgressBarScope progressBar (16 );
203
203
204
204
// Do not use the global undo info recording system.
205
205
// The read job Undo() / redo() functions will handle all operations.
@@ -259,22 +259,6 @@ bool UsdMaya_ReadJob::Read(std::vector<MDagPath>* addedDagPaths)
259
259
_setTimeSampleMultiplierFrom (stage->GetTimeCodesPerSecond ());
260
260
progressBar.advance ();
261
261
262
- // XXX Currently all distance values are set directly from USD and will be
263
- // interpreted as centimeters (Maya's internal distance unit). Future work
264
- // could include converting distance values based on the specified meters-
265
- // per-unit in the USD stage metadata. For now, simply warn.
266
- if (UsdGeomStageHasAuthoredMetersPerUnit (stage)) {
267
- MDistance::Unit mdistanceUnit = UsdMayaUtil::ConvertUsdGeomLinearUnitToMDistanceUnit (
268
- UsdGeomGetStageMetersPerUnit (stage));
269
-
270
- if (mdistanceUnit != MDistance::internalUnit ()) {
271
- TF_WARN (" Distance unit conversion is not yet supported. "
272
- " All distance values will be imported in Maya's internal "
273
- " distance unit." );
274
- }
275
- }
276
- progressBar.advance ();
277
-
278
262
// If the import time interval isn't empty, we expand the Min/Max time
279
263
// sliders to include the stage's range if necessary.
280
264
AutoTimelineRestore timelineRestore (mArgs .preserveTimeline );
@@ -483,7 +467,7 @@ bool UsdMaya_ReadJob::Read(std::vector<MDagPath>* addedDagPaths)
483
467
}
484
468
progressBar.advance ();
485
469
486
- _ConvertUpAxis (stage);
470
+ _ConvertUpAxisAndUnits (stage);
487
471
progressBar.advance ();
488
472
489
473
UsdMayaReadUtil::mapFileHashes.clear ();
@@ -498,37 +482,39 @@ static bool getUSDUpAxisZ(const UsdStageRefPtr& stage)
498
482
return UsdGeomGetStageUpAxis (stage) == UsdGeomTokens->z ;
499
483
}
500
484
501
- void UsdMaya_ReadJob::_ConvertUpAxis (const UsdStageRefPtr& stage)
485
+ void UsdMaya_ReadJob::_ConvertUpAxisAndUnits (const UsdStageRefPtr& stage)
502
486
{
503
- // If up-axis fixing is turned off, do nothing.
504
- if (!mArgs .upAxis )
505
- return ;
506
-
507
- // If up axis are the same in Maya and USD, do nothing.
508
- const bool isMayaUpAxisZ = getMayaUpAxisZ ();
509
- const bool isUSDUpAxisUZ = getUSDUpAxisZ (stage);
510
-
511
- if (isMayaUpAxisZ == isUSDUpAxisUZ)
487
+ ConversionInfo conversion;
488
+
489
+ // Convert up-axis based if required and different between Maya and USD.
490
+ const bool convertUpAxis = mArgs .upAxis ;
491
+ conversion.isMayaUpAxisZ = getMayaUpAxisZ ();
492
+ conversion.isUSDUpAxisUZ = getUSDUpAxisZ (stage);
493
+ conversion.needUpAxisConversion
494
+ = (convertUpAxis && (conversion.isMayaUpAxisZ != conversion.isUSDUpAxisUZ ));
495
+
496
+ // Convert units if required and different between Maya and USD.
497
+ const bool convertUnits = mArgs .unit ;
498
+ conversion.mayaMetersPerUnit
499
+ = UsdMayaUtil::ConvertMDistanceUnitToUsdGeomLinearUnit (MDistance::internalUnit ());
500
+ conversion.usdMetersPerUnit = UsdGeomGetStageMetersPerUnit (stage);
501
+ conversion.needUnitsConversion
502
+ = (convertUnits && (conversion.mayaMetersPerUnit != conversion.usdMetersPerUnit ));
503
+
504
+ // If neither up-axis nor units need to change, do nothing.
505
+ if (!conversion.needUpAxisConversion && !conversion.needUnitsConversion )
512
506
return ;
513
507
514
- // Convert axis based on desired method.
515
- const bool convertYtoZ = isMayaUpAxisZ;
516
-
517
- bool success = false ;
518
-
519
508
if (mArgs .axisAndUnitMethod == UsdMayaJobImportArgsTokens->rotateScale )
520
- success = _ConvertUpAxisWithRotation (stage, convertYtoZ , false );
509
+ _ConvertUpAxisAndUnitsByModifyingData (stage, conversion , false );
521
510
else if (mArgs .axisAndUnitMethod == UsdMayaJobImportArgsTokens->addTransform )
522
- success = _ConvertUpAxisWithRotation (stage, convertYtoZ , true );
511
+ _ConvertUpAxisAndUnitsByModifyingData (stage, conversion , true );
523
512
else if (mArgs .axisAndUnitMethod == UsdMayaJobImportArgsTokens->overwritePrefs )
524
- success = _ConvertUpAxisByChangingMayPrefs (convertYtoZ );
513
+ _ConvertUpAxisAndUnitsByChangingMayaPrefs (stage, conversion );
525
514
else
526
515
TF_WARN (
527
- " Unknown method of converting the USD up axis to Maya: %s" ,
516
+ " Unknown method of converting the USD up axis and units to Maya: %s" ,
528
517
mArgs .axisAndUnitMethod .c_str ());
529
-
530
- if (success)
531
- MGlobal::displayInfo (" Mismatching axis have been converted for accurate orientation." );
532
518
}
533
519
534
520
// Construct list of top level DAG nodes.
@@ -583,27 +569,37 @@ static std::string _cleanMayaNodeName(const std::string& name)
583
569
return cleaned;
584
570
}
585
571
586
- static void
587
- _addOrignalUpAxisAttribute (const std::vector<MDagPath>& dagNodePaths, bool convertUsdYtoMayaZ)
572
+ static void _addOrignalUpAxisAttribute (const std::vector<MDagPath>& dagNodePaths, bool isUSDUpAxisZ)
588
573
{
589
- // Note: if we're converting from Y to Z, then the original up axis was Y, otherwise Z.
590
- const MString originalUpAxis = convertUsdYtoMayaZ ? " Y" : " Z" ;
574
+ const MString originalUpAxis = isUSDUpAxisZ ? " Z" : " Y" ;
591
575
const MString attrName = " OriginalUSDUpAxis" ;
592
576
for (const MDagPath& dagPath : dagNodePaths) {
593
577
MFnDependencyNode depNode (dagPath.node ());
594
578
MayaUsd::setDynamicAttribute (depNode, attrName, originalUpAxis);
595
579
}
596
580
}
597
581
598
- bool UsdMaya_ReadJob::_ConvertUpAxisWithRotation (
582
+ static void
583
+ _addOrignalUnitsAttribute (const std::vector<MDagPath>& dagNodePaths, double usdMetersPerUnit)
584
+ {
585
+ MString originalUnits;
586
+ originalUnits.set (usdMetersPerUnit);
587
+ const MString attrName = " OriginalUSDMetersPerUnit" ;
588
+ for (const MDagPath& dagPath : dagNodePaths) {
589
+ MFnDependencyNode depNode (dagPath.node ());
590
+ MayaUsd::setDynamicAttribute (depNode, attrName, originalUnits);
591
+ }
592
+ }
593
+
594
+ void UsdMaya_ReadJob::_ConvertUpAxisAndUnitsByModifyingData (
599
595
const UsdStageRefPtr& stage,
600
- bool convertUsdYtoMayaZ ,
596
+ const ConversionInfo& conversion ,
601
597
bool keepParentGroup)
602
598
{
603
599
std::vector<MDagPath> dagNodePaths
604
600
= _findAllRootDagNodePaths (mNewNodeRegistry , mMayaRootDagPath );
605
601
if (dagNodePaths.size () <= 0 )
606
- return true ;
602
+ return ;
607
603
608
604
std::vector<std::string> dagNodeNames = _convertDagPathToNames (dagNodePaths);
609
605
@@ -648,7 +644,7 @@ bool UsdMaya_ReadJob::_ConvertUpAxisWithRotation(
648
644
649
645
if (mMayaRootDagPath .node () != MObject::kNullObj ) {
650
646
static const char groupUnderParentCmdFormat[]
651
- = " string $groupName = `group -name \" %s\" -absolute -parent \" %s\" \" %s\" `;" ;
647
+ = " string $groupName = `group -name \" %s\" -absolute -parent \" %s\" \" %s\" `;\n " ;
652
648
std::string rootName = mMayaRootDagPath .fullPathName ().asChar ();
653
649
groupCmd = TfStringPrintf (
654
650
groupUnderParentCmdFormat,
@@ -657,7 +653,7 @@ bool UsdMaya_ReadJob::_ConvertUpAxisWithRotation(
657
653
rootName.c_str ());
658
654
} else {
659
655
static const char groupUnderWorldCmdFormat[]
660
- = " string $groupName = `group -name \" %s\" -absolute -world \" %s\" `;" ;
656
+ = " string $groupName = `group -name \" %s\" -absolute -world \" %s\" `;\n " ;
661
657
groupCmd = TfStringPrintf (
662
658
groupUnderWorldCmdFormat, groupName.c_str (), joinedDAGNodeNames.c_str ());
663
659
}
@@ -673,26 +669,35 @@ bool UsdMaya_ReadJob::_ConvertUpAxisWithRotation(
673
669
// - Use -pivot to make sure we are rotating relative to the origin
674
670
// (The group is positioned at the center of all sub-object, so we need to specify the
675
671
// pivot)
676
- {
672
+ if (conversion. needUpAxisConversion ) {
677
673
static const char rotationCmdFormat[]
678
- = " rotate -relative -euler -pivot 0 0 0 -forceOrderXYZ %d 0 0 $groupName;" ;
674
+ = " rotate -relative -euler -pivot 0 0 0 -forceOrderXYZ %d 0 0 $groupName;\n " ;
679
675
const int angleYtoZ = 90 ;
680
676
const int angleZtoY = -90 ;
681
677
std::string rotationCmd
682
- = TfStringPrintf (rotationCmdFormat, convertUsdYtoMayaZ ? angleYtoZ : angleZtoY);
678
+ = TfStringPrintf (rotationCmdFormat, conversion. isMayaUpAxisZ ? angleYtoZ : angleZtoY);
683
679
fullScript += rotationCmd;
684
680
}
685
681
682
+ if (conversion.needUnitsConversion ) {
683
+ static const char scalingCmdFormat[]
684
+ = " scale -relative -pivot 0 0 0 -scaleXYZ %f %f %f $groupName;\n " ;
685
+ const double usdToMayaScaling = conversion.usdMetersPerUnit / conversion.mayaMetersPerUnit ;
686
+ std::string scalingCmd = TfStringPrintf (
687
+ scalingCmdFormat, usdToMayaScaling, usdToMayaScaling, usdToMayaScaling);
688
+ fullScript += scalingCmd;
689
+ }
690
+
686
691
if (!keepParentGroup) {
687
- static const char ungroupCmdFormat[] = " ungroup -absolute \" %s\" ;" ;
692
+ static const char ungroupCmdFormat[] = " ungroup -absolute \" %s\" ;\n " ;
688
693
std::string ungroupCmd = TfStringPrintf (ungroupCmdFormat, groupName.c_str ());
689
694
fullScript += ungroupCmd;
690
695
}
691
696
692
697
if (!MGlobal::executeCommand (fullScript.c_str ())) {
693
698
MGlobal::displayWarning (" Failed to add a transform to convert the up-axis to align "
694
699
" the USD data with Maya up-axis." );
695
- return false ;
700
+ return ;
696
701
}
697
702
698
703
if (keepParentGroup) {
@@ -702,26 +707,67 @@ bool UsdMaya_ReadJob::_ConvertUpAxisWithRotation(
702
707
sel.add (groupName.c_str ());
703
708
sel.getDagPath (0 , groupDagPath);
704
709
}
705
- _addOrignalUpAxisAttribute ({ groupDagPath }, convertUsdYtoMayaZ);
710
+ if (conversion.needUpAxisConversion )
711
+ _addOrignalUpAxisAttribute ({ groupDagPath }, conversion.isUSDUpAxisUZ );
712
+ if (conversion.needUnitsConversion )
713
+ _addOrignalUnitsAttribute ({ groupDagPath }, conversion.usdMetersPerUnit );
706
714
} else {
707
- _addOrignalUpAxisAttribute (dagNodePaths, convertUsdYtoMayaZ);
715
+ if (conversion.needUpAxisConversion )
716
+ _addOrignalUpAxisAttribute (dagNodePaths, conversion.isUSDUpAxisUZ );
717
+ if (conversion.needUnitsConversion )
718
+ _addOrignalUnitsAttribute (dagNodePaths, conversion.usdMetersPerUnit );
708
719
}
709
720
710
- return true ;
721
+ MGlobal::displayInfo (
722
+ " Mismatching axis and units have been converted for accurate orientation and scale." );
711
723
}
712
724
713
- bool UsdMaya_ReadJob::_ConvertUpAxisByChangingMayPrefs (const bool convertUsdYtoMayaZ)
725
+ void UsdMaya_ReadJob::_ConvertUpAxisAndUnitsByChangingMayaPrefs (
726
+ const UsdStageRefPtr& stage,
727
+ const ConversionInfo& conversion)
714
728
{
715
- const bool rotateView = true ;
716
- const MStatus status
717
- = convertUsdYtoMayaZ ? MGlobal::setYAxisUp (rotateView) : MGlobal::setZAxisUp (rotateView);
718
- if (!status) {
719
- MGlobal::displayWarning (
720
- " Failed to change the Maya up-axis preferences to match USD data up-axis." );
721
- return false ;
729
+ bool success = true ;
730
+
731
+ // Set up-axis preferences if needed.
732
+ if (conversion.needUpAxisConversion ) {
733
+ const bool rotateView = true ;
734
+ const MStatus status = conversion.isUSDUpAxisUZ ? MGlobal::setZAxisUp (rotateView)
735
+ : MGlobal::setYAxisUp (rotateView);
736
+ if (!status) {
737
+ MGlobal::displayWarning (
738
+ " Failed to change the Maya up-axis preferences to match USD data up-axis." );
739
+ success = false ;
740
+ }
722
741
}
723
742
724
- return true ;
743
+ // Set units preferences if needed.
744
+ if (conversion.needUnitsConversion ) {
745
+ const MDistance::Unit mayaUnit
746
+ = UsdMayaUtil::ConvertUsdGeomLinearUnitToMDistanceUnit (conversion.usdMetersPerUnit );
747
+ if (mayaUnit == MDistance::kInvalid ) {
748
+ MGlobal::displayWarning (
749
+ " Unable to convert <unit> to a Maya unit. Supported units include millimeters, "
750
+ " centimeters, meters, kilometers, inches, feet, yards and miles." );
751
+ success = false ;
752
+ } else {
753
+ const MString mayaUnitText = UsdMayaUtil::ConvertMDistanceUnitToText (mayaUnit);
754
+ MString changeUnitsCmd;
755
+ changeUnitsCmd.format (" currentUnit -linear ^1s;" , mayaUnitText);
756
+
757
+ // Note: we *must* execute the units change on-idle because the import process
758
+ // saves and restores all units! If we change it now, the change would be lost.
759
+ if (!MGlobal::executeCommandOnIdle (changeUnitsCmd)) {
760
+ MGlobal::displayWarning (
761
+ " Failed to change the Maya units preferences to match USD data "
762
+ " because the units are not supported by Maya." );
763
+ success = false ;
764
+ }
765
+ }
766
+ }
767
+
768
+ if (success)
769
+ MGlobal::displayInfo (
770
+ " Changed Maya preferences to match up-axis and units from the imported USD scene." );
725
771
}
726
772
727
773
bool UsdMaya_ReadJob::DoImport (UsdPrimRange& rootRange, const UsdPrim& usdRootPrim)
0 commit comments