HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_AgentClip.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_AgentClip.h (GU Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __GU_AgentClip__
12 #define __GU_AgentClip__
13 
14 #include "GU_API.h"
15 
16 #include "GU_AgentRig.h"
17 
18 #include <UT/UT_Array.h>
19 #include <UT/UT_Assert.h>
20 #include <UT/UT_IntrusivePtr.h>
21 #include <UT/UT_Matrix3.h>
22 #include <UT/UT_Matrix4.h>
24 #include <UT/UT_Quaternion.h>
25 #include <UT/UT_SharedPtr.h>
26 #include <UT/UT_StringArray.h>
27 #include <UT/UT_StringHolder.h>
28 #include <UT/UT_StringMap.h>
29 #include <UT/UT_SymMatrix3.h>
30 #include <UT/UT_ValArray.h>
31 #include <UT/UT_Vector3.h>
32 #include <UT/UT_VectorTypes.h>
33 #include <SYS/SYS_Inline.h>
34 #include <SYS/SYS_Math.h>
35 #include <SYS/SYS_Types.h>
36 
37 class CL_Clip;
39 class UT_BitArray;
40 class UT_StringArray;
41 
42 /// A factored transform geared for animation blending.
43 template <typename T>
45 {
46 public:
48 
50  GU_AgentXformT() = default;
51 
53  : myStretch(scale)
54  , myRotate(0, 0, 0, 0)
55  , myTranslate(0, 0, 0)
56  {
57  }
58 
59  const UT_SymMatrix3T<T>& stretch() const { return myStretch; }
60  const UT_QuaternionT<T>& rotate() const { return myRotate; }
61  const UT_Vector3T<T>& translate() const { return myTranslate; }
62 
63  void zero()
64  {
65  myStretch.zero();
66  myRotate.assign(0, 0, 0, 0);
67  myTranslate.assign(0, 0, 0);
68  }
69  void identity()
70  {
71  myStretch.identity();
72  myRotate.identity();
73  myTranslate.assign(0, 0, 0);
74  }
75 
76  /// Set the transform, in SRT/XYZ transform order.
77  /// The rotations are given in radians.
79  T tx, T ty, T tz,
80  T rx, T ry, T rz,
81  T sx, T sy, T sz)
82  {
84  myStretch.setScale(sx, sy, sz);
85  myRotate.updateFromEuler(UT_Vector3T<T>(rx, ry, rz), xord);
86  myTranslate.assign(tx, ty, tz);
87  }
88 
89  /// Set the transform, in SRT transform order.
90  /// The rotations are specified by a quaternion.
92  const UT_Vector3T<T> &t, const UT_QuaternionT<T> &r,
93  const UT_Vector3T<T> &s)
94  {
95  myStretch.setScale(s);
96  myRotate = r;
97  myTranslate = t;
98  }
99 
100  template <typename S>
102  S& tx, S& ty, S& tz,
103  S& rx, S& ry, S& rz,
104  S& sx, S& sy, S& sz) const
105  {
106  tx = myTranslate[0];
107  ty = myTranslate[1];
108  tz = myTranslate[2];
109 
111  UT_Vector3D r = myRotate.computeRotations(xord);
112  rx = r[0];
113  ry = r[1];
114  rz = r[2];
115 
116  sx = myStretch(0, 0);
117  sy = myStretch(1, 1);
118  sz = myStretch(2, 2);
119  }
120 
121  /// Set this to a linear interpolation of the two given transforms:
122  /// *this = a + t*(b - a)
123  void setLerp(const type& a, const type& b, T t)
124  {
125  myStretch.lerp(a.myStretch, b.myStretch, t);
126 
127  if (dot(a.myRotate, b.myRotate) >= 0)
128  myRotate.lerp(a.myRotate, b.myRotate, t);
129  else
130  myRotate.lerp(a.myRotate, -b.myRotate, t);
131  // NOTE: We don't normalize myRotate since this is already handled when
132  // we call UT_QuaternionT::getRotationMatrix().
133 
134  myTranslate = SYSlerp(a.myTranslate, b.myTranslate, t);
135  }
136 
137  void addScaled(T s, const type& xform)
138  {
139  myStretch += xform.myStretch * s;
140  if (dot(myRotate, xform.myRotate) >= 0)
141  myRotate += xform.myRotate * s;
142  else
143  myRotate += xform.myRotate * -s;
144  myTranslate += xform.myTranslate * s;
145  }
146 
147  /// Perform an additive blend with the specified percentage.
148  void concat(T t, const type& xform)
149  {
150  myRotate.normalize();
151 
152  UT_QuaternionT<T> additive_r = xform.myRotate;
153  additive_r.normalize();
154  UT_QuaternionT<T> new_r = additive_r * myRotate;
155 
156  if (dot(myRotate, new_r) < 0)
157  new_r.negate();
158 
159  myRotate.lerp(myRotate, new_r, t);
160  }
161 
162  void getMatrix4(UT_Matrix4T<T>& m) const
163  {
164  // Set m to the transform myStretch*myRotate*myTranslate
165  if (!myStretch.isIdentity())
166  {
167  UT_Matrix3T<T> sr;
168  myRotate.getRotationMatrix(sr);
169  sr.leftMult(myStretch);
170  m = sr;
171  }
172  else
173  myRotate.getTransformMatrix(m);
174 
175  m.setTranslates(myTranslate);
176  }
177 
178 private:
179  UT_SymMatrix3T<T> myStretch;
180  UT_QuaternionT<T> myRotate;
181  UT_Vector3T<T> myTranslate;
182 };
186 
187 // Declare as POD for UT_Array optimizations.
189 
191 typedef UT_IntrusivePtr<GU_AgentClip> GU_AgentClipPtr;
193 typedef UT_Array<GU_AgentClipConstPtr> GU_AgentClipPtrArray;
194 
195 
196 /// An agent motion clip
197 ///
198 /// It is represented as array of samples, where each sample has
199 /// transformsPerSample() number of transforms. These transforms can be "local"
200 /// (corresponding to the transform hierarchy of rig()), or "world" where they
201 /// are multiplied all the way up to a root node in the rig.
202 class GU_API GU_AgentClip : public UT_IntrusiveRefCounter<GU_AgentClip>
203 {
204 public:
205 
213 
214  /// Create an empty clip
215  static GU_AgentClipPtr addClip(
216  const char* name,
217  const GU_AgentRigConstPtr &rig);
218 
219  /// Create a clip given a CHOP clip file
220  static GU_AgentClipPtr addClipFromFile(
221  const char* name,
222  const char* filename,
223  const GU_AgentRigConstPtr& rig,
224  UT_StringArray& errors);
225 
226  /// Compute the world transforms 'matrices' from the local 'xforms'
227  /// corresponding to the transforms in 'rig'.
228  static void computeWorldTransforms(
229  const GU_AgentRig& rig,
230  const XformArray& xforms,
231  Matrix4Array& matrices);
232 
233  /// Compute the local transforms 'matrices' from the local 'xforms'
234  /// corresponding to the transforms in 'rig'.
235  static void computeLocalTransforms(
236  const GU_AgentRig& rig,
237  const XformArray& xforms,
238  Matrix4Array& matrices);
239 
240  /// Given the local transforms 'xforms' corresponding to 'rig', convert
241  /// them to world transforms in-place.
242  /// The optional 'in_world_space' array can be used to specify if some
243  /// transforms in 'xforms' are already in world space.
244  static void computeWorldTransforms(
245  const GU_AgentRig& rig,
246  const UT_BitArray *in_world_space,
247  Matrix4Array& xforms);
248 
249  /// Given the world transforms 'xforms' corresponding to 'rig', convert
250  /// them to local transforms in-place.
251  /// The optional 'in_world_space' array can be used to specify if only some
252  /// transforms in 'xforms' are currently in world space.
253  static void computeLocalTransforms(
254  const GU_AgentRig& rig,
255  const UT_BitArray *in_world_space,
256  Matrix4Array& xforms);
257 
258  /// Replaces whitespace, special characters, etc with underscores.
259  static void forceValidName(UT_String &clipname)
260  { clipname.forceValidVariableName(".-"); }
261 
262 private:
263  GU_AgentClip(const char* name,
264  const char *filename,
265  const GU_AgentRigConstPtr &rig)
266  : myName(name)
267  , myFileName(filename)
268  , myIsFile(filename != NULL)
269  , myNumXformTracks(0)
270  , myRig(rig)
271  , myStart(0)
272  , mySampleRate(24.0)
273  {
274  }
275 
276 public:
277 
278  ~GU_AgentClip();
279 
280  int64 getMemoryUsage(bool inclusive) const;
281 
282  /// Initialize this clip to a 2D array of identity transforms given by
283  /// 'num_transform_samples' columns each of length
284  /// 'num_transforms_per_sample'.
285  /// @pre num_transform_samples must be larger than 0.
286  /// @pre num_transforms_per_sample must be larger than 0.
287  void init(exint num_transform_samples,
288  exint num_transforms_per_sample);
289 
290  /// Load from clip.
291  void load(const CL_Clip &clip);
292 
293  /// Copy from another agent clip, and inherit the external reference if
294  /// there is one. If the rigs are different, identity matrices will be used
295  /// for the additional joints.
296  void load(const GU_AgentClip &clip);
297 
298  /// Return the number of transform tracks of the clip that was loaded into
299  /// this clip.
300  // This is currently only used for consistency checks.
301  int numTransformTracks() const
302  { return myNumXformTracks; }
303 
304  /// Save to clip
305  void save(CL_Clip &clip,
306  bool worldspace = false) const;
307 
308  const UT_StringHolder& name() const
309  { return myName; }
310 
311  bool isFile() const
312  { return myIsFile; }
313  void clearIsFile();
314 
315  const UT_StringHolder& fileName() const
316  { UT_ASSERT(isFile()); return myFileName; }
317 
318  const GU_AgentRig& rig() const
319  { return *myRig; }
320 
321  /// Number of transforms in each sample
323  {
324  if (myLocalTransforms.entries() < 1)
325  return 0;
326  return myLocalTransforms(0).entries();
327  }
328 
329  /// Number of samples in this clip
331  {
332  return myLocalTransforms.entries();
333  }
334 
335  /// Start time of this clip in seconds
336  /// @{
337  fpreal start() const
338  { return myStart; }
339  void setStart(fpreal t)
340  { myStart = t; }
341  /// @}
342 
343  /// Length of the clip, in seconds.
344  fpreal length() const
345  {
346  return secondsFromSample(sampleCount());
347  }
348 
349  /// Sample rate of this clip
350  /// @{
351  fpreal sampleRate() const { return mySampleRate; }
352  void setSampleRate(fpreal sample_rate)
353  { mySampleRate = sample_rate; }
354  /// @}
355 
356  /// Directly set the local transforms for this clip (as an alternative to
357  /// using GU_AgentClip::load()).
358  ///
359  /// @param samples An array of local transform samples
360  ///
361  /// @pre samples (and each sample within) must be at least length 1
362  /// @pre Each entry in samples must be the same length
363  /// @post sampleCount() == samples.entries()
364  /// @post transformsPerSample() == samples.last().entries()
365  void setLocalTransforms(
367 
368  const XformArray& localTransforms(exint sample_i) const
369  { return myLocalTransforms(sample_i); }
370  Matrix4ArrayConstPtr worldTransforms(exint sample_i) const
371  { return myWorldTransforms(sample_i); }
372 
373  /// Samples a transform in the clip at a specific time.
374  void sampleTransform(exint i, fpreal seconds,
375  bool worldspace,
376  Matrix4 &xform_sample) const;
377 
378  /// Add an extra channel into the clip (as an alternative to
379  /// GU_AgentClip::load()).
380  ///
381  /// @param name Unique name of the channel.
382  /// @param samples Float array with length sampleCount().
383  void addChannel(const UT_StringHolder &name,
384  const FloatType *samples);
385 
386  /// Finds a channel by name. Returns -1 if the channel does not exist.
387  exint findChannel(const UT_StringRef &name) const;
388  /// Samples an arbitrary channel in the clip at a specific time.
389  /// For transforms, use GU_AgentClip::sampleTransform().
390  FloatType sampleChannel(exint channel_index,
391  fpreal seconds) const;
392  /// Returns the names of all additional channels in the clip.
393  const UT_StringArray &channelNames() const { return myTrackNames; }
395  { return myTrackNames.entries(); }
396 
397  /// Add a scaled version of our local transforms using the given clip time.
398  /// If the time in seconds exceeds the length of our clip, then it is
399  /// wrapped around.
400  void addScaledLocalTransforms(
401  XformArray& dst,
402  fpreal scale,
403  fpreal seconds) const;
404  /// Variant of addScaledLocalTransforms that only affects a subset of the
405  /// joints.
406  ///
407  /// @param inv_total_weight Inverse of the total blend weight at each joint.
408  void addScaledLocalTransforms(
409  XformArray &dst,
410  const UT_BitArray &joints,
411  fpreal scale,
412  const UT_Array<fpreal> &inv_total_weights,
413  fpreal seconds) const;
414  /// Perform an additive blend with the specified percentage.
415  void concatLocalTransforms(
416  XformArray &dst,
417  const GU_AgentTransformGroup &xform_grp,
418  fpreal percent,
419  fpreal seconds) const;
420  void addScaledLocalTransform(
421  Xform& xform,
422  exint i,
423  fpreal scale,
424  fpreal seconds) const;
425 
426  inline fpreal sampleFromSeconds(fpreal seconds) const
427  {
428  return (seconds - myStart) * mySampleRate;
429  }
430  inline fpreal secondsFromSample(fpreal sample) const
431  {
432  return myStart + (sample / mySampleRate);
433  }
434  inline exint nearestSampleFromSeconds(fpreal seconds) const
435  {
436  return (exint)
437  SYSrint(sampleFromSeconds(seconds));
438  }
439  inline fpreal wrappedSampleFromSeconds(fpreal seconds) const
440  {
441  fpreal len = sampleCount();
442  fpreal s = SYSfmod(
443  sampleFromSeconds(seconds),
444  len);
445  if (s >= 0)
446  return s;
447  else
448  return s + len;
449  }
450 
451 private:
452  /// Given a sample time in seconds, find the two samples that we need to
453  /// interpolate between.
454  void getSamples(fpreal scale, fpreal seconds,
455  exint& sample_a, fpreal& weight_a,
456  exint& sample_b, fpreal& weight_b) const;
457 
458  /// Build myWorldTransforms from myLocalTransforms.
459  void computeWorldSpaceSamples();
460 
461  UT_StringHolder myName;
462  UT_StringHolder myFileName;
463  bool myIsFile;
464  int myNumXformTracks; // put here for the same ABI
465  GU_AgentRigConstPtr myRig;
466  fpreal myStart;
467  fpreal mySampleRate;
468 
469  /// The local transforms for the rig, at each sample.
470  UT_Array<XformArray> myLocalTransforms;
471  /// The world transforms for the rig, at each sample.
472  UT_Array<Matrix4ArrayPtr> myWorldTransforms;
473 
474  /// Additional (non-tranform) tracks.
476  UT_StringArray myTrackNames;
477  UT_StringMap<int> myTrackIndex;
478 };
479 
482 {
483  auto it = myTrackIndex.find(name);
484  return it != myTrackIndex.end() ? it->second : -1;
485 }
486 
487 #endif
GU_AgentXformT< float > GU_AgentXformF
Definition: GU_AgentClip.h:183
fpreal sampleFromSeconds(fpreal seconds) const
Definition: GU_AgentClip.h:426
void leftMult(const UT_SymMatrix3T< S > &m)
Multiply given symmetric matrix on the left.
Definition: UT_Matrix3.h:331
GT_API const UT_StringHolder filename
GU_AgentXformT(T scale)
Definition: GU_AgentClip.h:52
int numTransformTracks() const
Definition: GU_AgentClip.h:301
GU_AgentXformT< double > GU_AgentXformD
Definition: GU_AgentClip.h:184
IMF_EXPORT int & sampleCount(char *base, int xStride, int yStride, int x, int y)
SYS_FORCE_INLINE GU_AgentXformT()=default
static void forceValidName(UT_String &clipname)
Replaces whitespace, special characters, etc with underscores.
Definition: GU_AgentClip.h:259
exint findChannel(const UT_StringRef &name) const
Finds a channel by name. Returns -1 if the channel does not exist.
Definition: GU_AgentClip.h:481
void setLerp(const type &a, const type &b, T t)
Definition: GU_AgentClip.h:123
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
GU_AgentXformT< T > type
Definition: GU_AgentClip.h:47
void getTransform(S &tx, S &ty, S &tz, S &rx, S &ry, S &rz, S &sx, S &sy, S &sz) const
Definition: GU_AgentClip.h:101
Generic symmetric 3x3 matrix.
Definition: UT_SymMatrix3.h:26
fpreal wrappedSampleFromSeconds(fpreal seconds) const
Definition: GU_AgentClip.h:439
void setStart(fpreal t)
Definition: GU_AgentClip.h:339
void setTransform(T tx, T ty, T tz, T rx, T ry, T rz, T sx, T sy, T sz)
Definition: GU_AgentClip.h:78
const UT_Vector3T< T > & translate() const
Definition: GU_AgentClip.h:61
UT_Matrix2T< T > SYSlerp(const UT_Matrix2T< T > &v1, const UT_Matrix2T< T > &v2, S t)
Definition: UT_Matrix2.h:595
Matrix4ArrayConstPtr worldTransforms(exint sample_i) const
Definition: GU_AgentClip.h:370
3D Vector class.
A reference counter base class for use with UT_IntrusivePtr.
const UT_StringArray & channelNames() const
Returns the names of all additional channels in the clip.
Definition: GU_AgentClip.h:393
const GU_AgentRig & rig() const
Definition: GU_AgentClip.h:318
fpreal start() const
Definition: GU_AgentClip.h:337
png_uint_32 i
Definition: png.h:2877
UT_Matrix4T< FloatType > Matrix4
Definition: GU_AgentClip.h:209
long long int64
Definition: SYS_Types.h:107
GA_API const UT_StringHolder scale
UT_Array< Matrix4 > Matrix4Array
Definition: GU_AgentClip.h:210
A rig for the agent primitive.
Definition: GU_AgentRig.h:34
GU_AgentXformT< fpreal > GU_AgentXformR
Definition: GU_AgentClip.h:185
const UT_SymMatrix3T< T > & stretch() const
Definition: GU_AgentClip.h:59
void getMatrix4(UT_Matrix4T< T > &m) const
Definition: GU_AgentClip.h:162
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:28
int64 exint
Definition: SYS_Types.h:116
A factored transform geared for animation blending.
Definition: GU_AgentClip.h:44
fpreal64 dot(const CE_VectorT< T > &a, const CE_VectorT< T > &b)
Definition: CE_Vector.h:218
void concat(T t, const type &xform)
Perform an additive blend with the specified percentage.
Definition: GU_AgentClip.h:148
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
int int forceValidVariableName(const char *safechars=NULL)
#define SYS_DECLARE_IS_POD(T)
Declare a type as POD.
bool isFile() const
Definition: GU_AgentClip.h:311
Wrapper around hboost::intrusive_ptr.
GU_AgentXformT< FloatType > Xform
Definition: GU_AgentClip.h:207
#define GU_API
Definition: GU_API.h:12
exint channelCount() const
Definition: GU_AgentClip.h:394
const XformArray & localTransforms(exint sample_i) const
Definition: GU_AgentClip.h:368
GLuint const GLchar * name
Definition: glcorearb.h:785
UT_SharedPtr< const Matrix4Array > Matrix4ArrayConstPtr
Definition: GU_AgentClip.h:212
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
fpreal32 SYSrint(fpreal32 val)
Definition: SYS_Floor.h:163
void setTranslates(const UT_Vector3T< S > &translates)
Definition: UT_Matrix4.h:1306
GLsizei samples
Definition: glcorearb.h:1297
void setTransform(const UT_Vector3T< T > &t, const UT_QuaternionT< T > &r, const UT_Vector3T< T > &s)
Definition: GU_AgentClip.h:91
void setSampleRate(fpreal sample_rate)
Definition: GU_AgentClip.h:352
UT_Array< Xform > XformArray
Definition: GU_AgentClip.h:208
const UT_StringHolder & name() const
Definition: GU_AgentClip.h:308
GLenum GLenum dst
Definition: glcorearb.h:1792
double fpreal
Definition: SYS_Types.h:270
Quaternion class.
Definition: UT_Quaternion.h:51
fpreal32 FloatType
Definition: GU_AgentClip.h:206
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER T clip(const T &p, const Box< T > &box)
Definition: ImathBoxAlgo.h:89
fpreal length() const
Length of the clip, in seconds.
Definition: GU_AgentClip.h:344
exint nearestSampleFromSeconds(fpreal seconds) const
Definition: GU_AgentClip.h:434
UT_SharedPtr< Matrix4Array > Matrix4ArrayPtr
Definition: GU_AgentClip.h:211
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:126
const UT_StringHolder & fileName() const
Definition: GU_AgentClip.h:315
GLboolean r
Definition: glcorearb.h:1221
#define const
Definition: zconf.h:214
void addScaled(T s, const type &xform)
Definition: GU_AgentClip.h:137
fpreal sampleRate() const
Definition: GU_AgentClip.h:351
fpreal secondsFromSample(fpreal sample) const
Definition: GU_AgentClip.h:430
exint transformsPerSample() const
Number of transforms in each sample.
Definition: GU_AgentClip.h:322
float fpreal32
Definition: SYS_Types.h:191
exint sampleCount() const
Number of samples in this clip.
Definition: GU_AgentClip.h:330
const UT_QuaternionT< T > & rotate() const
Definition: GU_AgentClip.h:60