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