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"
16 
17 #include <CE/CE_BufferDevice.h>
18 
19 #include <GA/GA_CEAttribute.h>
20 #include <GA/GA_Range.h>
21 #include <GA/GA_Types.h>
22 
24 
25 #include <UT/UT_Array.h>
26 #include <UT/UT_Assert.h>
27 #include <UT/UT_DualQuaternion.h>
28 #include <UT/UT_IteratorRange.h>
29 #include <UT/UT_Matrix3.h>
30 #include <UT/UT_Matrix4.h>
31 #include <UT/UT_NonCopyable.h>
32 #include <UT/UT_Quaternion.h>
33 #include <UT/UT_StringHolder.h>
34 #include <UT/UT_StringMap.h>
35 #include <UT/UT_TaskGroup.h>
36 #include <UT/UT_UniquePtr.h>
37 #include <UT/UT_VectorTypes.h>
38 
39 #include <SYS/SYS_Inline.h>
40 #include <SYS/SYS_StaticAssert.h>
41 #include <SYS/SYS_TypeDecorate.h>
42 #include <SYS/SYS_Types.h>
43 
44 #include <stddef.h>
45 
46 class GA_Attribute;
47 class GA_ROAttributeRef;
49 class GU_Detail;
51 
53 {
55  GU_CaptureElement(int i, float w) : myI(i), myW(w) { }
56 
57  bool operator>(const GU_CaptureElement& elem) const
58  {
59  return (myW > elem.myW);
60  }
61 
62  int myI;
63  float myW;
64 };
67 
68 
69 template <typename T>
71 {
73 
74  SYS_FORCE_INLINE GU_DualQuatXformT() = default;
75  SYS_FORCE_INLINE GU_DualQuatXformT(const ThisType&) = default;
76  SYS_FORCE_INLINE GU_DualQuatXformT(ThisType&&) = default;
78  ThisType& operator=(const GU_DualQuatXformT<T>&) = default;
81 
84  {
86  myDQ.transform(src * myStretch, dst);
87  return dst;
88  }
91  {
93  myDQ.transform(src, dst);
94  dst *= myStretch;
95  return dst;
96  }
99  {
101  myDQ.getRotation().getRotationMatrix(dst);
102  dst.leftMult(src * myStretch);
103  return dst;
104  }
107  {
109  dst *= myStretch;
110  dst *= myDQ.convertToXform();
111  return dst;
112  }
115  {
117  myDQ.rotate(src, dst);
118  return dst;
119  }
122  {
123  return src * myDQ.getRotation();
124  }
125 
128 };
131 
132 /// Stores the source geometry and attributes to deform, for
133 /// GU_LinearSkinDeformer.
135 {
136 public:
137  GU_LinearSkinDeformerSourceAttribs(const GU_Detail *gdp);
138 
139  int64 getMemoryUsage(bool inclusive) const;
140 
141  /// Clear the list of attributes and rebind to a different detail.
142  void reset(const GU_Detail *gdp);
143 
144  /// Returns the source detail.
145  const GU_Detail *srcGdp() const { return myGdp; }
146 
147  /// Append attribute to be deformed. How it is deformed depends on the
148  /// attribute's GA_TypeInfo.
149  void append(const GA_Attribute &src_attrib);
150 
151 private:
152  const GU_Detail *myGdp;
153  UT_Array<const GA_Attribute *> myPosAttribs;
154  UT_Array<const GA_Attribute *> myVecAttribs;
155  UT_Array<const GA_Attribute *> myNmlAttribs;
156  UT_Array<const GA_Attribute *> myQuatAttribs;
157  UT_Array<const GA_Attribute *> myMat3Attribs;
158  UT_Array<const GA_Attribute *> myMat4Attribs;
159 
160  friend class GU_LinearSkinDeformer;
161 };
162 
163 /// Class representing source capture weight data for GU_LinearSkinDeformer
165 {
166 public:
168 
169  int64 getMemoryUsage(bool inclusive) const;
170 
171  /// Reset all state
172  void reset();
173 
174  /// Set up from the source geometry. Returns the number of transforms
175  /// required to deform using the capture weight attribute. If in error,
176  /// then 0 is returned.
177  /// If max_pt_weights > 0, then it will limit the number of weight entries
178  /// to use per point.
179  int init(
180  const GU_Detail& src,
181  const GA_Range& pt_range,
182  bool use_opencl = false,
183  int max_pt_weights = 0);
184 
185  const GU_Detail* srcGdp() const
186  { return myGdp; }
187  void setSrcGdp(const GU_Detail &src)
188  { myGdp = &src; }
189 
190  /// Set new region transforms from point skeleton geometry with P, name,
191  /// and transform. It will invert transform to match what getCaptureParms()
192  /// returns.
193  bool setRegionXformsFromGeo(
194  const GU_Detail& rest_skel,
195  const GA_Attribute& P,
196  const GA_Attribute& name,
197  const GA_Attribute& transform);
198 
199  /// Number of points in the range given to init().
200  exint numPoints() const { return myNumPoints; }
201 
202  /// Return the number of regions found by initSrc()
203  int numRegions() const
204  { return myRegionXforms.entries(); }
205 
206  /// Return the name given the region index. init() must have been
207  /// called first.
208  const UT_StringHolder & regionName(int i) const
209  { return myRegionNames[i]; }
210 
211  /// Return the transform given the region index. init() must have been
212  /// called first.
213  const UT_Matrix4F& regionXform(int i) const
214  { return myRegionXforms[i]; }
215 
216  /// Returns whether the region is referenced by at least one capture
217  /// element.
218  bool usesRegion(int i) const
219  { return myUsedRegions.getBitFast(i); }
220 
221  /// Static utility method to get capture parameters
222  static bool getCaptureParms(
223  const GU_Detail& src,
224  GA_ROAttributeRef& pcapt,
225  GEO_AttributeCapturePath& attr_cap_path,
226  UT_Array<UT_Matrix4F>& xforms,
227  int& max_pt_regions);
228 
229  using CaptureElementRange =
231 
232  /// Returns the range of capture elements for the given point index.
233  CaptureElementRange captureElementRange(exint ptidx) const;
234 
235 private:
236  /// Return the array of indices(int) and weights(float) from myCaptureElements for OpenCL kernel
237  template <typename ELEMENT_TYPE>
238  UT_Array<ELEMENT_TYPE> getCaptureElementsArray() const;
239 
240  /// Set the static arguments which will not be changed per frame
241  void setupStaticBufferOCL();
242 
243  /// Clear up OpenCL buffers
244  void clearOCL();
245 
246 private:
247  const GU_Detail* myGdp;
248  GA_OffsetArray myPointOffsets;
249  UT_ExintArray myPointStarts;
250  GU_CaptureElementArray myCaptureElements;
251  /// Number of points in the range passed to init(). This may not be the same
252  /// as myPointOffsets.size() if the range is not contiguous.
253  exint myNumPoints;
254  /// Primitives in the source detail that we will update transforms for.
255  GA_OffsetArray myPrimOffsets;
256  /// Index of the first primitive from the point range.
257  GA_Index myPrimStartIdx;
258 
259  UT_StringArray myRegionNames;
260  UT_Array<UT_Matrix4F> myRegionXforms;
261  UT_BitArray myUsedRegions;
262 
263  bool myUseOpenCL;
264 
265  /// Topology CE Attribute
266  UT_UniquePtr<GA_CEAttribute> myPtToVtxCEAttrib;
267 
268  /// Buffers are updated during init(), not every frame.
269  CE_BufferDevice<exint> myPtStartBuf;
270  CE_BufferDevice<int> myCaptureElementsIndexBuf;
271  CE_BufferDevice<float> myCaptureElementsWeightBuf;
272 
273  friend class GU_LinearSkinDeformer;
274 };
275 
278 {
279  return UTmakeRange(myCaptureElements.begin() + myPointStarts[ptidx],
280  myCaptureElements.begin() + myPointStarts[ptidx + 1]);
281 }
282 
283 /// Performs linear blend skinning of geometry
285 {
286 public:
288 
289  /// Reset all state
290  void reset();
291 
292  enum Method
293  {
297  };
298 
299 
301  {
308  MAT4D
309  };
310 
311  /// Setup the destination geometry. Fails if the destination is missing
312  /// attributes that were appended to deform. A reference to the src is
313  /// maintained until reset() is called.
314  bool init(
315  GU_Detail& dst,
316  const GA_Range& pt_range,
317  const GU_LinearSkinDeformerSourceWeights& src_weights,
318  const GU_LinearSkinDeformerSourceAttribs& src_attribs,
319  Method method = DEFORM_LINEAR,
320  bool create_missing_attribs = false,
321  const char *blend_attrib = nullptr);
322 
323  int numRegions() const
324  { return mySrcWeights->myRegionXforms.entries(); }
325 
326  const UT_StringHolder & regionName(int i) const
327  { return mySrcWeights->regionName(i); }
328 
329  /// For debugging purposes, call this before making your
330  /// setRegionTransform() calls to avoid asserts about missing transforms.
332  { UT_IF_ASSERT(myNumTransformsSet=0;) }
333 
334  /// Set deforming transform for region_idx, which matches indices found in
335  /// the capture weight attribute. init() must have been called first.
336  void setRegionTransform(
337  int region_idx,
338  const UT_Matrix4F& xform);
339 
340  /// Set deforming transform for region_idx. To apply the capture region's
341  /// transform use setRegionTransform(). init() must have been called first.
342  void setFullRegionTransform(
343  int region_idx,
344  const UT_Matrix4F& xform);
345 
346  /// Set transforms relative to capture region transforms from
347  /// P,name,transform attributes. This matches with
348  /// GU_LinearSkinDeformerSourceWeights::setRegionXformsFromGeo()
349  bool setRegionTransformsFromGeo(
350  const GU_Detail& anim_skel);
351 
352  /// Spawn tasks that will perform the deformation. The tasks will have
353  /// references to this object, so they must be executed before this object
354  /// is destroyed.
355  ///
356  /// The necessary steps in this specific order:
357  /// 1. N = GU_LinearSkinDeformerSource::init() for the point geometry you
358  /// want to deform
359  /// 2. GU_LinearSkinDeformerSource::appendAttrib() for each src attribute
360  /// you want to deform
361  /// 3. GU_LinearSkinDeformer::init() to set up where to put the results
362  /// 4. Call setRegionTransform() N times for each of the cregions
363  /// 5. Call spawnDeformTasks()
364  /// 6. When done with the task list, spawn them: tasks.spawnRootAndWait();
365  ///
366  /// @{
367  void spawnDeformTasks(
368  UT_TaskGroup& tasks);
369  void spawnInverseDeformTasks(
370  UT_TaskGroup& tasks);
371  /// @}
372 
373  /// Do the deform.
374  ///
375  /// The necessary steps in this specific order:
376  /// 1. N = GU_LinearSkinDeformerSource::init() for the point geometry you
377  /// want to deform
378  /// 2. GU_LinearSkinDeformerSource::appendAttrib() for each src attribute
379  /// you want to deform
380  /// 3. GU_LinearSkinDeformer::init() to set up where to put the results
381  /// 4. Call setRegionTransform() N times for each of the cregions
382  /// 5. Call deform()
383  ///
384  /// @{
385  void deform();
386  void inverseDeform();
387  /// @}
388 
389 public:
392 
393  static const char* SKIN_LINEAR;
394  static const char* SKIN_DUAL_QUATERNION;
396 
397  static bool getGlobalAttribMethod(const GU_Detail *igdp, Method &type);
398  static bool getGlobalAttribBlendAttrib(const GU_Detail *igdp,
399  UT_StringHolder &blend_attrib);
400 
401 private:
402 
403  void clearXforms();
404 
405  void deformInParallel();
406 
407  template <bool ALIGNED, bool INVERT>
408  void spawnLinearTasks(
409  UT_TaskGroup& tasks);
410  template <bool ALIGNED, bool INVERT>
411  void spawnDualQuatTasks(
412  UT_TaskGroup& tasks);
413  template <bool ALIGNED, bool INVERT>
414  void spawnBlendedDualQuatTasks(
415  UT_TaskGroup& tasks);
416 
417  /// OpenCL
418  void initializeOpenCL();
419  void deformOCL();
420  /// clear up OpenCL buffers
421  void clearOCL();
422 
423  template <Method METHOD>
424  void processDeformOCL();
425 
426  template <Method METHOD, AttributeType ATTRIB_TYPE>
427  void deformAttribOCL(
428  const UT_Array<const GA_Attribute*>& src_attribs,
429  UT_Array<GA_Attribute*>& dst_attribs,
430  GA_Size total_point,
431  GA_Size deform_point,
432  GA_Index dst_start,
433  GA_Index dst_end);
434 
435  template <Method METHOD>
436  void deformPrimCPU(GA_Index dst_start);
437 
438  void setupFrameSharedBufferOCL();
439 
440  template <typename BLEND_TYPE>
441  void setBlendKernelArgOCL(GA_Size point_num);
442  template <typename BLEND_TYPE>
443  void blendDeformOCL(GA_Size point_num);
444 
445  template < Method METHOD, GA_AttributeOwner ATTRIB_OWNER, AttributeType ATTRIB_TYPE>
446  void setApplyKernelArgOCL(
447  const GA_Attribute* src_attrib,
448  GA_Attribute* dst_attrib,
449  GA_Size point_num,
450  GA_Index dst_start, GA_Index dst_end);
451 
452  template <Method METHOD, GA_AttributeOwner ATTRIB_OWNER, AttributeType ATTRIB_TYPE>
453  void applyDeformOCL(
454  const GA_Attribute* src_attrib,
455  GA_Attribute* dst_attrib,
456  GA_Size point_num,
457  GA_Index dst_start, GA_Index dst_end);
458 
459  void splitDualQuatArray();
460 
461  /// Helper functions for getting kernel name
462  template<Method METHOD>
463  UT_StringHolder getMethodString();
464 
465  template<AttributeType ATTRIB_TYPE>
466  UT_StringHolder getAttributeTypeString();
467 
468  template<GA_AttributeOwner ATTRIB_CLASS>
469  UT_StringHolder getAttributeClassString();
470 
471  template<typename BLEND_TYPE>
472  UT_StringHolder getBlendTypeString();
473 
474  template <typename BLEND_TYPE>
475  UT_StringHolder getBlendKernelName();
476 
477  template <
478  Method METHOD,
479  GA_AttributeOwner ATTRIB_CLASS,
480  AttributeType ATTRIB_TYPE>
481  UT_StringHolder getApplyKernelName(bool is_pt_attrib = true);
482 
483 private:
484  Method myMethod;
485 
486  GU_Detail* myDstGdp;
487  GA_Range myDstRange;
488  UT_Array<GA_Attribute*> myDstPosAttribs;
489  UT_Array<GA_Attribute*> myDstVecAttribs;
490  UT_Array<GA_Attribute*> myDstNmlAttribs;
491  UT_Array<GA_Attribute*> myDstQuatAttribs;
492  UT_Array<GA_Attribute*> myDstMat3Attribs;
493  UT_Array<GA_Attribute*> myDstMat4Attribs;
494 
495  const GU_LinearSkinDeformerSourceWeights* mySrcWeights;
496  const GU_LinearSkinDeformerSourceAttribs* mySrcAttribs;
497 
498  GA_ROHandleF mySrcBlendAttrib;
499 
500  AttribPtrArray mySrcPromotedAttribs;
501 
502  // Linear blending
503  UT_Array<UT_Matrix4F> myPosXforms;
504  UT_Array<UT_QuaternionF> myQuatXforms;
505 
506  // DualQuaternion blending
507  UT_Array<DualQuatXformF> myDualQuatXforms;
508 
509  // This is only used when assertions are enabled
510  exint myNumTransformsSet;
511 
512  exint mySrcBlendAttribId;
513  // OpenCL data
514  bool myCEInitialized;
515  cl::Program myProgram;
516  UT_StringMap<cl::Kernel> myKernelMap;
517 
518  CE_BufferDevice<float> myBlendFactorBuf;
519 
520  CE_BufferDevice<UT_Matrix4F> myXformMatsBuf;
521  CE_BufferDevice<UT_QuaternionF> myXformQuatsBuf;
522 
523  UT_Array<UT_QuaternionF> myXformRealQuats;
524  UT_Array<UT_QuaternionF> myXformDualQuats;
525  UT_Array<UT_Matrix3F> myXformMat3Stretch;
526 
527  CE_BufferDevice<UT_QuaternionF> myXformRealQuatsBuf;
528  CE_BufferDevice<UT_QuaternionF> myXformDualQuatsBuf;
529  CE_BufferDevice<UT_Matrix3F> myXformMat3StretchBuf;
530 
531  CE_BufferDevice<UT_Matrix4F> myBlendMatsBuf;
532  CE_BufferDevice<UT_QuaternionF> myBlendQuatsBuf;
533 
534  CE_BufferDevice<UT_QuaternionF> myBlendRealQuatsBuf;
535  CE_BufferDevice<UT_QuaternionF> myBlendDualQuatsBuf;
536  CE_BufferDevice<UT_Matrix3F> myBlendMat3StretchBuf;
537 
538 };
539 
540 #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:632
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
exint GA_Size
Defines the bit width for index and offset types in GA.
Definition: GA_Types.h:236
GU_CaptureElement(int i, float w)
UT_DualQuaternionT< T > myDQ
A range of elements in an index-map.
Definition: GA_Range.h:42
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
double fpreal64
Definition: SYS_Types.h:201
Class representing source capture weight data for GU_LinearSkinDeformer.
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
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:1013
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:640
GA_API const UT_StringHolder transform
GLenum GLenum dst
Definition: glcorearb.h:1793
GA_AttributeOwner
Definition: GA_Types.h:35
Quaternion class.
Definition: GEO_Detail.h:49
const UT_StringHolder & regionName(int i) const
static const char * SKIN_BLEND_DUAL_QUATERNION_AND_LINEAR
LeafData & operator=(const LeafData &)=delete
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()
Program interface that implements cl_program.
Definition: cl.hpp:2649
GU_DualQuatXformT< float > DualQuatXformF
GLenum src
Definition: glcorearb.h:1793