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