Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added applyEulerFilter to import #2942

Merged
merged 6 commits into from
Mar 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/mayaUsd/commands/baseImportCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ MSyntax MayaUSDImportCommand::createSyntax()
MSyntax::kString);
syntax.makeFlagMultiUse(kImportChaserArgsFlag);

syntax.addFlag(
kApplyEulerFilterFlag,
UsdMayaJobImportArgsTokens->applyEulerFilter.GetText(),
MSyntax::kBoolean);

// These are additional flags under our control.
syntax.addFlag(kFileFlag, kFileFlagLong, MSyntax::kString);
syntax.addFlag(kParentFlag, kParentFlagLong, MSyntax::kString);
Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/commands/baseImportCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class MAYAUSD_CORE_PUBLIC MayaUSDImportCommand : public MPxCommand
static constexpr auto kUseAsAnimationCacheFlag = "uac";
static constexpr auto kImportChaserFlag = "chr";
static constexpr auto kImportChaserArgsFlag = "cha";
static constexpr auto kApplyEulerFilterFlag = "aef";

// Short and Long forms of flags defined by this command itself:
static constexpr auto kFileFlag = "f";
Expand Down
6 changes: 6 additions & 0 deletions lib/mayaUsd/fileio/importData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ ImportData::ImportData()
, fRootPrimPath(kRootPrimPath)
, fPrimsInScopeCount(0)
, fSwitchedVariantCount(0)
, fApplyEulerFilter(false)
{
}

Expand All @@ -39,6 +40,7 @@ ImportData::ImportData(const std::string& f)
, fFilename(f)
, fPrimsInScopeCount(0)
, fSwitchedVariantCount(0)
, fApplyEulerFilter(false)
{
}

Expand Down Expand Up @@ -88,6 +90,10 @@ void ImportData::setRootPrimPath(const std::string& primPath) { fRootPrimPath =

bool ImportData::hasPopulationMask() const { return !fPopMask.IsEmpty(); }

void ImportData::setApplyEulerFilter(bool value) { fApplyEulerFilter = value; }

bool ImportData::applyEulerFilter() const { return fApplyEulerFilter; }

const UsdStagePopulationMask& ImportData::stagePopulationMask() const { return fPopMask; }

void ImportData::setStagePopulationMask(const UsdStagePopulationMask& mask) { fPopMask = mask; }
Expand Down
11 changes: 9 additions & 2 deletions lib/mayaUsd/fileio/importData.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ class MAYAUSD_CORE_PUBLIC ImportData
//! \return True if the USD population mask is not empty.
bool hasPopulationMask() const;

//! Apply euler filter to imported rotation animCurves
void setApplyEulerFilter(bool value);

//! \return True if the imported rotation curves should be euler filtered
bool applyEulerFilter() const;

//! \return The USD population mask of the stage to use for import.
const UsdStagePopulationMask& stagePopulationMask() const;

Expand Down Expand Up @@ -134,8 +140,9 @@ class MAYAUSD_CORE_PUBLIC ImportData
std::string fRootPrimPath;
std::string fFilename;

int fPrimsInScopeCount;
int fSwitchedVariantCount;
int fPrimsInScopeCount;
int fSwitchedVariantCount;
bool fApplyEulerFilter;
};

} // namespace MAYAUSD_NS_DEF
6 changes: 5 additions & 1 deletion lib/mayaUsd/fileio/jobs/jobArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,7 @@ UsdMayaJobImportArgs::UsdMayaJobImportArgs(
, useAsAnimationCache(extractBoolean(userArgs, UsdMayaJobImportArgsTokens->useAsAnimationCache))
, importWithProxyShapes(importWithProxyShapes)
, preserveTimeline(extractBoolean(userArgs, UsdMayaJobImportArgsTokens->preserveTimeline))
, applyEulerFilter(extractBoolean(userArgs, UsdMayaJobImportArgsTokens->applyEulerFilter))
, pullImportStage(extractUsdStageRefPtr(userArgs, UsdMayaJobImportArgsTokens->pullImportStage))
, timeInterval(timeInterval)
, chaserNames(extractVector<std::string>(userArgs, UsdMayaJobImportArgsTokens->chaser))
Expand Down Expand Up @@ -1169,6 +1170,7 @@ const VtDictionary& UsdMayaJobImportArgs::GetDefaultDictionary()
d[UsdMayaJobImportArgsTokens->preserveTimeline] = false;
d[UsdMayaJobExportArgsTokens->chaser] = std::vector<VtValue>();
d[UsdMayaJobExportArgsTokens->chaserArgs] = std::vector<VtValue>();
d[UsdMayaJobImportArgsTokens->applyEulerFilter] = false;

// plugInfo.json site defaults.
// The defaults dict should be correctly-typed, so enable
Expand Down Expand Up @@ -1247,6 +1249,7 @@ const VtDictionary& UsdMayaJobImportArgs::GetGuideDictionary()
d[UsdMayaJobImportArgsTokens->preserveTimeline] = _boolean;
d[UsdMayaJobExportArgsTokens->chaser] = _stringVector;
d[UsdMayaJobExportArgsTokens->chaserArgs] = _stringTripletVector;
d[UsdMayaJobImportArgsTokens->applyEulerFilter] = _boolean;
});

