HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_LinearSkinDeformer.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: GU_LinearSkinDeformer.h (GU Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __GU_LINEARSKINDEFORMER_H_INCLUDED__
12 #define __GU_LINEARSKINDEFORMER_H_INCLUDED__
13 
14 #include "GU_API.h"
15 #include "GU_Detail.h"
17 #include <GA/GA_Range.h>
18 #include <UT/UT_Array.h>
19 #include <UT/UT_Assert.h>
20 #include <UT/UT_DualQuaternion.h>
21 #include <UT/UT_IteratorRange.h>
22 #include <UT/UT_Matrix3.h>
23 #include <UT/UT_Matrix4.h>
24 #include <UT/UT_NonCopyable.h>
25 #include <UT/UT_Quaternion.h>
26 #include <UT/UT_TaskGroup.h>
27 #include <UT/UT_UniquePtr.h>
28 #include <UT/UT_VectorTypes.h>
29 #include <SYS/SYS_Inline.h>
30 #include <SYS/SYS_StaticAssert.h>
31 #include <SYS/SYS_TypeDecorate.h>
32 #include <SYS/SYS_Types.h>
33 
34 #include <stddef.h>
35 
36 
37 
38 class GA_Attribute;
39 class GA_ROAttributeRef;
41 class GU_Detail;
43 
45 {
47  GU_CaptureElement(int i, float w) : myI(i), myW(w) { }
48 
49  bool operator>(const GU_CaptureElement& elem) const
50  {
51  return (myW > elem.myW);
52  }
53 
54  int myI;
55  float myW;
56 };
59 
60 
61 template <typename T>
63 {
65 
66  SYS_FORCE_INLINE GU_DualQuatXformT() = default;
67  SYS_FORCE_INLINE GU_DualQuatXformT(const ThisType&) = default;
68  SYS_FORCE_INLINE GU_DualQuatXformT(ThisType&&) = default;
70  ThisType& operator=(const GU_DualQuatXformT<T>&) = default;
72  ThisType& operator=(GU_DualQuatXformT<T>&&) = default;
73 
76  {
78  myDQ.transform(src * myStretch, dst);
79  return dst;
80  }
83  {
85  myDQ.transform(src, dst);
86  dst *= myStretch;
87  return dst;
88  }
91  {
93  myDQ.getRotation().getRotationMatrix(dst);
94  dst.leftMult(src * myStretch);
95  return dst;
96  }
99  {
101  dst *= myStretch;
102  dst *= myDQ.convertToXform();
103  return dst;
104  }
107  {
109  myDQ.rotate(src, dst);
110  return dst;
111  }
114  {
115  return src * myDQ.getRotation();
116  }
117 
120 };
123 
124 /// Stores the source geometry and attributes to deform, for
125 /// GU_LinearSkinDeformer.
127 {
128 public:
129  GU_LinearSkinDeformerSourceAttribs(const GU_Detail *gdp);
130 
131  int64 getMemoryUsage(bool inclusive) const;
132 
133  /// Clear the list of attributes and rebind to a different detail.
134  void reset(const GU_Detail *gdp);
135 
136  /// Returns the source detail.
137  const GU_Detail *srcGdp() const { return myGdp; }
138 
139  /// Append attribute to be deformed. How it is deformed depends on the
140  /// attribute's GA_TypeInfo.
141  void append(const GA_Attribute &src_attrib);
142 
143 private:
144  const GU_Detail *myGdp;
145  UT_Array<const GA_Attribute *> myPosAttribs;
146  UT_Array<const GA_Attribute *> myVecAttribs;
147  UT_Array<const GA_Attribute *> myNmlAttribs;
148  UT_Array<const GA_Attribute *> myQuatAttribs;
149  UT_Array<const GA_Attribute *> myMat3Attribs;
150  UT_Array<const GA_Attribute *> myMat4Attribs;
151 
152  friend class GU_LinearSkinDeformer;
153 };
154 
155 /// Class representing source capture weight data for GU_LinearSkinDeformer
157 {
158 public:
160 
161  int64 getMemoryUsage(bool inclusive) const;
162 
163  /// Reset all state
164  void reset();
165 
166  /// Set up from the source geometry. Returns the number of transforms
167  /// required to deform using the capture weight attribute. If in error,
168  /// then 0 is returned.
169  /// If max_pt_weights > 0, then it will limit the number of weight entries
170  /// to use per point.
171  int init(
172  const GU_Detail& src,
173  const GA_Range& pt_range,
174  int max_pt_weights = 0);
175 
176  const GU_Detail* srcGdp() const
177  { return myGdp; }
178  void setSrcGdp(const GU_Detail &src)
179  { myGdp = &src; }
180 
181  /// Set new region transforms from point skeleton geometry with P, name,
182  /// and transform. It will invert transform to match what getCaptureParms()
183  /// returns.
184  bool setRegionXformsFromGeo(
185  const GU_Detail& rest_skel,
186  const GA_Attribute& P,
187  const GA_Attribute& name,
188  const GA_Attribute& transform);
189 
190  /// Number of points in the range given to init().
191  exint numPoints() const { return myNumPoints; }
192 
193  /// Return the number of regions found by initSrc()
194  int numRegions() const
195  { return myRegionXforms.entries(); }
196 
197  /// Return the name given the region index. init() must have been
198  /// called first.
199  const UT_StringHolder & regionName(int i) const
200  { return myRegionNames[i]; }
201 
202  /// Return the transform given the region index. init() must have been
203  /// called first.
204  const UT_Matrix4F& regionXform(int i) const
205  { return myRegionXforms[i]; }
206 
207  /// Returns whether the region is referenced by at least one capture
208  /// element.
209  bool usesRegion(int i) const
210  { return myUsedRegions.getBitFast(i); }
211 
212  /// Static utility method to get capture parameters
213  static bool getCaptureParms(
214  const GU_Detail& src,
215  GA_ROAttributeRef& pcapt,
216  GEO_AttributeCapturePath& attr_cap_path,
217  UT_Array<UT_Matrix4F>& xforms,
218  int& max_pt_regions);
219 
220  using CaptureElementRange =
222 
223  /// Returns the range of capture elements for the given point index.
224  CaptureElementRange captureElementRange(exint ptidx) const;
225 
226 private:
227  const GU_Detail* myGdp;
228  GA_OffsetArray myPointOffsets;
229  UT_ExintArray myPointStarts;
230  GU_CaptureElementArray myCaptureElements;
231  /// Number of points in the range passed to init(). This may not be the same
232  /// as myPointOffsets.size() if the range is not contiguous.
233  exint myNumPoints;
234  /// Primitives in the source detail that we will update transforms for.
235  GA_OffsetArray myPrimOffsets;
236  /// Index of the first primitive from the point range.
237  GA_Index myPrimStartIdx;
238 
239  UT_StringArray myRegionNames;
240  UT_Array<UT_Matrix4F> myRegionXforms;
241  UT_BitArray myUsedRegions;
242 
243  friend class GU_LinearSkinDeformer;
244 };
245 
248 {
249  return UTmakeRange(myCaptureElements.begin() + myPointStarts[ptidx],
250  myCaptureElements.begin() + myPointStarts[ptidx + 1]);
251 }
252 
253 /// Performs linear blend skinning of geometry
255 {
256 public:
258 
259  /// Reset all state
260  void reset();
261 
262  enum Method
263  {
267  };
268 
269  /// Setup the destination geometry. Fails if the destination is missing
270  /// attributes that were appended to deform. A reference to the src is
271  /// maintained until reset() is called.
272  bool init(
273  GU_Detail& dst,
274  const GA_Range& pt_range,
275  const GU_LinearSkinDeformerSourceWeights& src_weights,
276  const GU_LinearSkinDeformerSourceAttribs& src_attribs,
277  Method method = DEFORM_LINEAR,
278  bool create_missing_attribs = false,
279  const char *blend_attrib = nullptr);
280 
281  int numRegions() const
282  { return mySrcWeights->myRegionXforms.entries(); }
283 
284  const UT_StringHolder & regionName(int i) const
285  { return mySrcWeights->regionName(i); }
286 
287  /// For debugging purposes, call this before making your
288  /// setRegionTransform() calls to avoid asserts about missing transforms.
290  { UT_IF_ASSERT(myNumTransformsSet=0;) }
291 
292  /// Set deforming transform for region_idx, which matches indices found in
293  /// the capture weight attribute. init() must have been called first.
294  void setRegionTransform(
295  int region_idx,
296  const UT_Matrix4F& xform);
297 
298  /// Set deforming transform for region_idx. To apply the capture region's
299  /// transform use setRegionTransform(). init() must have been called first.
300  void setFullRegionTransform(
301  int region_idx,
302  const UT_Matrix4F& xform);
303 
304  /// Set transforms relative to capture region transforms from
305  /// P,name,transform attributes. This matches with
306  /// GU_LinearSkinDeformerSourceWeights::setRegionXformsFromGeo()
307  bool setRegionTransformsFromGeo(
308  const GU_Detail& anim_skel);
309 
310  /// Spawn tasks that will perform the deformation. The tasks will have
311  /// references to this object, so they must be executed before this object
312  /// is destroyed.
313  ///
314  /// The necessary steps in this specific order:
315  /// 1. N = GU_LinearSkinDeformerSource::init() for the point geometry you
316  /// want to deform
317  /// 2. GU_LinearSkinDeformerSource::appendAttrib() for each src attribute
318  /// you want to deform
319  /// 3. GU_LinearSkinDeformer::init() to set up where to put the results
320  /// 4. Call setRegionTransform() N times for each of the cregions
321  /// 5. Call spawnDeformTasks()
322  /// 6. When done with the task list, spawn them: tasks.spawnRootAndWait();
323  ///
324  /// @{
325  void spawnDeformTasks(
326  UT_TaskGroup& tasks);
327  void spawnInverseDeformTasks(
328  UT_TaskGroup& tasks);
329  /// @}
330 
331  /// Do the deform.
332  ///
333  /// The necessary steps in this specific order:
334  /// 1. N = GU_LinearSkinDeformerSource::init() for the point geometry you
335  /// want to deform
336  /// 2. GU_LinearSkinDeformerSource::appendAttrib() for each src attribute
337  /// you want to deform
338  /// 3. GU_LinearSkinDeformer::init() to set up where to put the results
339  /// 4. Call setRegionTransform() N times for each of the cregions
340  /// 5. Call deform()
341  ///
342  /// @{
343  void deform();
344  void inverseDeform();
345  /// @}
346 
347 public:
350 
351  static const char* SKIN_LINEAR;
352  static const char* SKIN_DUAL_QUATERNION;
354 
355  static bool getGlobalAttribMethod(const GU_Detail *igdp, Method &type);
356  static bool getGlobalAttribBlendAttrib(const GU_Detail *igdp,
357  UT_StringHolder &blend_attrib);
358 
359 private:
360 
361  void clearXforms();
362 
363  void deformInParallel();
364 
365  template <bool ALIGNED, bool INVERT>
366  void spawnLinearTasks(
367  UT_TaskGroup& tasks);
368  template <bool ALIGNED, bool INVERT>
369  void spawnDualQuatTasks(
370  UT_TaskGroup& tasks);
371  template <bool ALIGNED, bool INVERT>
372  void spawnBlendedDualQuatTasks(
373  UT_TaskGroup& tasks);
374 
375 private:
376  Method myMethod;
377 
378  GU_Detail* myDstGdp;
379  GA_Range myDstRange;
380  UT_Array<GA_Attribute*> myDstPosAttribs;
381  UT_Array<GA_Attribute*> myDstVecAttribs;
382  UT_Array<GA_Attribute*> myDstNmlAttribs;
383  UT_Array<GA_Attribute*> myDstQuatAttribs;
384  UT_Array<GA_Attribute*> myDstMat3Attribs;
385  UT_Array<GA_Attribute*> myDstMat4Attribs;
386 
387  const GU_LinearSkinDeformerSourceWeights* mySrcWeights;
388  const GU_LinearSkinDeformerSourceAttribs* mySrcAttribs;
389 
390  GA_ROHandleF mySrcBlendAttrib;
391 
392  AttribPtrArray mySrcPromotedAttribs;
393 
394  // Linear blending
395  UT_Array<UT_Matrix4F> myPosXforms;
396  UT_Array<UT_QuaternionF> myQuatXforms;
397 
398  // DualQuaternion blending
399  UT_Array<DualQuatXformF> myDualQuatXforms;
400 
401  // This is only used when assertions are enabled
402  exint myNumTransformsSet;
403 };
404 
405 #endif // __GU_LINEARSKINDEFORMER_H_INCLUDED__
const UT_Matrix4F & regionXform(int i) const
Definition of a geometry attribute.
Definition: GA_Attribute.h:198
void leftMult(const UT_SymMatrix3T< S > &m)
Multiply given symmetric matrix on the left.
Definition: UT_Matrix3.h:330
*get result *(waiting if necessary)*A common idiom is to fire a bunch of sub tasks at the and then *wait for them to all complete We provide a helper class
Definition: thread.h:623
SYS_FORCE_INLINE UT_Vector3T< T > transform(const UT_Vector3T< T > &src) const
UT_IteratorRange< IterT > UTmakeRange(IterT &&b, IterT &&e)
int64 exint
Definition: SYS_Types.h:125
SYS_FORCE_INLINE UT_Vector3T< T > transformTransposed(const UT_Vector3T< T > &src) const
Performs linear blend skinning of geometry.
#define UT_IF_ASSERT(ZZ)
Definition: UT_Assert.h:174
3D Vector class.
UT_Matrix3T< T > myStretch
GU_CaptureElement(int i, float w)
UT_DualQuaternionT< T > myDQ
A range of elements in an index-map.
Definition: GA_Range.h:42
double fpreal64
Definition: SYS_Types.h:201
Class representing source capture weight data for GU_LinearSkinDeformer.
exint numPoints() const
Number of points in the range given to init().
GLboolean reset
Definition: glad.h:5138
SYS_FORCE_INLINE UT_Matrix3T< T > transform(const UT_Matrix3T< T > &src) const
This class provides a way to manage a reference to an attribute permitting Read-Only access...
const UT_StringHolder & regionName(int i) const
bool operator>(const GU_CaptureElement &elem) const
CaptureElementRange captureElementRange(exint ptidx) const
Returns the range of capture elements for the given point index.
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
SYS_FORCE_INLINE UT_Matrix4T< T > transform(const UT_Matrix4T< T > &src) const
#define SYS_DECLARE_IS_POD(T)
Declare a type as POD.
iterator begin()
Definition: UT_Array.h:986
long long int64
Definition: SYS_Types.h:116
UT_Array< GA_AttributeUPtr > AttribPtrArray
#define GU_API
Definition: GU_API.h:14
GLuint const GLchar * name
Definition: glcorearb.h:786
GA_Size GA_Index
Define the strictness of GA_Offset/GA_Index.
Definition: GA_Types.h:635
GA_API const UT_StringHolder transform
GLenum GLenum dst
Definition: glcorearb.h:1793
Quaternion class.
Definition: GEO_Detail.h:48
const UT_StringHolder & regionName(int i) const
static const char * SKIN_BLEND_DUAL_QUATERNION_AND_LINEAR
static const char * SKIN_DUAL_QUATERNION
SYS_FORCE_INLINE UT_QuaternionT< T > rotate(const UT_QuaternionT< T > &src) const
SYS_FORCE_INLINE UT_Vector3T< T > rotate(const UT_Vector3T< T > &src) const
static const char * SKIN_LINEAR
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
void setSrcGdp(const GU_Detail &src)
const GU_Detail * srcGdp() const
Returns the source detail.
int numRegions() const
Return the number of regions found by initSrc()
type
Definition: core.h:1059
GU_DualQuatXformT< float > DualQuatXformF
GLenum src
Definition: glcorearb.h:1793