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 disableSparseSamples #2815

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
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/baseExportCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,11 @@ MSyntax MayaUSDExportCommand::createSyntax()
kGeomSidednessFlag, UsdMayaJobExportArgsTokens->geomSidedness.GetText(), MSyntax::kString);

// These are additional flags under our control.
syntax.addFlag(
kDisableSparseSamples,
UsdMayaJobExportArgsTokens->disableSparseSamples.GetText(),
MSyntax::kBoolean);

syntax.addFlag(kFrameRangeFlag, kFrameRangeFlagLong, MSyntax::kDouble, MSyntax::kDouble);
syntax.addFlag(kFrameStrideFlag, kFrameStrideFlagLong, MSyntax::kDouble);
syntax.addFlag(kFrameSampleFlag, kFrameSampleFlagLong, MSyntax::kDouble);
Expand Down
1 change: 1 addition & 0 deletions lib/mayaUsd/commands/baseExportCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class MAYAUSD_CORE_PUBLIC MayaUSDExportCommand : public MPxCommand
static constexpr auto kApiSchemaFlag = "api";
static constexpr auto kJobContextFlag = "jc";
static constexpr auto kWorldspaceFlag = "wsp";
static constexpr auto kDisableSparseSamples = "dss";

// Short and Long forms of flags defined by this command itself:
static constexpr auto kAppendFlag = "a";
Expand Down
4 changes: 4 additions & 0 deletions lib/mayaUsd/fileio/jobs/jobArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,8 @@ UsdMayaJobExportArgs::UsdMayaJobExportArgs(
, jobContextNames(extractTokenSet(userArgs, UsdMayaJobExportArgsTokens->jobContext))
, chaserNames(extractVector<std::string>(userArgs, UsdMayaJobExportArgsTokens->chaser))
, allChaserArgs(_ChaserArgs(userArgs, UsdMayaJobExportArgsTokens->chaserArgs))
, disableSparseSamples(
extractBoolean(userArgs, UsdMayaJobExportArgsTokens->disableSparseSamples))
, remapUVSetsTo(_UVSetRemaps(userArgs, UsdMayaJobExportArgsTokens->remapUVSetsTo))
, melPerFrameCallback(extractString(userArgs, UsdMayaJobExportArgsTokens->melPerFrameCallback))
, melPostCallback(extractString(userArgs, UsdMayaJobExportArgsTokens->melPostCallback))
Expand Down Expand Up @@ -851,6 +853,7 @@ const VtDictionary& UsdMayaJobExportArgs::GetDefaultDictionary()
d[UsdMayaJobExportArgsTokens->staticSingleSample] = false;
d[UsdMayaJobExportArgsTokens->geomSidedness]
= UsdMayaJobExportArgsTokens->derived.GetString();
d[UsdMayaJobExportArgsTokens->disableSparseSamples] = false;

// plugInfo.json site defaults.
// The defaults dict should be correctly-typed, so enable
Expand Down Expand Up @@ -889,6 +892,7 @@ const VtDictionary& UsdMayaJobExportArgs::GetGuideDictionary()
d[UsdMayaJobExportArgsTokens->chaser] = _stringVector;
d[UsdMayaJobExportArgsTokens->chaserArgs] = _stringTripletVector;
d[UsdMayaJobExportArgsTokens->remapUVSetsTo] = _stringPairVector;
d[UsdMayaJobExportArgsTokens->disableSparseSamples] = _boolean;
d[UsdMayaJobExportArgsTokens->compatibility] = _string;
d[UsdMayaJobExportArgsTokens->defaultCameras] = _boolean;
d[UsdMayaJobExportArgsTokens->defaultMeshScheme] = _string;
Expand Down
2 changes: 2 additions & 0 deletions lib/mayaUsd/fileio/jobs/jobArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ TF_DECLARE_PUBLIC_TOKENS(
(staticSingleSample) \
(geomSidedness) \
(worldspace) \
(disableSparseSamples) \
/* Special "none" token */ \
(none) \
/* referenceObjectMode values */ \
Expand Down Expand Up @@ -230,6 +231,7 @@ struct UsdMayaJobExportArgs
using ChaserArgs = std::map<std::string, std::string>;
const std::vector<std::string> chaserNames;
const std::map<std::string, ChaserArgs> allChaserArgs;
const bool disableSparseSamples;

const std::map<std::string, std::string> remapUVSetsTo;

Expand Down
13 changes: 11 additions & 2 deletions lib/mayaUsd/fileio/primWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,11 @@ void UsdMayaPrimWriter::Write(const UsdTimeCode& usdTime)
// Currently only purpose, which is uniform, so only export at
// default time.
UsdMayaWriteUtil::WriteSchemaAttributesToPrim<UsdGeomImageable>(
GetMayaObject(), _usdPrim, { UsdGeomTokens->purpose }, usdTime, &_valueWriter);
GetMayaObject(),
_usdPrim,
{ UsdGeomTokens->purpose },
usdTime,
_GetSparseValueWriter());
}