return d;
Expand Down Expand Up @@ -1334,7 +1337,8 @@ std::ostream& operator<<(std::ostream& out, const UsdMayaJobImportArgs& importAr
<< "timeInterval: " << importArgs.timeInterval << std::endl
<< "useAsAnimationCache: " << TfStringify(importArgs.useAsAnimationCache) << std::endl
<< "preserveTimeline: " << TfStringify(importArgs.preserveTimeline) << std::endl
tryptik marked this conversation as resolved.
Show resolved Hide resolved
<< "importWithProxyShapes: " << TfStringify(importArgs.importWithProxyShapes) << std::endl;
<< "importWithProxyShapes: " << TfStringify(importArgs.importWithProxyShapes) << std::endl
<< "applyEulerFilter: " << importArgs.applyEulerFilter << std::endl;

out << "jobContextNames (" << importArgs.jobContextNames.size() << ")" << std::endl;
for (const std::string& jobContextName : importArgs.jobContextNames) {
Expand Down
4 changes: 3 additions & 1 deletion lib/mayaUsd/fileio/jobs/jobArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ TF_DECLARE_PUBLIC_TOKENS(
(Import) \
((Unloaded, "")) \
(chaser) \
(chaserArgs)
(chaserArgs) \
(applyEulerFilter)
// clang-format on

TF_DECLARE_PUBLIC_TOKENS(
Expand Down Expand Up @@ -338,6 +339,7 @@ struct UsdMayaJobImportArgs
const bool useAsAnimationCache;
const bool importWithProxyShapes;
const bool preserveTimeline;
const bool applyEulerFilter;
const UsdStageRefPtr pullImportStage;
/// The interval over which to import animated data.
/// An empty interval (<tt>GfInterval::IsEmpty()</tt>) means that no
Expand Down
30 changes: 27 additions & 3 deletions lib/mayaUsd/fileio/translators/translatorSkel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <maya/MDGModifier.h>
#include <maya/MDagModifier.h>
#include <maya/MDoubleArray.h>
#include <maya/MEulerRotation.h>
#include <maya/MFnAnimCurve.h>
#include <maya/MFnComponentListData.h>
#include <maya/MFnDependencyNode.h>
Expand Down Expand Up @@ -214,7 +215,8 @@ bool _SetTransformAnim(
MFnDependencyNode& transformNode,
const std::vector<GfMatrix4d>& xforms,
MTimeArray& times,
const UsdMayaPrimReaderContext* context)
const UsdMayaPrimReaderContext* context,
bool applyEulerFilter)
{
if (xforms.size() != times.length()) {
TF_WARN("xforms size [%zu] != times size [%du].", xforms.size(), times.length());
Expand Down Expand Up @@ -249,6 +251,22 @@ bool _SetTransformAnim(
}
}

if (applyEulerFilter) {
MPlug rotOrder = transformNode.findPlug("rotateOrder");
MEulerRotation::RotationOrder order
= static_cast<MEulerRotation::RotationOrder>(rotOrder.asInt());

MEulerRotation last(rotates[0][0], rotates[1][0], rotates[2][0], order);
for (unsigned int i = 1; i < rotates[0].length(); ++i) {
MEulerRotation current(rotates[0][i], rotates[1][i], rotates[2][i], order);
current.setToClosestSolution(last);
rotates[0][i] = current[0];
rotates[1][i] = current[1];
rotates[2][i] = current[2];
last = current;
}
}

for (int c = 0; c < 3; ++c) {
if (!_SetAnimPlugData(
transformNode, _MayaTokens->translates[c], translates[c], times, context)
Expand Down Expand Up @@ -502,7 +520,12 @@ bool _CopyAnimFromSkel(
MFnDependencyNode skelXformDep(jointContainer, &status);
CHECK_MSTATUS_AND_RETURN(status, false);

if (!_SetTransformAnim(skelXformDep, skelLocalXforms, mayaTimes, context)) {
if (!_SetTransformAnim(
skelXformDep,
skelLocalXforms,
mayaTimes,
context,
args.GetJobArguments().applyEulerFilter)) {
return false;
}
}
Expand Down Expand Up @@ -540,7 +563,8 @@ bool _CopyAnimFromSkel(
xforms[i] = samples[i][jointIdx];
}

if (!_SetTransformAnim(jointDep, xforms, mayaTimes, context))
if (!_SetTransformAnim(
jointDep, xforms, mayaTimes, context, args.GetJobArguments().applyEulerFilter))
return false;
}
return true;
Expand Down
46 changes: 40 additions & 6 deletions lib/mayaUsd/fileio/translators/translatorXformable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
#include <maya/MFnAnimCurve.h>
#include <maya/MFnDependencyNode.h>
#include <maya/MFnTransform.h>
#include <maya/MGlobal.h>
#include <maya/MMatrix.h>
#include <maya/MObjectArray.h>
#include <maya/MPlug.h>
#include <maya/MStatus.h>
#include <maya/MString.h>
Expand Down Expand Up @@ -120,7 +122,7 @@ _getXformOpAsVec3d(const UsdGeomXformOp& xformOp, GfVec3d& value, const UsdTimeC
}

// Sets the animation curve (a knot per frame) for a given plug/attribute
static void _setAnimPlugData(
static MObject _setAnimPlugData(
MPlug plg,
std::vector<double>& value,
MTimeArray& timeArray,
Expand All @@ -144,6 +146,8 @@ static void _setAnimPlugData(
TF_RUNTIME_ERROR(
"Failed to create animation object for attribute: %s", mayaPlgName.asChar());
}

return animObj;
}

// Returns true if the array is not constant
Expand Down Expand Up @@ -172,31 +176,57 @@ static void _setMayaAttribute(
const MString& x,
const MString& y,
const MString& z,
const UsdMayaPrimReaderContext* context)
const UsdMayaPrimReaderContext* context,
bool applyEulerFilter = false)
{

// if have multiple values, and applyEulerFilter, filter the values
//
if (applyEulerFilter && opName == "rotate") {
if (xVal.size() == static_cast<size_t>(timeArray.length()) && xVal.size() == yVal.size()
&& xVal.size() == zVal.size()) {
MPlug rotOrder = depFn.findPlug("rotateOrder");
MEulerRotation::RotationOrder order
= static_cast<MEulerRotation::RotationOrder>(rotOrder.asInt());

MEulerRotation last(xVal[0], yVal[0], zVal[0], order);
for (size_t i = 1; i < xVal.size(); ++i) {
MEulerRotation current(xVal[i], yVal[i], zVal[i], order);
current.setToClosestSolution(last);
xVal[i] = current[0];
yVal[i] = current[1];
zVal[i] = current[2];
last = current;
}
}
}

MPlug plg;
if (x != "" && !xVal.empty()) {
plg = depFn.findPlug(opName + x);
if (!plg.isNull()) {
plg.setDouble(xVal[0]);
if (xVal.size() > 1 && _isArrayVarying(xVal))
if (xVal.size() > 1 && (applyEulerFilter || _isArrayVarying(xVal))) {
_setAnimPlugData(plg, xVal, timeArray, context);
}
}
}
if (y != "" && !yVal.empty()) {
plg = depFn.findPlug(opName + y);
if (!plg.isNull()) {
plg.setDouble(yVal[0]);
if (yVal.size() > 1 && _isArrayVarying(yVal))
if (yVal.size() > 1 && (applyEulerFilter || _isArrayVarying(yVal))) {
_setAnimPlugData(plg, yVal, timeArray, context);
}
}
}
if (z != "" && !zVal.empty()) {
plg = depFn.findPlug(opName + z);
if (!plg.isNull()) {
plg.setDouble(zVal[0]);
if (zVal.size() > 1 && _isArrayVarying(zVal))
if (zVal.size() > 1 && (applyEulerFilter || _isArrayVarying(zVal))) {
_setAnimPlugData(plg, zVal, timeArray, context);
}
}
}
}
Expand All @@ -218,6 +248,9 @@ static bool _pushUSDXformOpToMayaXform(
std::vector<double> zValue;
GfVec3d value;
std::vector<double> timeSamples;

bool applyEulerFilter = args.GetJobArguments().applyEulerFilter;

if (!args.GetTimeInterval().IsEmpty()) {
xformop.GetTimeSamplesInInterval(args.GetTimeInterval(), &timeSamples);
}
Expand Down Expand Up @@ -352,7 +385,8 @@ static bool _pushUSDXformOpToMayaXform(
"X",
"Y",
"Z",
context);
context,
applyEulerFilter && opName == UsdMayaXformStackTokens->rotate);
}
return true;
}
Expand Down
2 changes: 2 additions & 0 deletions plugin/adsk/plugin/importTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ MStatus UsdMayaImportTranslator::reader(
timeInterval.SetMax(theOption[1].asDouble());
} else if (argName == "primPath") {
importData.setRootPrimPath(theOption[1].asChar());
} else if (argName == "applyEulerFilter") {
importData.setApplyEulerFilter(theOption[1].asInt() != 0);
} else {
userArgs[argName] = UsdMayaUtil::ParseArgumentValue(
argName, theOption[1].asChar(), UsdMayaJobImportArgs::GetGuideDictionary());
Expand Down
1 change: 1 addition & 0 deletions test/lib/usd/translators/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ set(TEST_SCRIPT_FILES
testUsdImportSkeleton.py
testUsdImportXforms.py
testUsdImportXformAnim.py
testUsdImportEulerFilter.py
testUsdMayaAdaptor.py
testUsdMayaAdaptorGeom.py
testUsdMayaAdaptorMetadata.py
Expand Down
Loading