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

[maya] added euler filter for imports #450

Closed
wants to merge 1 commit into from
Closed
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
15 changes: 15 additions & 0 deletions third_party/maya/lib/usdMaya/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ pxr_test_scripts(
testenv/testUsdImportAsAssemblies.py
testenv/testUsdImportCamera.py
testenv/testUsdImportColorSets.py
testenv/testUsdImportEulerFilter.py
testenv/testUsdImportFrameRange.py
testenv/testUsdImportNestedAssemblyAnimation.py
testenv/testUsdImportRfMLight.py
Expand Down Expand Up @@ -530,6 +531,20 @@ pxr_register_test(testUsdImportColorSets
MAYA_DISABLE_CIP=1
)

pxr_install_test_dir(
SRC testenv/UsdImportEulerFilterTest
DEST testUsdImportEulerFilter
)
pxr_register_test(testUsdImportEulerFilter
CUSTOM_PYTHON "${MAYA_BASE_DIR}/bin/mayapy"
COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testUsdImportEulerFilter"
TESTENV testUsdImportEulerFilter
ENV
MAYA_PLUG_IN_PATH=${CMAKE_INSTALL_PREFIX}/third_party/maya/plugin
MAYA_SCRIPT_PATH=${CMAKE_INSTALL_PREFIX}/third_party/maya/share/usd/plugins/usdMaya/resources
MAYA_DISABLE_CIP=1
)

pxr_install_test_dir(
SRC testenv/UsdImportFrameRangeTest
DEST testUsdImportFrameRange
Expand Down
6 changes: 4 additions & 2 deletions third_party/maya/lib/usdMaya/JobArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ JobImportArgs::JobImportArgs()
useCustomFrameRange(false),
startTime(1.0),
endTime(1.0),
importWithProxyShapes(false)
importWithProxyShapes(false),
useEulerFilter(true)
{
}

Expand All @@ -174,7 +175,8 @@ operator <<(std::ostream& out, const JobImportArgs& exportArgs)
<< "useCustomFrameRange: " << _StringifyBool(exportArgs.useCustomFrameRange) << std::endl
<< "startTime: " << exportArgs.startTime << std::endl
<< "endTime: " << exportArgs.endTime << std::endl
<< "importWithProxyShapes: " << _StringifyBool(exportArgs.importWithProxyShapes) << std::endl;
<< "importWithProxyShapes: " << _StringifyBool(exportArgs.importWithProxyShapes) << std::endl
<< "useEulerFilter: " << _StringifyBool(exportArgs.useEulerFilter) << std::endl;

return out;
}
Expand Down
1 change: 1 addition & 0 deletions third_party/maya/lib/usdMaya/JobArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ struct JobImportArgs
double startTime;
double endTime;
bool importWithProxyShapes;
bool useEulerFilter;
};

PXRUSDMAYA_API
Expand Down
11 changes: 9 additions & 2 deletions third_party/maya/lib/usdMaya/primReaderArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,17 @@ PxrUsdMayaPrimReaderArgs::PxrUsdMayaPrimReaderArgs(
const bool readAnimData,
const bool useCustomFrameRange,
const double startTime,
const double endTime)
const double endTime,
const bool useEulerFilter)
:
_prim(prim),
_shadingMode(shadingMode),
_defaultMeshScheme(defaultMeshScheme),
_readAnimData(readAnimData),
_useCustomFrameRange(useCustomFrameRange),
_startTime(startTime),
_endTime(endTime)
_endTime(endTime),
_useEulerFilter(useEulerFilter)
{
}
const UsdPrim&
Expand Down Expand Up @@ -80,6 +82,11 @@ PxrUsdMayaPrimReaderArgs::GetEndTime() const
{
return _endTime;
}
const bool&
PxrUsdMayaPrimReaderArgs::GetUseEulerFilter() const
{
return _useEulerFilter;
}

PXR_NAMESPACE_CLOSE_SCOPE

7 changes: 6 additions & 1 deletion third_party/maya/lib/usdMaya/primReaderArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ class PxrUsdMayaPrimReaderArgs
const bool readAnimData,
const bool useCustomFrameRange,
const double startTime,
const double endTime);
const double endTime,
const bool useEulerFilter);

/// \brief return the usd prim that should be read.
PXRUSDMAYA_API
Expand All @@ -70,6 +71,9 @@ class PxrUsdMayaPrimReaderArgs
double GetStartTime() const;
PXRUSDMAYA_API
double GetEndTime() const;

PXRUSDMAYA_API
const bool& GetUseEulerFilter() const;

bool ShouldImportUnboundShaders() const {
// currently this is disabled.
Expand All @@ -84,6 +88,7 @@ class PxrUsdMayaPrimReaderArgs
const bool _useCustomFrameRange;
const double _startTime;
const double _endTime;
const bool _useEulerFilter;
};


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#usda 1.0
(
defaultPrim = "World"
endTimeCode = 2
startTimeCode = 0
upAxis = "Y"
)

