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  // Note that we have to apply this in the REVERSE order here
124  // because src and m here are both quaternions.
125  //
126  // (q1 * q2) * v * (q1 * q2)^*
127  // ==> q1 * q2 * v * q2^* * q1^*
128  // ==> q1 * (q2 * v * q2^*) * q1^*
129  //
130  // This implies that q2 is applied to v, followed by q1.
131  // Meaning => matrix(q1 * q2) = matrix(q2) * matrix(q1).
132  // Fixes bad results from bug 156035.
133  //
134  return myDQ.getRotation() * src;
135  }
136 
139 };
142 
143 /// Stores the source geometry and attributes to deform, for
144 /// GU_LinearSkinDeformer.
146 {
147 public:
148  GU_LinearSkinDeformerSourceAttribs(const GU_Detail *gdp);
149 
150  int64 getMemoryUsage(bool inclusive) const;
151 
152  /// Clear the list of attributes and rebind to a different detail.
153  void reset(const GU_Detail *gdp);
154 
155  /// Returns the source detail.
156  const GU_Detail *srcGdp() const { return myGdp; }
157 
158  /// Append attribute to be deformed. How it is deformed depends on the
159  /// attribute's GA_TypeInfo.
160  void append(const GA_Attribute &src_attrib);
161 
162 private:
163  const GU_Detail *myGdp;
164  UT_Array<const GA_Attribute *> myPosAttribs;
165  UT_Array<const GA_Attribute *> myVecAttribs;
166  UT_Array<const GA_Attribute *> myNmlAttribs;
167  UT_Array<const GA_Attribute *> myQuatAttribs;
168  UT_Array<const GA_Attribute *> myMat3Attribs;
169  UT_Array<const GA_Attribute *> myMat4Attribs;
170 
171  friend class GU_LinearSkinDeformer;
172 };
173 
174 /// Class representing source capture weight data for GU_LinearSkinDeformer
176 {
177 public:
179 
180  int64 getMemoryUsage(bool inclusive) const;
181 
182  /// Reset all state
183  void reset();
184 
185  /// Set up from the source geometry. Returns the number of transforms
186  /// required to deform using the capture weight attribute. If in error,
187  /// then 0 is returned.
188  /// If max_pt_weights > 0, then it will limit the number of weight entries
189  /// to use per point.
190  /// @{
191  int init(
192  const GU_Detail& src,
193  const GA_Range& pt_range,
194  bool use_opencl = false,
195  int max_pt_weights = 0);
196  int init(
197  const GU_Detail& src,
198  const GA_Range& pt_range,
199  const UT_StringRef &capt_attrib_name,
200  bool use_opencl = false,
201  int max_pt_weights = 0);
202  /// @}
203 
205  { return myCaptAttribName; }
206 
207  const GU_Detail* srcGdp() const
208  { return myGdp; }
209  void setSrcGdp(const GU_Detail &src)
210  { myGdp = &src; }
211 
212  /// Set new region transforms from point skeleton geometry with P, name,
213  /// and transform. It will invert transform to match what getCaptureParms()
214  /// returns.
215  bool setRegionXformsFromGeo(
216  const GU_Detail& rest_skel,
217  const GA_Attribute& P,
218  const GA_Attribute& name,
219  const GA_Attribute& transform);
220 
221  /// Number of points in the range given to init().
222  exint numPoints() const { return myNumPoints; }
223 
224  /// Return the number of regions found by initSrc()
225  int numRegions() const
226  { return myRegionXforms.entries(); }
227 
228  /// Return the name given the region index. init() must have been
229  /// called first.
230  const UT_StringHolder & regionName(int i) const
231  { return myRegionNames[i]; }
232 
233  /// Return the transform given the region index. init() must have been
234  /// called first.
235  const UT_Matrix4F& regionXform(int i) const
236  { return myRegionXforms[i]; }
237 
238  /// Return if myRegionXforms has been initialized
239  bool haveRegionXforms() const
240  { return myHaveRegionXforms; }
241 
242  /// Returns whether the region is referenced by at least one capture
243  /// element.
244  bool usesRegion(int i) const
245  { return myUsedRegions.getBitFast(i); }
246 
247  /// Static utility method to get capture parameters
248  /// @{
249  static bool getCaptureParms(
250  const GU_Detail& src,
251  GA_ROAttributeRef& pcapt,
252  GEO_AttributeCapturePath& attr_cap_path,
253  UT_Array<UT_Matrix4F>& xforms,
254  int& max_pt_regions,
255  bool& have_region_xforms);
256  static bool getCaptureParms(
257  const GU_Detail& src,
258  const UT_StringRef &capt_attrib_name,
259  GA_ROAttributeRef& pcapt,
260  GEO_AttributeCapturePath& attr_cap_path,
261  UT_Array<UT_Matrix4F>& xforms,
262  int& max_pt_regions,
263  bool& have_region_xforms);
264  /// @}
265 
266  using CaptureElementRange =
268 
269  /// Returns the range of capture elements for the given point index.
270  CaptureElementRange captureElementRange(exint ptidx) const;
271 
272 private:
273  /// Return the array of indices(int) and weights(float) from myCaptureElements for OpenCL kernel
274  template <typename ELEMENT_TYPE>
275  UT_Array<ELEMENT_TYPE> getCaptureElementsArray() const;
276 
277  /// Set the static arguments which will not be changed per frame
278  void setupStaticBufferOCL();
279 
280  /// Clear up OpenCL buffers
281  void clearOCL();
282 
283 private:
284  const GU_Detail* myGdp;
285  UT_StringHolder myCaptAttribName;
286  GA_OffsetArray myPointOffsets;
287  UT_ExintArray myPointStarts;
288  GU_CaptureElementArray myCaptureElements;
289  /// Number of points in the range passed to init(). This may not be the same
290  /// as myPointOffsets.size() if the range is not contiguous.
291  exint myNumPoints;
292  /// Primitives in the source detail that we will update transforms for.
293  GA_OffsetArray myPrimOffsets;
294  /// Index of the first primitive from the point range.
295  GA_Index myPrimStartIdx;
296 
297  UT_StringArray myRegionNames;
298  UT_Array<UT_Matrix4F> myRegionXforms;
299  UT_BitArray myUsedRegions;
300 
301  /// Topology CE Attribute
302  GA_CEAttributePtr myPtToVtxCEAttrib;
303 
304  /// Buffers are updated during init(), not every frame.
305  CE_BufferDevice<exint> myPtStartBuf;
306  CE_BufferDevice<int> myCaptureElementsIndexBuf;
307  CE_BufferDevice<float> myCaptureElementsWeightBuf;
308 
309  bool myUseOpenCL;
310  bool myHaveRegionXforms;
311 
312  friend class GU_LinearSkinDeformer;
313 };
314 
317 {
318  return UTmakeRange(myCaptureElements.begin() + myPointStarts[ptidx],
319  myCaptureElements.begin() + myPointStarts[ptidx + 1]);
320 }
321 
322 /// Performs linear blend skinning of geometry
324 {
325 public:
327 
328  /// Reset all state
329  void reset();
330 
331  enum Method
332  {
336  };
337 
338 
340  {
347  MAT4D
348  };
349 
350  /// Setup the destination geometry. Fails if the destination is missing
351  /// attributes that were appended to deform. A reference to the src is
352  /// maintained until reset() is called.
353  bool init(
354  GU_Detail& dst,
355  const GA_Range& pt_range,
356  const GU_LinearSkinDeformerSourceWeights& src_weights,
357  const GU_LinearSkinDeformerSourceAttribs& src_attribs,
358  Method method = DEFORM_LINEAR,
359  bool create_missing_attribs = false,
360  const char *blend_attrib = nullptr);
361 
362  int numRegions() const
363  { return mySrcWeights->myRegionXforms.entries(); }
364 
365  const UT_StringHolder & regionName(int i) const
366  { return mySrcWeights->regionName(i); }
367 
368  /// For debugging purposes, call this before making your
369  /// setRegionTransform() calls to avoid asserts about missing transforms.
371  { UT_IF_ASSERT(myNumTransformsSet=0;) }
372 
373  /// Set deforming transform for region_idx, which matches indices found in
374  /// the capture weight attribute. init() must have been called first.
375  void setRegionTransform(
376  int region_idx,
377  const UT_Matrix4F& xform);
378 
379  /// Set deforming transform for region_idx. To apply the capture region's
380  /// transform use setRegionTransform(). init() must have been called first.
381  void setFullRegionTransform(
382  int region_idx,
383  const UT_Matrix4F& xform);
384 
385  /// Set transforms relative to capture region transforms from
386  /// P,name,transform attributes. This matches with
387  /// GU_LinearSkinDeformerSourceWeights::setRegionXformsFromGeo()
388  bool setRegionTransformsFromGeo(
389  const GU_Detail& anim_skel);
390 
391  /// Spawn tasks that will perform the deformation. The tasks will have
392  /// references to this object, so they must be executed before this object
393  /// is destroyed.
394  ///
395  /// The necessary steps in this specific order:
396  /// 1. N = GU_LinearSkinDeformerSource::init() for the point geometry you
397  /// want to deform
398  /// 2. GU_LinearSkinDeformerSource::appendAttrib() for each src attribute
399  /// you want to deform
400  /// 3. GU_LinearSkinDeformer::init() to set up where to put the results
401  /// 4. Call setRegionTransform() N times for each of the cregions
402  /// 5. Call spawnDeformTasks()
403  /// 6. When done with the task list, spawn them: tasks.spawnRootAndWait();
404  ///
405  /// @{
406  void spawnDeformTasks(
407  UT_TaskGroup& tasks);
408  void spawnInverseDeformTasks(
409  UT_TaskGroup& tasks);
410  /// @}
411 
412  /// Do the deform.
413  ///
414  /// The necessary steps in this specific order:
415  /// 1. N = GU_LinearSkinDeformerSource::init() for the point geometry you
416  /// want to deform
417  /// 2. GU_LinearSkinDeformerSource::appendAttrib() for each src attribute
418  /// you want to deform
419  /// 3. GU_LinearSkinDeformer::init() to set up where to put the results
420  /// 4. Call setRegionTransform() N times for each of the cregions
421  /// 5. Call deform()
422  ///
423  /// @{
424  void deform();
425  void inverseDeform();
426  /// @}
427 
428 public:
431 
432  static const char* SKIN_LINEAR;
433  static const char* SKIN_DUAL_QUATERNION;
435 
436  static bool getGlobalAttribMethod(const GU_Detail *igdp, Method &type);
437  static bool getGlobalAttribBlendAttrib(const GU_Detail *igdp,
438  UT_StringHolder &blend_attrib);
439 
440 private:
441 
442  void clearXforms();
443 
444  void deformInParallel();
445 
446  template <bool ALIGNED, bool INVERT>
447  void spawnLinearTasks(
448  UT_TaskGroup& tasks);
449  template <bool ALIGNED, bool INVERT>
450  void spawnDualQuatTasks(
451  UT_TaskGroup& tasks);
452  template <bool ALIGNED, bool INVERT>
453  void spawnBlendedDualQuatTasks(
454  UT_TaskGroup& tasks);
455 
456  /// OpenCL
457  void initializeOpenCL();
458  void deformOCL();
459  /// clear up OpenCL buffers
460  void clearOCL();
461 
462  template <Method METHOD>
463  void processDeformOCL();
464 
465  template <Method METHOD, AttributeType ATTRIB_TYPE>
466  void deformAttribOCL(
467  const UT_Array<const GA_Attribute*>& src_attribs,
468  UT_Array<GA_Attribute*>& dst_attribs,
469  GA_Size total_point,
470  GA_Size deform_point,
471  GA_Index dst_start,
472  GA_Index dst_end);
473 
474  template <Method METHOD>
475  void deformPrimCPU(GA_Index dst_start);
476 
477  void setupFrameSharedBufferOCL();
478 
479  template <typename BLEND_TYPE>
480  void setBlendKernelArgOCL(GA_Size point_num);
481  template <typename BLEND_TYPE>
482  void blendDeformOCL(GA_Size point_num);
483 
484  template < Method METHOD, GA_AttributeOwner ATTRIB_OWNER, AttributeType ATTRIB_TYPE>
485  void setApplyKernelArgOCL(
486  const GA_Attribute* src_attrib,
487  GA_Attribute* dst_attrib,
488  GA_Size point_num,
489  GA_Index dst_start, GA_Index dst_end);
490 
491  template <Method METHOD, GA_AttributeOwner ATTRIB_OWNER, AttributeType ATTRIB_TYPE>
492  void applyDeformOCL(
493  const GA_Attribute* src_attrib,
494  GA_Attribute* dst_attrib,
495  GA_Size point_num,
496  GA_Index dst_start, GA_Index dst_end);
497 
498  void splitDualQuatArray();
499 
500  /// Helper functions for getting kernel name
501  template<Method METHOD>
502  UT_StringHolder getMethodString();
503 
504  template<AttributeType ATTRIB_TYPE>
505  UT_StringHolder getAttributeTypeString();
506 
507  template<GA_AttributeOwner ATTRIB_CLASS>
508  UT_StringHolder getAttributeClassString();
509 
510  template<typename BLEND_TYPE>
511  UT_StringHolder getBlendTypeString();
512 
513  template <typename BLEND_TYPE>
514  UT_StringHolder getBlendKernelName();
515 
516  template <
517  Method METHOD,
518  GA_AttributeOwner ATTRIB_CLASS,
519  AttributeType ATTRIB_TYPE>
520  UT_StringHolder getApplyKernelName(bool is_pt_attrib = true);
521 
522 private:
523  Method myMethod;
524 
525  GU_Detail* myDstGdp;
526  GA_Range myDstRange;
527  UT_Array<GA_Attribute*> myDstPosAttribs;
528  UT_Array<GA_Attribute*> myDstVecAttribs;
529  UT_Array<GA_Attribute*> myDstNmlAttribs;
530  UT_Array<GA_Attribute*> myDstQuatAttribs;
531  UT_Array<GA_Attribute*> myDstMat3Attribs;
532  UT_Array<GA_Attribute*> myDstMat4Attribs;
533 
534  const GU_LinearSkinDeformerSourceWeights* mySrcWeights;
535  const GU_LinearSkinDeformerSourceAttribs* mySrcAttribs;
536 
537  GA_ROHandleF mySrcBlendAttrib;
538 
539  AttribPtrArray mySrcPromotedAttribs;
540 
541  // Linear blending
542  UT_Array<UT_Matrix4F> myPosXforms;
543  UT_Array<UT_QuaternionF> myQuatXforms;
544 
545  // DualQuaternion blending
546  UT_Array<DualQuatXformF> myDualQuatXforms;
547 
548  // This is only used when assertions are enabled
549  exint myNumTransformsSet;
550 
551  exint mySrcBlendAttribId;
552  // OpenCL data
553  bool myCEInitialized;
554  cl::Program myProgram;
555  UT_StringMap<cl::Kernel> myKernelMap;
556 
557  CE_BufferDevice<float> myBlendFactorBuf;
558 
559  CE_BufferDevice<UT_Matrix4F> myXformMatsBuf;
560  CE_BufferDevice<UT_QuaternionF> myXformQuatsBuf;
561 
562  UT_Array<UT_QuaternionF> myXformRealQuats;
563  UT_Array<UT_QuaternionF> myXformDualQuats;
564  UT_Array<UT_Matrix3F> myXformMat3Stretch;
565 
566  CE_BufferDevice<UT_QuaternionF> myXformRealQuatsBuf;
567  CE_BufferDevice<UT_QuaternionF> myXformDualQuatsBuf;
568  CE_BufferDevice<UT_Matrix3F> myXformMat3StretchBuf;
569 
570  CE_BufferDevice<UT_Matrix4F> myBlendMatsBuf;
571  CE_BufferDevice<UT_QuaternionF> myBlendQuatsBuf;
572 
573  CE_BufferDevice<UT_QuaternionF> myBlendRealQuatsBuf;
574  CE_BufferDevice<UT_QuaternionF> myBlendDualQuatsBuf;
575  CE_BufferDevice<UT_Matrix3F> myBlendMat3StretchBuf;
576 
577 };
578 
579 #endif // __GU_LINEARSKINDEFORMER_H_INCLUDED__
UT_SharedPtr< GA_CEAttribute > GA_CEAttributePtr
Definition: GA_Attribute.h:56
const UT_Matrix4F & regionXform(int i) const
Definition of a geometry attribute.
Definition: GA_Attribute.h:203
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
void deform(OUTPOS &newposdata, const INPOS &points, const DEFRESTPOS &constrestpos, const DEFANIMPOS &constanimpos, const GU_Detail &defgdp, const GA_ROHandleV3 restnmlattrib, const GA_ROHandleV3 resttanattrib, const GA_ROHandleV3 animnmlattrib, const GA_ROHandleV3 animtanattrib, const UT_IntArray &primptstarts, const GA_OffsetArray &ptoffsets, const UT_FloatArray &ptweights)
Performs linear blend skinning of geometry.
#define UT_IF_ASSERT(ZZ)
Definition: UT_Assert.h:183
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:243
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.
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:1039
long long int64
Definition: SYS_Types.h:116
UT_Array< GA_AttributeUPtr > AttribPtrArray
const UT_StringHolder & captAttribName() const
#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:647
GA_API const UT_StringHolder transform
GLenum GLenum dst
Definition: glcorearb.h:1793
bool haveRegionXforms() const
Return if myRegionXforms has been initialized.
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
GU_API void xform(CE_Context &context, bool recompile, int npts, const cl::Buffer &outPos, const cl::Buffer &inPos, const cl::Buffer &surfacexform, const cl::Buffer *grp=nullptr)
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