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 #include "GU_AgentXform.h"
18 
19 #include <UT/UT_Array.h>
20 #include <UT/UT_Assert.h>
21 #include <UT/UT_IntrusivePtr.h>
22 #include <UT/UT_Lock.h>
23 #include <UT/UT_Matrix3.h>
24 #include <UT/UT_Matrix4.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_ValArray.h>
30 #include <UT/UT_VectorTypes.h>
31 #include <SYS/SYS_Inline.h>
32 #include <SYS/SYS_Math.h>
33 #include <SYS/SYS_Types.h>
34 
35 class CL_Clip;
37 class UT_BitArray;
38 class UT_StringArray;
39 
44 
45 /// An agent motion clip
46 ///
47 /// It is represented as array of samples, where each sample has
48 /// transformsPerSample() number of transforms. These transforms can be "local"
49 /// (corresponding to the transform hierarchy of rig()), or "world" where they
50 /// are multiplied all the way up to a root node in the rig.
51 class GU_API GU_AgentClip : public UT_IntrusiveRefCounter<GU_AgentClip>
52 {
53 public:
54 
64 
65  /// Create an empty clip
66  static GU_AgentClipPtr addClip(
67  const UT_StringHolder &name,
68  const GU_AgentRigConstPtr &rig);
69 
70  /// Create a clip by loading a clip file from disk.
71  static GU_AgentClipPtr addClipFromFile(
72  const UT_StringHolder &name,
74  const GU_AgentRigConstPtr& rig,
75  bool delay_load,
76  UT_StringArray& errors);
77 
78  /// Create a clone of a clip, referencing the specified rig.
79  /// 'copy_external_ref' should be disabled if the new clip will be
80  /// further modified.
81  static GU_AgentClipPtr addClipCopy(const GU_AgentClip &src,
82  const GU_AgentRigConstPtr &rig,
83  bool copy_external_ref);
84 
85  /// Compute the world transforms 'matrices' from the local 'xforms'
86  /// corresponding to the transforms in 'rig'.
87  static void computeWorldTransforms(
88  const GU_AgentRig& rig,
89  const XformArray& xforms,
90  Matrix4Array& matrices);
91 
92  /// Compute the local transforms 'matrices' from the local 'xforms'
93  /// corresponding to the transforms in 'rig'.
94  static void computeLocalTransforms(
95  const GU_AgentRig& rig,
96  const XformArray& xforms,
97  Matrix4Array& matrices);
98 
99  /// Given the local transforms 'xforms' corresponding to 'rig', convert
100  /// them to world transforms in-place.
101  /// The optional 'in_world_space' array can be used to specify if some
102  /// transforms in 'xforms' are already in world space.
103  static void computeWorldTransforms(
104  const GU_AgentRig& rig,
105  const UT_BitArray *in_world_space,
106  Matrix4Array& xforms);
107 
108  /// Given the world transforms 'xforms' corresponding to 'rig', convert
109  /// them to local transforms in-place.
110  /// The optional 'in_world_space' array can be used to specify if only some
111  /// transforms in 'xforms' are currently in world space.
112  static void computeLocalTransforms(
113  const GU_AgentRig& rig,
114  const UT_BitArray *in_world_space,
115  Matrix4Array& xforms);
116 
117  /// Replaces whitespace, special characters, etc with underscores.
118  SYS_NO_DISCARD_RESULT static UT_StringHolder forceValidName(
119  const UT_StringHolder &clipname);
120 
121 private:
123  const UT_StringHolder &filename,
124  const GU_AgentRigConstPtr &rig)
125  : myName(name)
126  , myFileName(filename)
127  , myIsFile(filename.isstring())
128  , myIsLoaded(!filename.isstring())
129  , myHasLoadErrors(false)
130  , myNumXformTracks(0)
131  , myRig(rig)
132  , myStart(0)
133  , mySampleRate(24.0)
134  {
135  }
136 
137 public:
138 
139  ~GU_AgentClip();
140 
141  int64 getMemoryUsage(bool inclusive) const;
142 
143  /// Set this clip to have the specified number of samples, filled with
144  /// the rest transforms.
145  ///
146  /// @pre num_samples must be larger than 0.
147  void init(exint num_samples);
148 
149  /// Load from clip.
150  void load(const CL_Clip &clip);
151 
152  /// Copy from another agent clip, and inherit the external reference if
153  /// there is one. If the rigs are different, the rig's rest transforms will
154  /// be used for the additional joints.
155  void load(const GU_AgentClip &clip);
156 
157  /// Return the number of transform tracks of the clip that was loaded into
158  /// this clip.
159  // This is currently only used for consistency checks.
160  int numTransformTracks() const
161  { ensureLoaded(); return myNumXformTracks; }
162 
163  /// Save to clip
164  void save(CL_Clip &clip,
165  bool worldspace = false) const;
166 
167  /// Name of the clip.
168  /// @{
169  const UT_StringHolder& name() const
170  { return myName; }
172  { myName = name; }
173  /// @}
174 
175  /// Returns whether the clip references a file on disk.
176  bool isFile() const
177  { return myIsFile; }
178  /// Returns the name of the file referenced by the clip.
179  const UT_StringHolder& fileName() const
180  { UT_ASSERT(isFile()); return myFileName; }
181  /// Clears the external file reference. The clip's contents will also be
182  /// loaded from disk if necessary.
183  void clearIsFile();
184 
185  /// Returns whether the clip's contents have been loaded from disk.
186  bool isLoaded() const
187  { UT_ASSERT(isFile()); return myIsLoaded; }
188  /// Returns whether there were errors when loading the clip from disk.
189  bool hasLoadErrors() const
190  { return myHasLoadErrors; }
191  /// Explicitly loads the clip from disk.
192  bool loadFromFile(
193  UT_StringArray *errors = nullptr) const;
194 
195  const GU_AgentRig& rig() const
196  { return *myRig; }
197 
198  /// Number of transforms in each sample
200  {
201  ensureLoaded();
202  if (myLocalTransforms.entries() < 1)
203  return 0;
204  return myLocalTransforms(0).entries();
205  }
206 
207  /// Number of samples in this clip
209  {
210  ensureLoaded();
211  return myLocalTransforms.entries();
212  }
213 
214  /// Start time of this clip in seconds
215  /// @{
216  fpreal start() const
217  { ensureLoaded(); return myStart; }
219  { ensureLoaded(); myStart = t; }
220  /// @}
221 
222  /// Length of the clip, in seconds.
223  fpreal length() const
224  {
225  return sampleCount() / sampleRate();
226  }
227 
228  /// Sample rate of this clip
229  /// @{
231  { ensureLoaded(); return mySampleRate; }
232  void setSampleRate(fpreal sample_rate)
233  {
234  ensureLoaded();
235  mySampleRate = sample_rate;
236  }
237  /// @}
238 
239  /// Directly set the local transforms for this clip (as an alternative to
240  /// using GU_AgentClip::load()).
241  ///
242  /// @param samples An array of local transform samples
243  ///
244  /// @pre samples (and each sample within) must be at least length 1
245  /// @pre Each entry in samples must be the same length
246  /// @post sampleCount() == samples.entries()
247  /// @post transformsPerSample() == samples.last().entries()
248  void setLocalTransforms(
250 
251  /// Edit the transforms for a specific sample in the clip.
252  void setLocalTransforms(exint sample_i,
253  const XformArray &xforms);
254 
255  const XformArray& localTransforms(exint sample_i) const
256  {
257  ensureLoaded();
258  return myLocalTransforms(sample_i);
259  }
261  {
262  ensureLoaded();
263  return myWorldTransforms(sample_i);
264  }
265  const FloatArray& channelValues(exint sample_i) const
266  {
267  ensureLoaded();
268  return *myChannelValueSamples[sample_i];
269  }
270 
271  /// Samples a transform in the clip at a specific time.
272  void sampleTransform(exint i, fpreal seconds,
273  bool worldspace,
274  Matrix4 &xform_sample) const;
275 
276  /// Add an extra channel into the clip (as an alternative to
277  /// GU_AgentClip::load()).
278  /// If a channel with the same name already exists, its data is replaced
279  /// with the new samples.
280  ///
281  /// @param name Unique name of the channel.
282  /// @param samples Float array with length sampleCount().
283  void addChannel(const UT_StringHolder &name,
284  const FloatType *samples);
285 
286  /// Finds a channel by name. Returns -1 if the channel does not exist.
287  exint findChannel(const UT_StringRef &name) const;
288  /// Samples a channel in the clip at a specific time.
289  /// The channel indices from GU_AgentRig are valid indices for the clip's
290  /// channels.
291  /// For transforms, use GU_AgentClip::sampleTransform().
292  FloatType sampleChannel(exint channel_index,
293  fpreal seconds) const;
294  /// Returns the number of non-transform channels in the clip. This value
295  /// will be >= GU_AgentRig::channelCount().
296  exint channelCount() const;
297  /// Returns the name of the specified channel.
298  const UT_StringHolder &channelName(exint i) const;
299  /// Builds a list of all channel names in the clip (channels defined by
300  /// GU_AgentRig, plus any spare channels).
301  UT_StringArray channelNames() const;
302 
303  /// Add a scaled version of our local transforms using the given clip time.
304  /// If the time in seconds exceeds the length of our clip, then it is
305  /// wrapped around.
306  void addScaledLocalTransforms(
307  XformArray& dst,
308  fpreal scale,
309  fpreal seconds) const;
310  /// Variant of addScaledLocalTransforms that only affects a subset of the
311  /// joints.
312  ///
313  /// @param inv_total_weight Inverse of the total blend weight at each joint.
314  void addScaledLocalTransforms(
315  XformArray &dst,
316  const UT_BitArray &joints,
317  fpreal scale,
318  const UT_Array<fpreal> &inv_total_weights,
319  fpreal seconds) const;
320  /// Perform an additive blend with the specified percentage.
321  void concatLocalTransforms(
322  XformArray &dst,
323  const GU_AgentTransformGroup &xform_grp,
324  fpreal percent,
325  fpreal seconds) const;
326  void addScaledLocalTransform(
327  Xform& xform,
328  exint i,
329  fpreal scale,
330  fpreal seconds) const;
331 
332  /// Adds a scaled version of the channel values given a clip time. Only the
333  /// channels defined on GU_AgentRig are included.
334  void addScaledChannelValues(
335  FloatArray &dst,
336  const UT_BitArray &channels,
337  fpreal scale,
338  const UT_Array<fpreal> &inv_total_weights,
339  fpreal seconds) const;
340 
342  {
343  ensureLoaded();
344  return (seconds - myStart) * mySampleRate;
345  }
346  inline fpreal secondsFromSample(fpreal sample) const
347  {
348  ensureLoaded();
349  return myStart + (sample / mySampleRate);
350  }
352  {
353  return (exint)
354  SYSrint(sampleFromSeconds(seconds));
355  }
357  {
358  fpreal len = sampleCount();
359  fpreal s = SYSfmod(
360  sampleFromSeconds(seconds),
361  len);
362  if (s >= 0)
363  return s;
364  else
365  return s + len;
366  }
367 
368 private:
369  /// Called before any clip data is accessed to ensure that the clip has
370  /// been loaded from disk.
371  SYS_FORCE_INLINE void ensureLoaded() const
372  {
373  if (!myIsLoaded)
374  loadFromFile();
375  }
376 
377  /// Removes the clip from the agent clip file cache.
378  void removeFromFileCache();
379 
380  /// Given a sample time in seconds, find the two samples that we need to
381  /// interpolate between.
382  void getSamples(fpreal scale, fpreal seconds,
383  exint& sample_a, fpreal& weight_a,
384  exint& sample_b, fpreal& weight_b) const;
385 
386  /// Initialize myChannelValueSamples with the channels defined on
387  /// GU_AgentRig.
388  void initChannels(exint num_samples);
389 
390  /// Build myWorldTransforms from myLocalTransforms.
391  void computeWorldSpaceSamples();
392 
393  UT_StringHolder myName;
394  UT_StringHolder myFileName;
395  bool myIsFile;
396  /// Tracks whether the clip's contents have been loaded from disk.
397  bool myIsLoaded;
398  /// Records whether there were any errors when the clip was delay-loaded.
399  bool myHasLoadErrors;
400  int myNumXformTracks; // put here for the same ABI
401  GU_AgentRigConstPtr myRig;
402  fpreal myStart;
403  fpreal mySampleRate;
404 
405  /// The local transforms for the rig, at each sample.
406  UT_Array<XformArray> myLocalTransforms;
407  /// The world transforms for the rig, at each sample.
408  UT_Array<Matrix4ArrayPtr> myWorldTransforms;
409 
410  /// The (non-transform) channel values in the clip, at each sample.
411  /// Channels are ordered beginning with the channels defined on
412  /// GU_AgentRig.
413  UT_Array<FloatArrayPtr> myChannelValueSamples;
414  /// List of spare channels not defined on GU_AgentRig. These are stored at
415  /// the end of myChannelValueSamples[i].
416  UT_StringArray mySpareChannelNames;
417  /// Index into myChannelValueSamples[i] for each channel in
418  /// mySpareChannelNames.
419  UT_StringMap<int> mySpareChannelIndex;
420 
421  /// Lock for delayed loading of the clip data.
422  mutable UT_Lock myDelayLoadLock;
423 };
424 
425 inline exint
427 {
428  ensureLoaded();
429 
430  // First, see if this channel is defined on the rig.
431  exint i = myRig->findChannel(name);
432  if (i >= 0)
433  return i;
434 
435  // Otherwise, it would need to be a spare channel.
436  auto it = mySpareChannelIndex.find(name);
437  return it != mySpareChannelIndex.end() ? it->second : -1;
438 }
439 
440 inline const UT_StringHolder &
442 {
443  ensureLoaded();
444 
445  // Grab the channel name from the rig, unless it is a spare channel.
446  if (i < myRig->channelCount())
447  return myRig->channelName(i);
448  else
449  return mySpareChannelNames[i - myRig->channelCount()];
450 }
451 
452 inline exint
454 {
455  ensureLoaded();
456  return myRig->channelCount() + mySpareChannelNames.entries();
457 }
458 
459 inline UT_StringHolder
461 {
462  return clipname.forceValidVariableName(".-");
463 }
464 
465 #endif
fpreal sampleFromSeconds(fpreal seconds) const
Definition: GU_AgentClip.h:341
GT_API const UT_StringHolder filename
int numTransformTracks() const
Definition: GU_AgentClip.h:160
GLenum GLenum GLenum GLenum GLenum scale
Definition: glew.h:14163
static SYS_NO_DISCARD_RESULT UT_StringHolder forceValidName(const UT_StringHolder &clipname)
Replaces whitespace, special characters, etc with underscores.
Definition: GU_AgentClip.h:460
UT_IntrusivePtr< const GU_AgentClip > GU_AgentClipConstPtr
Definition: GU_AgentClip.h:42
exint findChannel(const UT_StringRef &name) const
Finds a channel by name. Returns -1 if the channel does not exist.
Definition: GU_AgentClip.h:426
int64 exint
Definition: SYS_Types.h:125
UT_IntrusivePtr< GU_AgentClip > GU_AgentClipPtr
Definition: GU_AgentClip.h:40
fpreal wrappedSampleFromSeconds(fpreal seconds) const
Definition: GU_AgentClip.h:356
void setStart(fpreal t)
Definition: GU_AgentClip.h:218
GLuint const GLchar * name
Definition: glcorearb.h:785
Matrix4ArrayConstPtr worldTransforms(exint sample_i) const
Definition: GU_AgentClip.h:260
GLenum src
Definition: glcorearb.h:1792
A reference counter base class for use with UT_IntrusivePtr.
float fpreal32
Definition: SYS_Types.h:200
const GU_AgentRig & rig() const
Definition: GU_AgentClip.h:195
GLdouble GLdouble t
Definition: glew.h:1403
fpreal start() const
Definition: GU_AgentClip.h:216
GLsizei samples
Definition: glcorearb.h:1297
UT_Matrix4T< FloatType > Matrix4
Definition: GU_AgentClip.h:60
UT_SharedPtr< FloatArray > FloatArrayPtr
Definition: GU_AgentClip.h:57
UT_Array< Matrix4 > Matrix4Array
Definition: GU_AgentClip.h:61
A rig for the agent primitive.
Definition: GU_AgentRig.h:38
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:30
const FloatArray & channelValues(exint sample_i) const
Definition: GU_AgentClip.h:265
GLenum GLsizei len
Definition: glew.h:7782
A factored transform geared for animation blending.
Definition: GU_AgentXform.h:20
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
void setName(const UT_StringHolder &name)
Definition: GU_AgentClip.h:171
UT_Array< GU_AgentClipConstPtr > GU_AgentClipPtrArray
Definition: GU_AgentClip.h:43
bool isFile() const
Returns whether the clip references a file on disk.
Definition: GU_AgentClip.h:176
Wrapper around hboost::intrusive_ptr.
long long int64
Definition: SYS_Types.h:116
#define SYS_NO_DISCARD_RESULT
Definition: SYS_Compiler.h:93
UT_Array< FloatType > FloatArray
Definition: GU_AgentClip.h:56
GU_AgentXformT< FloatType > Xform
Definition: GU_AgentClip.h:58
#define GU_API
Definition: GU_API.h:14
exint channelCount() const
Definition: GU_AgentClip.h:453
const XformArray & localTransforms(exint sample_i) const
Definition: GU_AgentClip.h:255
UT_SharedPtr< const Matrix4Array > Matrix4ArrayConstPtr
Definition: GU_AgentClip.h:63
SYS_NO_DISCARD_RESULT UT_StringRef forceValidVariableName(const char *safechars=nullptr) const
fpreal32 SYSrint(fpreal32 val)
Definition: SYS_Floor.h:163
const UT_StringHolder & channelName(exint i) const
Returns the name of the specified channel.
Definition: GU_AgentClip.h:441
exint entries() const
Alias of size(). size() is preferred.
Definition: UT_Array.h:481
void setSampleRate(fpreal sample_rate)
Definition: GU_AgentClip.h:232
UT_Array< Xform > XformArray
Definition: GU_AgentClip.h:59
const UT_StringHolder & name() const
Definition: GU_AgentClip.h:169
fpreal32 FloatType
Definition: GU_AgentClip.h:55
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER T clip(const T &p, const Box< T > &box)
Definition: ImathBoxAlgo.h:89
UT_Array< FloatType > FloatArray
fpreal64 fpreal
Definition: SYS_Types.h:277
fpreal length() const
Length of the clip, in seconds.
Definition: GU_AgentClip.h:223
exint nearestSampleFromSeconds(fpreal seconds) const
Definition: GU_AgentClip.h:351
UT_SharedPtr< Matrix4Array > Matrix4ArrayPtr
Definition: GU_AgentClip.h:62
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:171
const UT_StringHolder & fileName() const
Returns the name of the file referenced by the clip.
Definition: GU_AgentClip.h:179
fpreal sampleRate() const
Definition: GU_AgentClip.h:230
bool hasLoadErrors() const
Returns whether there were errors when loading the clip from disk.
Definition: GU_AgentClip.h:189
GLfloat seconds
Definition: wglew.h:950
fpreal secondsFromSample(fpreal sample) const
Definition: GU_AgentClip.h:346
exint transformsPerSample() const
Number of transforms in each sample.
Definition: GU_AgentClip.h:199
GLenum GLenum dst
Definition: glcorearb.h:1792
GLdouble s
Definition: glew.h:1395
bool isLoaded() const
Returns whether the clip's contents have been loaded from disk.
Definition: GU_AgentClip.h:186
ImageBuf OIIO_API channels(const ImageBuf &src, int nchannels, cspan< int > channelorder, cspan< float > channelvalues={}, cspan< std::string > newchannelnames={}, bool shuffle_channel_names=false, int nthreads=0)
exint sampleCount() const
Number of samples in this clip.
Definition: GU_AgentClip.h:208