def Xform "World" (
kind = "component"
)
{
def Xform "EulerFlips"
{
float3 xformOp:rotateXYZ.timeSamples = {
0: (0, 80, 0),
1: (0, 90, 0),
2: (0, 100, 0),
}
float3 xformOp:scale = (1.0, 1.0, 1.0)
double3 xformOp:translate = (0.0, 0.0, 0.0)
float3 xformOp:rotateXYZ:rotateOffset = (0, 0, 0)
float3 xformOp:scale = (1, 1, 1)
float3 xformOp:scale:scaleOffset = (1, 1, 1)
matrix4d xformOp:transform:shear = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) )
double3 xformOp:translate = (0, 0, 0)
float3 xformOp:translate:rotatePivot = (0, 0, 0)
float3 xformOp:translate:rotatePivotOffset = (0, 0, 0)
float3 xformOp:translate:scalePivot = (0, 0, 0)
float3 xformOp:translate:scalePivotOffset = (0, 0, 0)
uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:translate:rotatePivotOffset", "xformOp:translate:rotatePivot", "xformOp:rotateXYZ:rotateOffset", "xformOp:rotateXYZ", "!invert!xformOp:translate:rotatePivot", "xformOp:translate:scalePivotOffset", "xformOp:translate:scalePivot", "xformOp:transform:shear", "xformOp:scale:scaleOffset", "xformOp:scale", "!invert!xformOp:translate:scalePivot"]
}

def Xform "NoEulerFlips"
{
float3 xformOp:rotateXYZ.timeSamples = {
0: (0, 10, 0),
1: (0, 20, 0),
2: (0, 30, 0),
}
float3 xformOp:scale = (1.0, 1.0, 1.0)
double3 xformOp:translate = (0.0, 0.0, 0.0)
float3 xformOp:rotateXYZ:rotateOffset = (0, 0, 0)
float3 xformOp:scale = (1, 1, 1)
float3 xformOp:scale:scaleOffset = (1, 1, 1)
matrix4d xformOp:transform:shear = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) )
double3 xformOp:translate = (0, 0, 0)
float3 xformOp:translate:rotatePivot = (0, 0, 0)
float3 xformOp:translate:rotatePivotOffset = (0, 0, 0)
float3 xformOp:translate:scalePivot = (0, 0, 0)
float3 xformOp:translate:scalePivotOffset = (0, 0, 0)
uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:translate:rotatePivotOffset", "xformOp:translate:rotatePivot", "xformOp:rotateXYZ:rotateOffset", "xformOp:rotateXYZ", "!invert!xformOp:translate:rotatePivot", "xformOp:translate:scalePivotOffset", "xformOp:translate:scalePivot", "xformOp:transform:shear", "xformOp:scale:scaleOffset", "xformOp:scale", "!invert!xformOp:translate:scalePivot"]
}

def Xform "SimpleXformEulerFlips"
{
float3 xformOp:rotateXYZ.timeSamples = {
0: (0, 80, 0),
1: (0, 90, 0),
2: (0, 100, 0),
}
float3 xformOp:scale = (1.0, 1.0, 1.0)
double3 xformOp:translate = (0.0, 0.0, 0.0)
uniform token[] xformOpOrder = ["xformOp:translate", "xformOp:rotateXYZ", "xformOp:scale"]
}
}
213 changes: 213 additions & 0 deletions third_party/maya/lib/usdMaya/testenv/testUsdImportEulerFilter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
#!/pxrpythonsubst
#
# Copyright 2016 Pixar
#
# Licensed under the Apache License, Version 2.0 (the "Apache License")
# with the following modification; you may not use this file except in
# compliance with the Apache License and the following modification to it:
# Section 6. Trademarks. is deleted and replaced with:
#
# 6. Trademarks. This License does not grant permission to use the trade
# names, trademarks, service marks, or product names of the Licensor
# and its affiliates, except as required to comply with Section 4(c) of
# the License and to reproduce the content of the NOTICE file.
#
# You may obtain a copy of the Apache License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the Apache License with the above modification is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the Apache License for the specific
# language governing permissions and limitations under the Apache License.
#

from pxr import Gf

from maya import cmds
from maya.api import OpenMaya as OM
from maya.api import OpenMayaAnim as OMA
from maya import standalone

import os
import unittest


class testUsdImportEulerFilter(unittest.TestCase):

EPSILON = 1e-6

@classmethod
def setUpClass(cls):
standalone.initialize('usd')
cmds.loadPlugin('pxrUsd')

@classmethod
def tearDownClass(cls):
standalone.uninitialize()

def setUp(cls):
# Create a new file so each test case starts with a fresh state.
cmds.file(new=1, f=1)

def _GetNode(self, nodeName):
if not cmds.objExists(nodeName):
return None

selectionList = OM.MSelectionList()
selectionList.add(nodeName)
return selectionList.getDependNode(0)

