@@ -199,7 +199,7 @@ bool UsdMaya_ReadJob::Read(std::vector<MDagPath>* addedDagPaths)
199199 // When we are called from PrimUpdaterManager we should already have
200200 // a computation scope. If we are called from elsewhere don't show any
201201 // progress bar here.
202- MayaUsd::ProgressBarScope progressBar (17 );
202+ MayaUsd::ProgressBarScope progressBar (16 );
203203
204204 // Do not use the global undo info recording system.
205205 // The read job Undo() / redo() functions will handle all operations.
@@ -259,22 +259,6 @@ bool UsdMaya_ReadJob::Read(std::vector<MDagPath>* addedDagPaths)
259259 _setTimeSampleMultiplierFrom (stage->GetTimeCodesPerSecond ());
260260 progressBar.advance ();
261261
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-
278262 // If the import time interval isn't empty, we expand the Min/Max time
279263 // sliders to include the stage's range if necessary.
280264 AutoTimelineRestore timelineRestore (mArgs .preserveTimeline );
@@ -483,7 +467,7 @@ bool UsdMaya_ReadJob::Read(std::vector<MDagPath>* addedDagPaths)
483467 }
484468 progressBar.advance ();
485469
486- _ConvertUpAxis (stage);
470+ _ConvertUpAxisAndUnits (stage);
487471 progressBar.advance ();
488472
489473 UsdMayaReadUtil::mapFileHashes.clear ();
@@ -498,37 +482,39 @@ static bool getUSDUpAxisZ(const UsdStageRefPtr& stage)
498482 return UsdGeomGetStageUpAxis (stage) == UsdGeomTokens->z ;
499483}
500484
501- void UsdMaya_ReadJob::_ConvertUpAxis (const UsdStageRefPtr& stage)
485+ void UsdMaya_ReadJob::_ConvertUpAxisAndUnits (const UsdStageRefPtr& stage)
502486{
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 )
512506 return ;
513507
514- // Convert axis based on desired method.
515- const bool convertYtoZ = isMayaUpAxisZ;
516-
517- bool success = false ;
518-
519508 if (mArgs .axisAndUnitMethod == UsdMayaJobImportArgsTokens->rotateScale )
520- success = _ConvertUpAxisWithRotation (stage, convertYtoZ , false );
509+ _ConvertUpAxisAndUnitsByModifyingData (stage, conversion , false );
521510 else if (mArgs .axisAndUnitMethod == UsdMayaJobImportArgsTokens->addTransform )
522- success = _ConvertUpAxisWithRotation (stage, convertYtoZ , true );
511+ _ConvertUpAxisAndUnitsByModifyingData (stage, conversion , true );
523512 else if (mArgs .axisAndUnitMethod == UsdMayaJobImportArgsTokens->overwritePrefs )
524- success = _ConvertUpAxisByChangingMayPrefs (convertYtoZ );
513+ _ConvertUpAxisAndUnitsByChangingMayaPrefs (stage, conversion );
525514 else
526515 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" ,
528517 mArgs .axisAndUnitMethod .c_str ());
529-
530- if (success)
531- MGlobal::displayInfo (" Mismatching axis have been converted for accurate orientation." );
532518}
533519
534520// Construct list of top level DAG nodes.
@@ -583,27 +569,37 @@ static std::string _cleanMayaNodeName(const std::string& name)
583569 return cleaned;
584570}
585571
586- static void
587- _addOrignalUpAxisAttribute (const std::vector<MDagPath>& dagNodePaths, bool convertUsdYtoMayaZ)
572+ static void _addOrignalUpAxisAttribute (const std::vector<MDagPath>& dagNodePaths, bool isUSDUpAxisZ)
588573{
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" ;
591575 const MString attrName = " OriginalUSDUpAxis" ;
592576 for (const MDagPath& dagPath : dagNodePaths) {
593577 MFnDependencyNode depNode (dagPath.node ());
594578 MayaUsd::setDynamicAttribute (depNode, attrName, originalUpAxis);
595579 }
596580}
597581
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 (
599595 const UsdStageRefPtr& stage,
600- bool convertUsdYtoMayaZ ,
596+ const ConversionInfo& conversion ,
601597 bool keepParentGroup)
602598{
603599 std::vector<MDagPath> dagNodePaths
604600 = _findAllRootDagNodePaths (mNewNodeRegistry , mMayaRootDagPath );
605601 if (dagNodePaths.size () <= 0 )
606- return true ;
602+ return ;
607603
608604 std::vector<std::string> dagNodeNames = _convertDagPathToNames (dagNodePaths);
609605
@@ -648,7 +644,7 @@ bool UsdMaya_ReadJob::_ConvertUpAxisWithRotation(
648644
649645 if (mMayaRootDagPath .node () != MObject::kNullObj ) {
650646 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 " ;
652648 std::string rootName = mMayaRootDagPath .fullPathName ().asChar ();
653649 groupCmd = TfStringPrintf (
654650 groupUnderParentCmdFormat,
@@ -657,7 +653,7 @@ bool UsdMaya_ReadJob::_ConvertUpAxisWithRotation(
657653 rootName.c_str ());
658654 } else {
659655 static const char groupUnderWorldCmdFormat[]
660- = " string $groupName = `group -name \" %s\" -absolute -world \" %s\" `;" ;
656+ = " string $groupName = `group -name \" %s\" -absolute -world \" %s\" `;\n " ;
661657 groupCmd = TfStringPrintf (
662658 groupUnderWorldCmdFormat, groupName.c_str (), joinedDAGNodeNames.c_str ());
663659 }
@@ -673,26 +669,35 @@ bool UsdMaya_ReadJob::_ConvertUpAxisWithRotation(
673669 // - Use -pivot to make sure we are rotating relative to the origin
674670 // (The group is positioned at the center of all sub-object, so we need to specify the
675671 // pivot)
676- {
672+ if (conversion. needUpAxisConversion ) {
677673 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 " ;
679675 const int angleYtoZ = 90 ;
680676 const int angleZtoY = -90 ;
681677 std::string rotationCmd
682- = TfStringPrintf (rotationCmdFormat, convertUsdYtoMayaZ ? angleYtoZ : angleZtoY);
678+ = TfStringPrintf (rotationCmdFormat, conversion. isMayaUpAxisZ ? angleYtoZ : angleZtoY);
683679 fullScript += rotationCmd;
684680 }
685681
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+
686691 if (!keepParentGroup) {
687- static const char ungroupCmdFormat[] = " ungroup -absolute \" %s\" ;" ;
692+ static const char ungroupCmdFormat[] = " ungroup -absolute \" %s\" ;\n " ;
688693 std::string ungroupCmd = TfStringPrintf (ungroupCmdFormat, groupName.c_str ());
689694 fullScript += ungroupCmd;
690695 }
691696
692697 if (!MGlobal::executeCommand (fullScript.c_str ())) {
693698 MGlobal::displayWarning (" Failed to add a transform to convert the up-axis to align "
694699 " the USD data with Maya up-axis." );
695- return false ;
700+ return ;
696701 }
697702
698703 if (keepParentGroup) {
@@ -702,26 +707,67 @@ bool UsdMaya_ReadJob::_ConvertUpAxisWithRotation(
702707 sel.add (groupName.c_str ());
703708 sel.getDagPath (0 , groupDagPath);
704709 }
705- _addOrignalUpAxisAttribute ({ groupDagPath }, convertUsdYtoMayaZ);
710+ if (conversion.needUpAxisConversion )
711+ _addOrignalUpAxisAttribute ({ groupDagPath }, conversion.isUSDUpAxisUZ );
712+ if (conversion.needUnitsConversion )
713+ _addOrignalUnitsAttribute ({ groupDagPath }, conversion.usdMetersPerUnit );
706714 } else {
707- _addOrignalUpAxisAttribute (dagNodePaths, convertUsdYtoMayaZ);
715+ if (conversion.needUpAxisConversion )
716+ _addOrignalUpAxisAttribute (dagNodePaths, conversion.isUSDUpAxisUZ );
717+ if (conversion.needUnitsConversion )
718+ _addOrignalUnitsAttribute (dagNodePaths, conversion.usdMetersPerUnit );
708719 }
709720
710- return true ;
721+ MGlobal::displayInfo (
722+ " Mismatching axis and units have been converted for accurate orientation and scale." );
711723}
712724
713- bool UsdMaya_ReadJob::_ConvertUpAxisByChangingMayPrefs (const bool convertUsdYtoMayaZ)
725+ void UsdMaya_ReadJob::_ConvertUpAxisAndUnitsByChangingMayaPrefs (
726+ const UsdStageRefPtr& stage,
727+ const ConversionInfo& conversion)
714728{
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+ }
722741 }
723742
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." );
725771}
726772
727773bool UsdMaya_ReadJob::DoImport (UsdPrimRange& rootRange, const UsdPrim& usdRootPrim)
0 commit comments