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_TaskList.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  exint numPoints() const
191  { return myPointStarts.entries() > 0
192  ? myPointStarts.entries()-1 : 0; }
193 
194  /// Return the number of regions found by initSrc()
195  int numRegions() const
196  { return myRegionXforms.entries(); }
197 
198  /// Return the name given the region index. init() must have been
199  /// called first.
200  const UT_StringHolder & regionName(int i) const
201  { return myRegionNames[i]; }
202 
203  /// Return the transform given the region index. init() must have been
204  /// called first.
205  const UT_Matrix4F& regionXform(int i) const
206  { return myRegionXforms[i]; }
207 
208  /// Returns whether the region is referenced by at least one capture
209  /// element.
210  bool usesRegion(int i) const
211  { return myUsedRegions.getBitFast(i); }
212 
213  /// Static utility method to get capture parameters
214  static bool getCaptureParms(
215  const GU_Detail& src,
216  GA_ROAttributeRef& pcapt,
217  GEO_AttributeCapturePath& attr_cap_path,
218  UT_Array<UT_Matrix4F>& xforms,
219  int& max_pt_regions);
220 
221  using CaptureElementRange =
223 
224  /// Returns the range of capture elements for the given point index.
225  CaptureElementRange captureElementRange(exint ptidx) const;
226 
227 private:
228  const GU_Detail* myGdp;
229  GA_OffsetArray myPointOffsets;
230  UT_ExintArray myPointStarts;
231  GU_CaptureElementArray myCaptureElements;
232  /// Primitives in the source detail that we will update transforms for.
233  GA_OffsetArray myPrimOffsets;
234  /// Index of the first primitive from the point range.
235  GA_Index myPrimStartIdx;
236 
237  UT_StringArray myRegionNames;
238  UT_Array<UT_Matrix4F> myRegionXforms;
239  UT_BitArray myUsedRegions;
240 
241  friend class GU_LinearSkinDeformer;
242 };
243 
246 {
247  return UTmakeRange(myCaptureElements.begin() + myPointStarts[ptidx],
248  myCaptureElements.begin() + myPointStarts[ptidx + 1]);
249 }
250 
251 /// Performs linear blend skinning of geometry
253 {
254 public:
256 
257  /// Reset all state
258  void reset();
259 
260  enum Method
261  {
265  };
266 
267  /// Setup the destination geometry. Fails if the destination is missing
268  /// attributes that were appended to deform. A reference to the src is
269  /// maintained until reset() is called.
270  bool init(
271  GU_Detail& dst,
272  const GA_Range& pt_range,
273  const GU_LinearSkinDeformerSourceWeights& src_weights,
274  const GU_LinearSkinDeformerSourceAttribs& src_attribs,
275  Method method = DEFORM_LINEAR,
276  bool create_missing_attribs = false,
277  const char *blend_attrib = nullptr);
278 
279  int numRegions() const
280  { return mySrcWeights->myRegionXforms.entries(); }
281 
282  const UT_StringHolder & regionName(int i) const
283  { return mySrcWeights->regionName(i); }
284 
285  /// For debugging purposes, call this before making your
286  /// setRegionTransform() calls to avoid asserts about missing transforms.
288  { UT_IF_ASSERT(myNumTransformsSet=0;) }
289 
290  /// Set deforming transform for region_idx, which matches indices found in
291  /// the capture weight attribute. init() must have been called first.
292  void setRegionTransform(
293  int region_idx,
294  const UT_Matrix4F& xform);
295 
296  /// Set deforming transform for region_idx. To apply the capture region's
297  /// transform use setRegionTransform(). init() must have been called first.
298  void setFullRegionTransform(
299  int region_idx,
300  const UT_Matrix4F& xform);
301 
302  /// Set transforms relative to capture region transforms from
303  /// P,name,transform attributes. This matches with
304  /// GU_LinearSkinDeformerSourceWeights::setRegionXformsFromGeo()
305  bool setRegionTransformsFromGeo(
306  const GU_Detail& anim_skel);
307 
308  /// Append UT_Tasks that will perform the deformation. The tasks will have
309  /// references to this object, so they must be executed before this object
310  /// is destroyed.
311  ///
312  /// The necessary steps in this specific order:
313  /// 1. N = GU_LinearSkinDeformerSource::init() for the point geometry you
314  /// want to deform
315  /// 2. GU_LinearSkinDeformerSource::appendAttrib() for each src attribute
316  /// you want to deform
317  /// 3. GU_LinearSkinDeformer::init() to set up where to put the results
318  /// 4. Call setRegionTransform() N times for each of the cregions
319  /// 5. Call appendDeformTasks()
320  /// 6. When done with the task list, spawn them: tasks.spawnRootAndWait();
321  ///
322  void appendDeformTasks(
323  UT_TaskList& tasks);
324  void appendInverseDeformTasks(
325  UT_TaskList& tasks);
326 
327  /// Do the deform.
328  ///
329  /// The necessary steps in this specific order:
330  /// 1. N = GU_LinearSkinDeformerSource::init() for the point geometry you
331  /// want to deform
332  /// 2. GU_LinearSkinDeformerSource::appendAttrib() for each src attribute
333  /// you want to deform
334  /// 3. GU_LinearSkinDeformer::init() to set up where to put the results
335  /// 4. Call setRegionTransform() N times for each of the cregions
336  /// 5. Call deform()
337  ///
338  void deform();
339  void inverse_deform();
340 
341 public:
344 
345  static const char* SKIN_LINEAR;
346  static const char* SKIN_DUAL_QUATERNION;
348 
349  static bool getGlobalAttribMethod(const GU_Detail *igdp, Method &type);
350  static bool getGlobalAttribBlendAttrib(const GU_Detail *igdp,
351  UT_StringHolder &blend_attrib);
352 
353 private:
354 
355  void clearXforms();
356 
357  void deformInParallel();
358 
359  template <bool ALIGNED, bool INVERT>
360  void appendLinearTasks(
361  UT_TaskList& tasks);
362  template <bool ALIGNED, bool INVERT>
363  void appendDualQuatTasks(
364  UT_TaskList& tasks);
365  template <bool ALIGNED, bool INVERT>
366  void appendBlendedDualQuatTasks(
367  UT_TaskList& tasks);
368 
369 private:
370  Method myMethod;
371 
372  GU_Detail* myDstGdp;
373  GA_Range myDstRange;
374  UT_Array<GA_Attribute*> myDstPosAttribs;
375  UT_Array<GA_Attribute*> myDstVecAttribs;
376  UT_Array<GA_Attribute*> myDstNmlAttribs;
377  UT_Array<GA_Attribute*> myDstQuatAttribs;
378  UT_Array<GA_Attribute*> myDstMat3Attribs;
379  UT_Array<GA_Attribute*> myDstMat4Attribs;
380 
381  const GU_LinearSkinDeformerSourceWeights* mySrcWeights;
382  const GU_LinearSkinDeformerSourceAttribs* mySrcAttribs;
383 
384  GA_ROHandleF mySrcBlendAttrib;
385 
386  AttribPtrArray mySrcPromotedAttribs;
387 
388  // Linear blending
389  UT_Array<UT_Matrix4F> myPosXforms;
390  UT_Array<UT_QuaternionF> myQuatXforms;
391 
392  // DualQuaternion blending
393  UT_Array<DualQuatXformF> myDualQuatXforms;
394 
395  // This is only used when assertions are enabled
396  exint myNumTransformsSet;
397 
398  UT_TaskList myTasks;
399 };
400 
401 #endif // __GU_LINEARSKINDEFORMER_H_INCLUDED__
const UT_Matrix4F & regionXform(int i) const
Definition of a geometry attribute.
Definition: GA_Attribute.h:196
void leftMult(const UT_SymMatrix3T< S > &m)
Multiply given symmetric matrix on the left.
Definition: UT_Matrix3.h:340
*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:629
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
GLuint const GLchar * name
Definition: glcorearb.h:785
Performs linear blend skinning of geometry.
#define UT_IF_ASSERT(ZZ)
Definition: UT_Assert.h:189
GLenum src
Definition: glcorearb.h:1792
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
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
double fpreal64
Definition: SYS_Types.h:201
Class representing source capture weight data for GU_LinearSkinDeformer.
GLuint GLenum GLenum transform
Definition: glew.h:15055
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
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:817
long long int64
Definition: SYS_Types.h:116
UT_Array< GA_AttributeUPtr > AttribPtrArray
#define GU_API
Definition: GU_API.h:14
GLboolean reset
Definition: glew.h:4989
GA_Size GA_Index
Define the strictness of GA_Offset/GA_Index.
Definition: GA_Types.h:634
Quaternion class.
Definition: UT_Quaternion.h:51
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
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()
GLenum GLenum dst
Definition: glcorearb.h:1792
GU_DualQuatXformT< float > DualQuatXformF