1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #include "pxr/usd/usdSkel/utils.h"
25
26 #include "pxr/base/gf/matrix3d.h"
27 #include "pxr/base/gf/matrix3f.h"
28 #include "pxr/base/gf/matrix4d.h"
29 #include "pxr/base/gf/matrix4f.h"
30 #include "pxr/base/gf/range3f.h"
31 #include "pxr/base/tf/pyContainerConversions.h"
32 #include "pxr/base/tf/pyResultConversions.h"
33 #include "pxr/base/tf/pyUtils.h"
34 #include "pxr/base/tf/wrapTypeHelpers.h"
35
36 #include "pxr/usd/usd/pyConversions.h"
37 #include "pxr/usd/usd/primRange.h"
38 #include "pxr/usd/usd/relationship.h"
39
40 #include "pxr/usd/usdSkel/root.h"
41 #include "pxr/usd/usdSkel/topology.h"
42 #include "pxr/usd/usdSkel/utils.h"
43
44 #include <boost/python.hpp>
45 #include <boost/python/extract.hpp>
46
47
48 using namespace boost::python;
49
50 PXR_NAMESPACE_USING_DIRECTIVE
51
52
53 namespace {
54
55
56 // deprecated
57 VtMatrix4dArray
_ComputeJointLocalTransforms(const UsdSkelTopology & topology,const VtMatrix4dArray & xforms,const VtMatrix4dArray & inverseXforms,const GfMatrix4d * rootInverseXform=nullptr)58 _ComputeJointLocalTransforms(const UsdSkelTopology& topology,
59 const VtMatrix4dArray& xforms,
60 const VtMatrix4dArray& inverseXforms,
61 const GfMatrix4d* rootInverseXform=nullptr)
62 {
63 VtMatrix4dArray jointLocalXforms;
64 UsdSkelComputeJointLocalTransforms(topology, xforms, inverseXforms,
65 &jointLocalXforms, rootInverseXform);
66 return jointLocalXforms;
67 }
68
69
70 // deprecated
71 VtMatrix4dArray
_ComputeJointLocalTransforms_NoInvXforms(const UsdSkelTopology & topology,const VtMatrix4dArray & xforms,const GfMatrix4d * rootInverseXform=nullptr)72 _ComputeJointLocalTransforms_NoInvXforms(
73 const UsdSkelTopology& topology,
74 const VtMatrix4dArray& xforms,
75 const GfMatrix4d* rootInverseXform=nullptr)
76 {
77 VtMatrix4dArray jointLocalXforms;
78 UsdSkelComputeJointLocalTransforms(topology, xforms, &jointLocalXforms,
79 rootInverseXform);
80 return jointLocalXforms;
81 }
82
83
84 // depreacted
85 VtMatrix4dArray
_ConcatJointTransforms(const UsdSkelTopology & topology,const VtMatrix4dArray & jointLocalXforms,const GfMatrix4d * rootXform=nullptr)86 _ConcatJointTransforms(const UsdSkelTopology& topology,
87 const VtMatrix4dArray& jointLocalXforms,
88 const GfMatrix4d* rootXform=nullptr)
89 {
90 VtMatrix4dArray xforms;
91 UsdSkelConcatJointTransforms(topology, jointLocalXforms,
92 &xforms, rootXform);
93 return xforms;
94 }
95
96
97 template <typename Matrix4>
98 tuple
_DecomposeTransform(const Matrix4 & mx)99 _DecomposeTransform(const Matrix4& mx)
100 {
101 GfVec3f t;
102 GfQuatf r;
103 GfVec3h s;
104 if (!UsdSkelDecomposeTransform(mx, &t, &r, &s)) {
105 // XXX: Want this case to throw an exception.
106 TF_CODING_ERROR("Failed decomposing transform. "
107 "The transform may be singular.");
108 }
109 return boost::python::make_tuple(t, r, s);
110 }
111
112
113 template <typename Matrix4>
114 tuple
_DecomposeTransforms(const TfSpan<Matrix4> & xforms)115 _DecomposeTransforms(const TfSpan<Matrix4>& xforms)
116 {
117 VtVec3fArray t(xforms.size());
118 VtQuatfArray r(xforms.size());
119 VtVec3hArray s(xforms.size());
120 if (!UsdSkelDecomposeTransforms(xforms, t, r, s)) {
121 TF_CODING_ERROR("Failed decomposing transforms. "
122 "Some transforms may be singular.");
123 }
124 return boost::python::make_tuple(t, r, s);
125 }
126
127
128 GfMatrix4d
_MakeTransform(const GfVec3f & translate,const GfQuatf & rotate,const GfVec3h & scale)129 _MakeTransform(const GfVec3f& translate,
130 const GfQuatf& rotate,
131 const GfVec3h& scale)
132 {
133 GfMatrix4d xform;
134 UsdSkelMakeTransform(translate, rotate, scale, &xform);
135 return xform;
136 }
137
138
139 VtMatrix4dArray
_MakeTransforms(TfSpan<const GfVec3f> translations,TfSpan<const GfQuatf> rotations,TfSpan<const GfVec3h> scales)140 _MakeTransforms(TfSpan<const GfVec3f> translations,
141 TfSpan<const GfQuatf> rotations,
142 TfSpan<const GfVec3h> scales)
143 {
144 VtMatrix4dArray xforms(translations.size());
145 UsdSkelMakeTransforms(translations, rotations, scales, xforms);
146 return xforms;
147 }
148
149
150 template <typename Matrix4>
151 GfRange3f
_ComputeJointsExtent(TfSpan<const Matrix4> xforms,float pad=0,const Matrix4 * rootXform=nullptr)152 _ComputeJointsExtent(TfSpan<const Matrix4> xforms,
153 float pad=0,
154 const Matrix4* rootXform=nullptr)
155 {
156 GfRange3f range;
157 UsdSkelComputeJointsExtent(xforms, &range, pad, rootXform);
158 return range;
159 }
160
161
162 template <typename T>
163 bool
_ExpandConstantInfluencesToVarying(VtArray<T> & array,size_t size)164 _ExpandConstantInfluencesToVarying(VtArray<T>& array, size_t size)
165 {
166 return UsdSkelExpandConstantInfluencesToVarying(&array, size);
167 }
168
169
170 template <typename T>
171 bool
_ResizeInfluences(VtArray<T> & array,int srcNumInfluencesPerPoint,int newNumInfluencesPerPoint)172 _ResizeInfluences(VtArray<T>& array,
173 int srcNumInfluencesPerPoint,
174 int newNumInfluencesPerPoint)
175 {
176 return UsdSkelResizeInfluences(
177 &array, srcNumInfluencesPerPoint, newNumInfluencesPerPoint);
178 }
179
180
181 template <typename Matrix4>
182 Matrix4
_InterleavedSkinTransformLBS(const Matrix4 & geomBindTransform,TfSpan<const Matrix4> jointXforms,TfSpan<const GfVec2f> influences)183 _InterleavedSkinTransformLBS(const Matrix4& geomBindTransform,
184 TfSpan<const Matrix4> jointXforms,
185 TfSpan<const GfVec2f> influences)
186 {
187 Matrix4 xform;
188 if (!UsdSkelSkinTransformLBS(geomBindTransform, jointXforms,
189 influences, &xform)) {
190 xform = geomBindTransform;
191 }
192 return xform;
193 }
194
195
196 template <typename Matrix4>
197 Matrix4
_NonInterleavedSkinTransformLBS(const Matrix4 & geomBindTransform,TfSpan<const Matrix4> jointXforms,TfSpan<const int> jointIndices,TfSpan<const float> jointWeights)198 _NonInterleavedSkinTransformLBS(const Matrix4& geomBindTransform,
199 TfSpan<const Matrix4> jointXforms,
200 TfSpan<const int> jointIndices,
201 TfSpan<const float> jointWeights)
202 {
203 Matrix4 xform;
204 if (!UsdSkelSkinTransformLBS(geomBindTransform, jointXforms,
205 jointIndices, jointWeights, &xform)) {
206 xform = geomBindTransform;
207 }
208 return xform;
209 }
210
211
212 template <class Matrix3, class Matrix4>
_WrapUtilsT()213 void _WrapUtilsT()
214 {
215 def("ComputeJointLocalTransforms",
216 static_cast<bool (*)(const UsdSkelTopology&, TfSpan<const Matrix4>,
217 TfSpan<const Matrix4>, TfSpan<Matrix4>,
218 const Matrix4*)>(
219 &UsdSkelComputeJointLocalTransforms),
220 (arg("topology"), arg("xforms"), arg("inverseXforms"),
221 arg("jointLocalXforms"), arg("rootInverseXform")=object()));
222
223 def("ComputeJointLocalTransforms",
224 static_cast<bool (*)(const UsdSkelTopology&, TfSpan<const Matrix4>,
225 TfSpan<Matrix4>, const Matrix4*)>(
226 &UsdSkelComputeJointLocalTransforms),
227 (arg("topology"), arg("xforms"),
228 arg("jointLocalXforms"), arg("rootInverseXform")=object()));
229
230 def("ConcatJointTransforms",
231 static_cast<bool (*)(const UsdSkelTopology&, TfSpan<const Matrix4>,
232 TfSpan<Matrix4>, const Matrix4*)>(
233 &UsdSkelConcatJointTransforms),
234 (arg("topology"), arg("jointLocalXforms"),
235 arg("rootXform")=object()));
236
237 def("DecomposeTransform", &_DecomposeTransform<Matrix4>,
238 "Decompose a transform into a (translate,rotate,scale) tuple.");
239
240 def("DecomposeTransforms", &_DecomposeTransforms<Matrix4>,
241 "Decompose a transform array into a "
242 "(translations,rotations,scales) tuple.");
243
244 def("ComputeJointsExtent", _ComputeJointsExtent<Matrix4>,
245 (arg("xforms"), arg("pad")=0.0f, arg("rootXform")=object()));
246
247 def("SkinPointsLBS",
248 static_cast<bool (*)(const Matrix4&, TfSpan<const Matrix4>,
249 TfSpan<const int>, TfSpan<const float>,
250 int, TfSpan<GfVec3f>, bool)>(
251 &UsdSkelSkinPointsLBS),
252 (arg("geomBindTransform"),
253 arg("jointXforms"),
254 arg("jointIndices"),
255 arg("jointWeights"),
256 arg("numInfluencesPerPoint"),
257 arg("points"),
258 arg("inSerial")=true));
259
260 def("SkinPointsLBS",
261 static_cast<bool (*)(const Matrix4&, TfSpan<const Matrix4>,
262 TfSpan<const GfVec2f>, int,
263 TfSpan<GfVec3f>, bool)>(
264 &UsdSkelSkinPointsLBS),
265 (arg("geomBindTransform"),
266 arg("jointXforms"),
267 arg("influences"),
268 arg("numInfluencesPerPoint"),
269 arg("points"),
270 arg("inSerial")=true));
271
272
273
274 def("SkinNormalsLBS",
275 static_cast<bool (*)(const Matrix3&, TfSpan<const Matrix3>,
276 TfSpan<const int>, TfSpan<const float>,
277 int, TfSpan<GfVec3f>, bool)>(
278 &UsdSkelSkinNormalsLBS),
279 (arg("geomBindTransform"),
280 arg("jointXforms"),
281 arg("jointIndices"),
282 arg("jointWeights"),
283 arg("numInfluencesPerPoint"),
284 arg("normals"),
285 arg("inSerial")=true));
286
287 def("SkinNormalsLBS",
288 static_cast<bool (*)(const Matrix3&, TfSpan<const Matrix3>,
289 TfSpan<const GfVec2f>, int,
290 TfSpan<GfVec3f>, bool)>(
291 &UsdSkelSkinNormalsLBS),
292 (arg("geomBindTransform"),
293 arg("jointXforms"),
294 arg("influences"),
295 arg("numInfluencesPerPoint"),
296 arg("normals"),
297 arg("inSerial")=true));
298
299 def("SkinTransformLBS", &_InterleavedSkinTransformLBS<Matrix4>,
300 (arg("geomBindTransform"),
301 arg("jointXforms"),
302 arg("influences")));
303
304 def("SkinTransformLBS", &_NonInterleavedSkinTransformLBS<Matrix4>,
305 (arg("geomBindTransform"),
306 arg("jointXforms"),
307 arg("jointIndices"),
308 arg("jointWeights")));
309 }
310
311
312 } // namespace
313
314
wrapUsdSkelUtils()315 void wrapUsdSkelUtils()
316 {
317 // Wrap methods supporting different matrix precisions.
318 _WrapUtilsT<GfMatrix3d, GfMatrix4d>();
319 _WrapUtilsT<GfMatrix3f, GfMatrix4f>();
320
321 def("IsSkelAnimationPrim", &UsdSkelIsSkelAnimationPrim, (arg("prim")));
322
323 def("IsSkinnablePrim", &UsdSkelIsSkinnablePrim, (arg("prim")));
324
325 // deprecated
326 def("ComputeJointLocalTransforms", &_ComputeJointLocalTransforms,
327 (arg("topology"), arg("xforms"), arg("inverseXforms"),
328 arg("rootInverseXform")=object()));
329
330 // deprecated
331 def("ComputeJointLocalTransforms",
332 &_ComputeJointLocalTransforms_NoInvXforms,
333 (arg("topology"), arg("xforms"),
334 arg("rootInverseXform")=object()));
335
336 // deprecated
337 def("ConcatJointTransforms", &_ConcatJointTransforms,
338 (arg("topology"), arg("jointLocalXforms"),
339 arg("rootXform")=object()));
340
341 def("MakeTransform", &_MakeTransform,
342 (arg("translate"), arg("rotate"), arg("scale")));
343
344 // deprecated
345 def("MakeTransforms", &_MakeTransforms,
346 (arg("translations"), arg("rotations"), arg("scales")));
347
348 def("NormalizeWeights",
349 static_cast<bool (*)(TfSpan<float>,int)>(
350 &UsdSkelNormalizeWeights),
351 (arg("weights"), arg("numInfluencesPerComponent")));
352
353 def("SortInfluences",
354 static_cast<bool (*)(TfSpan<int>, TfSpan<float>,int)>(
355 &UsdSkelSortInfluences),
356 (arg("indices"), arg("weights"), arg("numInfluencesPerComponent")));
357
358 def("ExpandConstantInfluencesToVarying",
359 &_ExpandConstantInfluencesToVarying<int>,
360 (arg("array"), arg("size")));
361
362 def("ExpandConstantInfluencesToVarying",
363 &_ExpandConstantInfluencesToVarying<float>,
364 (arg("array"), arg("size")));
365
366 def("ResizeInfluences", &_ResizeInfluences<int>,
367 (arg("array"),
368 arg("srcNumInfluencesPerComponent"),
369 arg("newNumInfluencesPerComponent")));
370
371 def("ResizeInfluences", &_ResizeInfluences<float>,
372 (arg("array"),
373 arg("srcNumInfluencesPerComponent"),
374 arg("newNumInfluencesPerComponent")));
375
376 def("InterleaveInfluences", &UsdSkelInterleaveInfluences,
377 (arg("indices"), arg("weights"),
378 arg("interleavedInfluences")));
379
380 def("ApplyBlendShape", &UsdSkelApplyBlendShape,
381 (arg("weight"),
382 arg("offsets"),
383 arg("indices"),
384 arg("points")));
385 }
386