def _GetMayaTransform(self, transformName):
node = self._GetNode(transformName)
if node:
return OM.MFnTransform(node)
return None

def _TestRotations(self, xformName, expectedRotations):
for timeCode in range(3):
mayaTime = OM.MTime(timeCode)
OMA.MAnimControl.setCurrentTime(mayaTime)

mayaTransform = self._GetMayaTransform(xformName)
transformationMatrix = mayaTransform.transformation()
actualRotation = [Gf.RadiansToDegrees(r) for r in transformationMatrix.rotation()]
expectedRotation = expectedRotations[timeCode]
self.assertTrue(
Gf.IsClose(
expectedRotation,
actualRotation,
self.EPSILON),
"Expected '{0}' but got '{1}' for xform {2} at t={3}".format(
expectedRotation,
actualRotation,
xformName,
timeCode))

def testImportXformNoEulerFlipsNoFilter(self):
"""
Tests that importing a USD Xform that has custom XformOps with a
a rotation not suffering from Euler flips results in the correct rotations
when imported into Maya when not using the Euler filter.
"""
usdFile = os.path.abspath('UsdImportEulerFilterTest.usda')
cmds.usdImport(
file=usdFile,
shadingMode='none',
readAnimData=True,
useEulerFilter=False)

expectedRotations = {
0: [0.0, 10.0, 0.0],
1: [0.0, 20.0, 0.0],
2: [0.0, 30.0, 0.0]}

xformName = "NoEulerFlips"
self._TestRotations(xformName, expectedRotations)

def testImportXformNoEulerFlipsWithFilter(self):
"""
Tests that importing a USD Xform that has custom XformOps with a
a rotation not suffering from Euler flips results in the correct rotations
when imported into Maya when using the Euler filter.
"""
usdFile = os.path.abspath('UsdImportEulerFilterTest.usda')
cmds.usdImport(
file=usdFile,
shadingMode='none',
readAnimData=True)

expectedRotations = {
0: [0.0, 10.0, 0.0],
1: [0.0, 20.0, 0.0],
2: [0.0, 30.0, 0.0]}

xformName = "NoEulerFlips"
self._TestRotations(xformName, expectedRotations)

def testImportXformEulerFlipsNoFilter(self):
"""
Tests that importing a USD Xform that has custom XformOps with a
a rotation suffering from Euler flips results in the correct (flipped)
rotations when imported into Maya when not using the Euler filter.
"""
usdFile = os.path.abspath('UsdImportEulerFilterTest.usda')
cmds.usdImport(
file=usdFile,
shadingMode='none',
readAnimData=True,
useEulerFilter=False)

expectedRotations = {
0: [0.0, 80.0, 0.0],
1: [0.0, 90.0, 0.0],
2: [180.0, 80.0, 180.0]}

xformName = "EulerFlips"
self._TestRotations(xformName, expectedRotations)

def testImportXformEulerFlipsWithFilter(self):
"""
Tests that importing a USD Xform that has custom XformOps with a
a rotation suffering from Euler flips results in the correct rotations
when imported into Maya when using the Euler filter.
"""
usdFile = os.path.abspath('UsdImportEulerFilterTest.usda')
cmds.usdImport(
file=usdFile,
shadingMode='none',
readAnimData=True)

expectedRotations = {
0: [0.0, 80.0, 0.0],
1: [0.0, 90.0, 0.0],
2: [0.0, 100.0, 0.0]}

xformName = "EulerFlips"
self._TestRotations(xformName, expectedRotations)


def testImportSimpleXformEulerFlipsNoFilter(self):
"""
Tests that importing a USD Xform that has simple XformOps with a
a rotation suffering from Euler flips results in the correct
rotations when imported into Maya when not using the Euler filter.
"""
usdFile = os.path.abspath('UsdImportEulerFilterTest.usda')
cmds.usdImport(
file=usdFile,
shadingMode='none',
readAnimData=True,
useEulerFilter=False)

expectedRotations = {
0: [0.0, 80.0, 0.0],
1: [0.0, 90.0, 0.0],
2: [0.0, 100.0, 0.0]}

xformName = "SimpleXformEulerFlips"
self._TestRotations(xformName, expectedRotations)

def testImportSimpleXformEulerFlipsWithFilter(self):
"""
Tests that importing a USD Xform that has simple XformOps with a
a rotation suffering from Euler flips results in the correct rotations
when imported into Maya when using the Euler filter.
"""
usdFile = os.path.abspath('UsdImportEulerFilterTest.usda')
cmds.usdImport(
file=usdFile,
shadingMode='none',
readAnimData=True)

expectedRotations = {
0: [0.0, 80.0, 0.0],
1: [0.0, 90.0, 0.0],
2: [0.0, 100.0, 0.0]}

xformName = "SimpleXformEulerFlips"
self._TestRotations(xformName, expectedRotations)

if __name__ == '__main__':
unittest.main(verbosity=2)
Loading