// Write API schema attributes and strongly-typed metadata.
Expand Down Expand Up @@ -255,7 +259,12 @@ const UsdMayaJobExportArgs& UsdMayaPrimWriter::_GetExportArgs() const
return _writeJobCtx.GetArgs();
}

UsdUtilsSparseValueWriter* UsdMayaPrimWriter::_GetSparseValueWriter() { return &_valueWriter; }
UsdUtilsSparseValueWriter* UsdMayaPrimWriter::_GetSparseValueWriter()
{
if (_writeJobCtx.GetArgs().disableSparseSamples)
return nullptr;
return &_valueWriter;
}

void UsdMayaPrimWriter::MakeSingleSamplesStatic()
{
Expand Down
5 changes: 4 additions & 1 deletion lib/mayaUsd/fileio/transformWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ void UsdMayaTransformWriter::_AnimChannel::setXformOp(
} else { // float precision
vtValue = VtValue(GfVec3f(value));
}
valueWriter->SetAttribute(op.GetAttr(), vtValue, usdTime);
if (valueWriter)
valueWriter->SetAttribute(op.GetAttr(), vtValue, usdTime);
else
op.GetAttr().Set(vtValue, usdTime);
}

/* static */
Expand Down
1 change: 1 addition & 0 deletions test/lib/mayaUsd/fileio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set(TEST_SCRIPT_FILES
testImportWithNamespace.py
testJobContextRegistry.py
testDisplayLayerSaveRestore.py
testDisableSparseSamples.py

# Once of the tests in this file requires UsdMaya (from the Pixar plugin). That test
# will be skipped if not found (probably because BUILD_PXR_PLUGIN is off).
Expand Down
159 changes: 159 additions & 0 deletions test/lib/mayaUsd/fileio/testDisableSparseSamples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#!/usr/bin/env mayapy
#
# Copyright 2023 Apple
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import os
import tempfile
import unittest

import mayaUsd.lib as mayaUsdLib
import mayaUsd.ufe as mayaUsdUfe

from pxr import Plug, Usd, Sdf, Tf, UsdSkel, UsdGeom

from maya import cmds
from maya.api import OpenMaya
from maya import standalone

import fixturesUtils


def do_setup():
"""Setup the scene"""
cmds.file(f=1, new=1)

grp = cmds.createNode('transform', name='root')
pcube = cmds.polyCube()
cmds.parent(pcube[0], grp)
cmds.select( d=True )

cmds.select(grp)
joint_a = cmds.joint()
joint_a = cmds.joint( p=(0, 0, 0))
cmds.joint( p=(0, 4, 0))

cmds.skinCluster(joint_a, pcube[0], tsb=1, mi=1)

cmds.setKeyframe("joint2.sx", t=0.0, v=0.0)
cmds.setKeyframe("joint2.sx", t=100.0, v=1.0)
cmds.keyTangent("joint2.sx", wt=1)
cmds.keyTangent("joint2.sx", e=1, index=(0,), itt='linear', ott='linear')
cmds.keyTangent("joint2.sx", e=1, index=(1,), itt='auto', ott='auto')

psphere = cmds.polySphere()
cmds.setKeyframe(psphere[0]+".sx", t=0.0, v=0.0)
cmds.setKeyframe(psphere[0]+".sx", t=100.0, v=1.0)
cmds.keyTangent(psphere[0]+".sx", wt=1)
cmds.keyTangent(psphere[0]+".sx", e=1, index=(0,), itt='linear', ott='linear')
cmds.keyTangent(psphere[0]+".sx", e=1, index=(1,), itt='auto', ott='auto')




class TestSparseSampler(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.input_path = fixturesUtils.setUpClass(__file__)
cls.temp_dir = os.path.abspath('.')


do_setup()

cls.usd_file_sparse = os.path.join(cls.input_path, 'sparse_samples.usda')
export_kwargs = export_kwargs = {
"file": cls.usd_file_sparse,
"selection" : False,
"exportDisplayColor": True,
"materialsScopeName": "Looks",
"mergeTransformAndShape": True,
"shadingMode": "useRegistry",
"defaultMeshScheme": "none",
"exportSkin": "auto",
"exportSkels": "auto",
"frameRange": [70, 99]
}

cmds.mayaUSDExport(**export_kwargs)
cls.sparse_stage = Usd.Stage.Open(cls.usd_file_sparse)


cls.usd_file_not_sparse = os.path.join(cls.input_path, 'no_sparse_samples.usda')
export_kwargs['file'] = cls.usd_file_not_sparse
export_kwargs['disableSparseSamples'] = True

cmds.mayaUSDExport(**export_kwargs)
cls.not_sparse_stage = Usd.Stage.Open(cls.usd_file_not_sparse)


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

# this test disabled as it will fail.
def _test_with_sparse_samples_joint(self):
"""Check for duplicate values in the sample data in joint_attr[1]

This test fails, indicating that the SparseValueWriter has written 2 samples at the same value which causes jitter in the
output animation. This test should be re-enabled if SparseValueWriter is fixed.

"""
skel_anim = UsdSkel.Animation.Get(self.sparse_stage, '/root/joint1/Animation')

scales_attr = skel_anim.GetScalesAttr()
samples = scales_attr.GetTimeSamples()
for i in range(len(samples)-1):
prev = scales_attr.Get(samples[i])
nxt = scales_attr.Get(samples[i+1])
# this indicates duplicate values
self.assertNotAlmostEqual(prev[1][0], nxt[1][0])

def test_with_sparse_samples_xform(self):
"""Check the same animation values on an xform"""
prim = self.sparse_stage.GetPrimAtPath('/pSphere1')
xform = UsdGeom.Xformable(prim)
scale_op = [x for x in xform.GetOrderedXformOps() if x.GetOpType() == UsdGeom.XformOp.TypeScale][0]
samples = scale_op.GetTimeSamples()
for i in range(len(samples)-1):
prev = scale_op.Get(samples[i])
nxt = scale_op.Get(samples[i+1])
self.assertNotAlmostEqual(prev[0], nxt[0])

def test_without_sparse_samples_joint(self):
"""Check for duplicate values in the sample data in joint_attr[1]"""

skel_anim = UsdSkel.Animation.Get(self.not_sparse_stage, '/root/joint1/Animation')

scales_attr = skel_anim.GetScalesAttr()
samples = scales_attr.GetTimeSamples()
for i in range(len(samples)-1):
prev = scales_attr.Get(samples[i])
nxt = scales_attr.Get(samples[i+1])
self.assertNotAlmostEqual(prev[1][0], nxt[1][0])

def test_without_sparse_samples_xform(self):
"""Check the same animation values on an xform"""
prim = self.not_sparse_stage.GetPrimAtPath('/pSphere1')
xform = UsdGeom.Xformable(prim)
scale_op = [x for x in xform.GetOrderedXformOps() if x.GetOpType() == UsdGeom.XformOp.TypeScale][0]
samples = scale_op.GetTimeSamples()
for i in range(len(samples)-1):
prev = scale_op.Get(samples[i])
nxt = scale_op.Get(samples[i+1])
self.assertNotAlmostEqual(prev[0], nxt[0])

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