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 #ifndef PXR_USD_USD_SKEL_SKINNING_QUERY_H
25 #define PXR_USD_USD_SKEL_SKINNING_QUERY_H
26 
27 /// \file usdSkel/skinningQuery.h
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/usdSkel/api.h"
31 
32 #include "pxr/usd/usd/attribute.h"
33 #include "pxr/usd/usd/prim.h"
34 #include "pxr/usd/usd/relationship.h"
35 
36 #include "pxr/usd/usdGeom/primvar.h"
37 
38 #include "pxr/usd/usdSkel/animMapper.h"
39 
40 
41 PXR_NAMESPACE_OPEN_SCOPE
42 
43 
44 class UsdGeomBoundable;
45 
46 
47 /// \class UsdSkelSkinningQuery
48 ///
49 /// Object used for querying resolved bindings for skinning.
50 class UsdSkelSkinningQuery
51 {
52 public:
53     USDSKEL_API
54     UsdSkelSkinningQuery();
55 
56     /// Construct a new skining query for the resolved properties
57     /// set through the UsdSkelBindingAPI, as inherited on \p prim.
58     /// The resulting query will be marked valid only if the inherited
59     /// properties provide proper valid joint influences.
60     USDSKEL_API
61     UsdSkelSkinningQuery(const UsdPrim& prim,
62                          const VtTokenArray& skelJointOrder,
63                          const VtTokenArray& blendShapeOrder,
64                          const UsdAttribute& jointIndices,
65                          const UsdAttribute& jointWeights,
66                          const UsdAttribute& geomBindTransform,
67                          const UsdAttribute& joints,
68                          const UsdAttribute& blendShapes,
69                          const UsdRelationship& blendShapeTargets);
70 
71     /// Returns true if this query is valid.
IsValid()72     bool IsValid() const { return bool(_prim); }
73 
74     /// Boolean conversion operator. Equivalent to IsValid().
75     explicit operator bool() const { return IsValid(); }
76 
GetPrim()77     const UsdPrim& GetPrim() const { return _prim; }
78 
79     /// Returns true if there are blend shapes associated with this prim.
80     USDSKEL_API
81     bool HasBlendShapes() const;
82 
83     /// Returns true if joint influence data is associated with this prim.
84     USDSKEL_API
85     bool HasJointInfluences() const;
86 
87     /// Returns the number of influences encoded for each component.
88     /// If the prim defines rigid joint influences, then this returns
89     /// the number of influences that map to every point. Otherwise,
90     /// this provides the number of influences per point.
91     /// \sa IsRigidlyDeformed
GetNumInfluencesPerComponent()92     int GetNumInfluencesPerComponent() const {
93         return _numInfluencesPerComponent;
94     }
95 
GetInterpolation()96     const TfToken& GetInterpolation() const { return _interpolation; }
97 
98     /// Returns true if the held prim has the same joint influences
99     /// across all points, or false otherwise.
100     USDSKEL_API
101     bool IsRigidlyDeformed() const;
102 
GetGeomBindTransformAttr()103     const UsdAttribute& GetGeomBindTransformAttr() const {
104         return _geomBindTransformAttr;
105     }
106 
GetJointIndicesPrimvar()107     const UsdGeomPrimvar& GetJointIndicesPrimvar() const {
108         return _jointIndicesPrimvar;
109     }
110 
GetJointWeightsPrimvar()111     const UsdGeomPrimvar& GetJointWeightsPrimvar() const {
112         return _jointWeightsPrimvar;
113     }
114 
GetBlendShapesAttr()115     const UsdAttribute& GetBlendShapesAttr() const {
116         return _blendShapes;
117     }
118 
GetBlendShapeTargetsRel()119     const UsdRelationship& GetBlendShapeTargetsRel() const {
120         return _blendShapeTargets;
121     }
122 
123     /// Return a mapper for remapping from the joint order of the skeleton
124     /// to the local joint order of this prim, if any. Returns a null
125     /// pointer if the prim has no custom joint orer.
126     /// The mapper maps data from the order given by the \em joints order
127     /// on the Skeleton to the order given by the \em skel:joints property,
128     /// as optionally set through the UsdSkelBindingAPI.
GetJointMapper()129     const UsdSkelAnimMapperRefPtr& GetJointMapper() const {
130         return _jointMapper;
131     }
132 
133     /// \deprecated Use GetJointMapper.
GetMapper()134     const UsdSkelAnimMapperRefPtr& GetMapper() const { return _jointMapper; }
135 
136 
137     /// Return the mapper for remapping blend shapes from the order of the
138     /// bound SkelAnimation to the local blend shape order of this prim.
139     /// Returns a null reference if the underlying prim has no blend shapes.
140     /// The mapper maps data from the order given by the \em blendShapes order
141     /// on the SkelAnimation to the order given by the \em skel:blendShapes
142     /// property, as set through the UsdSkelBindingAPI.
GetBlendShapeMapper()143     const UsdSkelAnimMapperRefPtr& GetBlendShapeMapper() const {
144         return _blendShapeMapper;
145     }
146 
147     /// Get the custom joint order for this skinning site, if any.
148     USDSKEL_API
149     bool GetJointOrder(VtTokenArray* jointOrder) const;
150 
151     /// Get the blend shapes for this skinning site, if any.
152     USDSKEL_API
153     bool GetBlendShapeOrder(VtTokenArray* blendShapes) const;
154 
155     /// Populate \p times with the union of time samples for all properties
156     /// that affect skinning, independent of joint transforms and any
157     /// other prim-specific properties (such as points).
158     ///
159     /// \sa UsdAttribute::GetTimeSamples
160     USDSKEL_API
161     bool GetTimeSamples(std::vector<double>* times) const;
162 
163     /// Populate \p times with the union of time samples within \p interval,
164     /// for all properties that affect skinning, independent of joint
165     /// transforms and any other prim-specific properties (such as points).
166     ///
167     /// \sa UsdAttribute::GetTimeSamplesInInterval
168     USDSKEL_API
169     bool GetTimeSamplesInInterval(const GfInterval& interval,
170                                   std::vector<double>* times) const;
171 
172     /// Convenience method for computing joint influences.
173     /// In addition to querying influences, this will also perform
174     /// validation of the basic form of the weight data -- although
175     /// the array contents is not validated.
176     USDSKEL_API
177     bool ComputeJointInfluences(VtIntArray* indices,
178                                 VtFloatArray* weights,
179                                 UsdTimeCode time=UsdTimeCode::Default()) const;
180 
181     /// Convenience method for computing joint influence, where constant
182     /// influences are expanded to hold values per point.
183     /// In addition to querying influences, this will also perform
184     /// validation of the basic form of the weight data -- although
185     /// the array contents is not validated.
186     USDSKEL_API
187     bool ComputeVaryingJointInfluences(
188              size_t numPoints,
189              VtIntArray* indices,
190              VtFloatArray* weights,
191              UsdTimeCode time=UsdTimeCode::Default()) const;
192 
193     /// Compute skinned points using linear blend skinning.
194     /// Both \p xforms and \p points are given in _skeleton space_,
195     /// using the joint order of the bound skeleton.
196     /// Joint influences and the (optional) binding transform are computed
197     /// at time \p time (which will typically be unvarying).
198     ///
199     /// \sa UsdSkelSkeletonQuery::ComputeSkinningTransforms
200     template <typename Matrix4>
201     USDSKEL_API
202     bool ComputeSkinnedPoints(const VtArray<Matrix4>& xforms,
203                               VtVec3fArray* points,
204                               UsdTimeCode time=UsdTimeCode::Default()) const;
205 
206     /// Compute skinned normals using linear blend skinning.
207     /// Both \p xforms and \p points are given in _skeleton space_,
208     /// using the joint order of the bound skeleton.
209     /// Joint influences and the (optional) binding transform are computed
210     /// at time \p time (which will typically be unvarying).
211     ///
212     /// \sa UsdSkelSkeletonQuery::ComputeSkinningTransforms
213     template <typename Matrix4>
214     USDSKEL_API
215     bool ComputeSkinnedNormals(const VtArray<Matrix4>& xforms,
216                               VtVec3fArray* points,
217                               UsdTimeCode time=UsdTimeCode::Default()) const;
218 
219     /// Compute a skinning transform using linear blend skinning.
220     /// The \p xforms are given in _skeleton space_, using the joint order of
221     /// the bound skeleton.
222     /// Joint influences and the (optional) binding transform are computed
223     /// at time \p time (which will typically be unvarying).
224     /// If this skinning query holds non-constant joint influences,
225     /// no transform will be computed, and the function will return false.
226     ///
227     /// \sa UsdSkelSkeletonQuery::ComputeSkinningTransforms
228     template <typename Matrix4>
229     USDSKEL_API
230     bool ComputeSkinnedTransform(const VtArray<Matrix4>& xforms,
231                                  Matrix4* xform,
232                                  UsdTimeCode time=UsdTimeCode::Default()) const;
233 
234     /// Helper for computing an *approximate* padding for use in extents
235     /// computations. The padding is computed as the difference between the
236     /// pivots of the \p skelRestXforms -- _skeleton space_ joint transforms
237     /// at rest -- and the extents of the skinned primitive.
238     /// This is intended to provide a suitable, constant metric for padding
239     /// joint extents as computed by UsdSkelComputeJointsExtent.
240     template <typename Matrix4>
241     USDSKEL_API
242     float ComputeExtentsPadding(const VtArray<Matrix4>& skelRestXforms,
243                                 const UsdGeomBoundable& boundable) const;
244 
245     USDSKEL_API
246     GfMatrix4d
247     GetGeomBindTransform(UsdTimeCode time=UsdTimeCode::Default()) const;
248 
249     USDSKEL_API
250     std::string GetDescription() const;
251 
252 private:
253 
254     void _InitializeJointInfluenceBindings(
255              const UsdAttribute& jointIndices,
256              const UsdAttribute& jointWeights);
257 
258     void _InitializeBlendShapeBindings(
259              const UsdAttribute& blendShapes,
260              const UsdRelationship& blendShapeTargets);
261 
262     UsdPrim _prim;
263     int _numInfluencesPerComponent = 1;
264     int _flags = 0;
265     TfToken _interpolation;
266 
267     UsdGeomPrimvar _jointIndicesPrimvar;
268     UsdGeomPrimvar _jointWeightsPrimvar;
269     UsdAttribute _geomBindTransformAttr;
270     UsdAttribute _blendShapes;
271     UsdRelationship _blendShapeTargets;
272     UsdSkelAnimMapperRefPtr _jointMapper;
273     UsdSkelAnimMapperRefPtr _blendShapeMapper;
274     boost::optional<VtTokenArray> _jointOrder;
275     boost::optional<VtTokenArray> _blendShapeOrder;
276 };
277 
278 PXR_NAMESPACE_CLOSE_SCOPE
279 
280 #endif // PXR_USD_USD_SKEL_SKINNING_QUERY_H
281