Skip to content

Commit 3eb83cb

Browse files
roggiezhang-nvmeshula
authored andcommitted
NVIDIA: Defensive check for UsdSkel_SkelAnimationQueryImp to avoid crash
Removing animation prim with visiblity update to UsdSkelRoot may cause a crash. Closes PixarAnimationStudios#3544 (Internal change: 2369232)
1 parent 54db6bf commit 3eb83cb

File tree

4 files changed

+142
-5
lines changed

4 files changed

+142
-5
lines changed

pxr/usd/usdSkel/animQueryImpl.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ class UsdSkel_SkelAnimationQueryImpl : public UsdSkel_AnimQueryImpl
7373
bool BlendShapeWeightsMightBeTimeVarying() const override;
7474

7575
private:
76+
bool _VerifyAnimation() const {
77+
return TF_VERIFY(_anim, "PackedJointAnimation schema object is invalid.");
78+
}
79+
7680
template <typename Matrix4>
7781
bool _ComputeJointLocalTransforms(VtArray<Matrix4>* xforms,
7882
UsdTimeCode time) const;
@@ -170,6 +174,10 @@ UsdSkel_SkelAnimationQueryImpl::GetJointTransformTimeSamples(
170174
const GfInterval& interval,
171175
std::vector<double>* times) const
172176
{
177+
if (!_VerifyAnimation()) {
178+
return false;
179+
}
180+
173181
return UsdAttribute::GetUnionedTimeSamplesInInterval(
174182
{_translations.GetAttribute(),
175183
_rotations.GetAttribute(),
@@ -180,6 +188,10 @@ bool
180188
UsdSkel_SkelAnimationQueryImpl::GetJointTransformAttributes(
181189
std::vector<UsdAttribute>* attrs) const
182190
{
191+
if (!_VerifyAnimation()) {
192+
return false;
193+
}
194+
183195
attrs->push_back(_translations.GetAttribute());
184196
attrs->push_back(_rotations.GetAttribute());
185197
attrs->push_back(_scales.GetAttribute());
@@ -190,6 +202,10 @@ UsdSkel_SkelAnimationQueryImpl::GetJointTransformAttributes(
190202
bool
191203
UsdSkel_SkelAnimationQueryImpl::JointTransformsMightBeTimeVarying() const
192204
{
205+
if (!_VerifyAnimation()) {
206+
return false;
207+
}
208+
193209
return _translations.ValueMightBeTimeVarying() ||
194210
_rotations.ValueMightBeTimeVarying() ||
195211
_scales.ValueMightBeTimeVarying();
@@ -201,10 +217,10 @@ UsdSkel_SkelAnimationQueryImpl::ComputeBlendShapeWeights(
201217
VtFloatArray* weights,
202218
UsdTimeCode time) const
203219
{
204-
if (TF_VERIFY(_anim, "PackedJointAnimation schema object is invalid.")) {
205-
return _blendShapeWeights.Get(weights, time);
220+
if (!_VerifyAnimation()) {
221+
return false;
206222
}
207-
return false;
223+
return _blendShapeWeights.Get(weights, time);
208224
}
209225

210226

@@ -213,6 +229,9 @@ UsdSkel_SkelAnimationQueryImpl::GetBlendShapeWeightTimeSamples(
213229
const GfInterval& interval,
214230
std::vector<double>* times) const
215231
{
232+
if (!_VerifyAnimation()) {
233+
return false;
234+
}
216235
return _blendShapeWeights.GetTimeSamplesInInterval(interval, times);
217236
}
218237

@@ -221,13 +240,19 @@ bool
221240
UsdSkel_SkelAnimationQueryImpl::GetBlendShapeWeightAttributes(
222241
std::vector<UsdAttribute>* attrs) const
223242
{
243+
if (!_VerifyAnimation()) {
244+
return false;
245+
}
224246
attrs->push_back(_blendShapeWeights.GetAttribute());
225247
return true;
226248
}
227249

228250
bool
229251
UsdSkel_SkelAnimationQueryImpl::BlendShapeWeightsMightBeTimeVarying() const
230252
{
253+
if (!_VerifyAnimation()) {
254+
return false;
255+
}
231256
return _blendShapeWeights.ValueMightBeTimeVarying();
232257
}
233258

pxr/usdImaging/usdSkelImaging/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pxr_build_test(testUsdSkelImagingChanges
5353
LIBRARIES
5454
usdImaging
5555
usdShade
56+
usdSkel
5657
usd
5758
sdf
5859
hd
@@ -71,4 +72,6 @@ pxr_install_test_dir(
7172
pxr_register_test(testUsdSkelImagingChanges
7273
COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testUsdSkelImagingChanges"
7374
EXPECTED_RETURN_CODE 0
74-
)
75+
ENV
76+
TF_FATAL_VERIFY=0
77+
)

pxr/usdImaging/usdSkelImaging/testenv/testUsdSkelImagingChanges.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55
// https://openusd.org/license.
66
//
77

8+
#include "pxr/base/tf/errorMark.h"
89
#include "pxr/imaging/hd/renderIndex.h"
910
#include "pxr/imaging/hd/unitTestNullRenderDelegate.h"
1011

1112
#include "pxr/usd/sdf/path.h"
13+
#include "pxr/usd/usd/editContext.h"
1214
#include "pxr/usd/usd/prim.h"
1315
#include "pxr/usd/usd/stage.h"
16+
#include "pxr/usd/usdSkel/animation.h"
17+
#include "pxr/usd/usdSkel/bindingAPI.h"
18+
#include "pxr/usd/usdSkel/root.h"
1419

1520
#include "pxr/usdImaging/usdImaging/delegate.h"
1621

@@ -47,7 +52,8 @@ SwitchBoundMaterialTest()
4752
// Switch the material for box1
4853
auto box1Prim = stage->GetPrimAtPath(SdfPath("/Root/Geometry/box1"));
4954
TF_AXIOM(box1Prim);
50-
auto materialBinding = box1Prim.GetRelationship(UsdShadeTokens->materialBinding);
55+
auto materialBinding =
56+
box1Prim.GetRelationship(UsdShadeTokens->materialBinding);
5157
TF_AXIOM(materialBinding);
5258
materialBinding.SetTargets({SdfPath("/Root/Looks/green")});
5359

@@ -71,11 +77,68 @@ SwitchBoundMaterialTest()
7177
TF_AXIOM(dirtyBits != HdChangeTracker::Clean);
7278
}
7379

80+
static void
81+
SkelAnimUpdateTest()
82+
{
83+
std::cout << "-------------------------------------------------------\n";
84+
std::cout << "SkelAnimUpdateTest\n";
85+
std::cout << "-------------------------------------------------------\n";
86+
87+
const std::string usdPath = "animation.usda";
88+
UsdStageRefPtr stage = UsdStage::Open(usdPath);
89+
TF_AXIOM(stage);
90+
91+
// Bring up Hydra
92+
Hd_UnitTestNullRenderDelegate renderDelegate;
93+
std::unique_ptr<HdRenderIndex>
94+
renderIndex(HdRenderIndex::New(&renderDelegate, HdDriverVector()));
95+
auto delegate = std::make_unique<UsdImagingDelegate>(renderIndex.get(),
96+
SdfPath::AbsoluteRootPath());
97+
delegate->Populate(stage->GetPseudoRoot());
98+
delegate->SetTime(0);
99+
delegate->SyncAll(true);
100+
101+
UsdEditContext editContext(stage, stage->GetSessionLayer());
102+
SdfPath animationPath("/Animation");
103+
UsdSkelAnimation skelAnimation =
104+
UsdSkelAnimation::Define(stage, animationPath);
105+
UsdPrim animationPrim = skelAnimation.GetPrim();
106+
TF_AXIOM(animationPrim);
107+
108+
// Update skeleton binding
109+
UsdPrim skeletonPrim = stage->GetPrimAtPath(SdfPath("/Root/Skeleton"));
110+
UsdSkelBindingAPI skeletonBindingAPI = UsdSkelBindingAPI(skeletonPrim);
111+
skeletonBindingAPI.GetAnimationSourceRel()
112+
.SetTargets({animationPath});
113+
delegate->ApplyPendingUpdates();
114+
delegate->SyncAll(true);
115+
116+
// Remove animation and update skelRoot's visibility
117+
stage->RemovePrim(animationPath);
118+
skeletonBindingAPI.GetAnimationSourceRel().ClearTargets(false);
119+
UsdPrim rootPrim = stage->GetPrimAtPath(SdfPath("/Root"));
120+
UsdSkelRoot skelRoot = UsdSkelRoot(rootPrim);
121+
skelRoot.GetVisibilityAttr().Set(UsdGeomTokens->inherited);
122+
123+
// Expect errors because animation was removed
124+
TfErrorMark errorMark;
125+
126+
delegate->ApplyPendingUpdates();
127+
delegate->SyncAll(true);
128+
129+
size_t numErrors = 0;
130+
errorMark.GetBegin(&numErrors);
131+
TF_AXIOM(numErrors == 2);
132+
133+
errorMark.Clear();
134+
}
135+
74136
int main()
75137
{
76138
TfErrorMark mark;
77139

78140
SwitchBoundMaterialTest();
141+
SkelAnimUpdateTest();
79142

80143
if (TF_AXIOM(mark.IsClean())) {
81144
std::cout << "OK" << std::endl;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#usda 1.0
2+
(
3+
defaultPrim = "Root"
4+
endTimeCode = 120
5+
metersPerUnit = 0.01
6+
startTimeCode = 0
7+
timeCodesPerSecond = 24
8+
upAxis = "Z"
9+
)
10+
11+
def SkelRoot "Root" (
12+
prepend apiSchemas = ["SkelBindingAPI"]
13+
)
14+
{
15+
matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1) )
16+
uniform token[] xformOpOrder = ["xformOp:transform"]
17+
18+
def Mesh "box" (
19+
prepend apiSchemas = ["SkelBindingAPI"]
20+
)
21+
{
22+
int[] faceVertexCounts = [4, 4, 4, 4, 4, 4]
23+
int[] faceVertexIndices = [0, 1, 3, 2, 4, 5, 6, 7, 1, 2, 5, 6, 0, 4, 7, 3, 0, 1, 5, 4, 3, 7, 6, 2]
24+
token orientation = "rightHanded"
25+
point3f[] points = [(-0.6, -0.6, 0), (-0.6, 0.6, 0), (0.6, 0.6, 0), (0.6, -0.6, 0), (-0.6, -0.6, 0.14), (-0.6, 0.6, 0.14), (0.6, 0.6, 0.14), (0.6, -0.6, 0.14)]
26+
27+
int[] primvars:skel:jointIndices = [0, 0, 0, 0] (interpolation = "vertex")
28+
float[] primvars:skel:jointWeights = [1., 1., 1., 1.] (interpolation = "vertex")
29+
prepend rel skel:skeleton = </Root/Skeleton>
30+
bool doubleSided = 1
31+
}
32+
33+
def Skeleton "Skeleton" (
34+
prepend apiSchemas = ["SkelBindingAPI"]
35+
)
36+
{
37+
uniform token[] joints = ["Root"]
38+
uniform matrix4d[] bindTransforms = [
39+
((1., 0., 0., 0.), (0., 1., 0., 0.), (0., 0., 1., 0.), (0.0, 0.0, 0.0, 1.)), # Root
40+
]
41+
uniform matrix4d[] restTransforms = [
42+
((1., 0., 0., 0.), (0., 1., 0., 0.), (0., 0., 1., 0.), (0., 0., 0., 1.)), # Root
43+
]
44+
}
45+
}
46+

0 commit comments

Comments
 (0)