HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GU_MotionClipUtil.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_MotionClipUtil.h (GU Library, C++)
7  *
8  * COMMENTS: Utility methods for working with motion clips
9  */
10 
11 #ifndef __GU_MOTIONCLIPUTIL_H_INCLUDED__
12 #define __GU_MOTIONCLIPUTIL_H_INCLUDED__
13 
14 #include "GU_API.h"
15 
16 #include <CH/CH_Manager.h>
17 
18 #include <GA/GA_Types.h>
19 
20 #include <UT/UT_Assert.h>
21 #include <UT/UT_Options.h>
22 #include <UT/UT_Vector2.h>
23 
24 #include <SYS/SYS_Math.h>
25 #include <SYS/SYS_Types.h>
26 
27 class GEO_Detail;
28 class GU_Detail;
29 
31 {
32  Clamp = 0,
33  Loop = 1,
34  Mirror = 2
35 };
36 
37 /// Returns true if target_rate needs interpolation into source_rate
38 inline bool
39 GUsampleRatesNeedInterpolation(fpreal target_rate, fpreal source_rate)
40 {
41  // No interpolation needed if rates match
42  // NOTE: Use high tolerance here because we're comparing FPS values
43  if (SYSisEqual(target_rate, source_rate, 1e-2))
44  return false;
45 
46  // Needs interpolation when target_rate is faster because source has less
47  // samples.
48  if (target_rate > source_rate)
49  return true;
50 
51  // When source_rate is faster, then only needs to interpolate if it doesn't
52  // divide evenly.
53  return !SYSequalZero(SYSfmod(source_rate, target_rate));
54 }
55 
56 /// Mapper class for conversion between clip and scene time (in seconds)
58 {
59 public:
60 
61  /// Reset to the default scene's global range, unclamped.
62  void reset() { *this = GU_MotionClipTimeMap{}; }
63 
64  /// Start time in clip seconds
65  /// @{
66  fpreal start() const
67  { return myStart; }
68  void setStart(fpreal v, bool clamp = true)
69  { myStart = v; myClampStart = clamp; }
70  /// This variant will first clamp v to existing parameters
71  void setClampedStart(fpreal v, bool clamp = true)
72  { myStart = clampClipSeconds(v); myClampStart = clamp; }
73  /// @}
74 
75  /// End time to clamp to in clip seconds
76  /// @{
77  fpreal end() const
78  { return myEnd; }
79  void setEnd(fpreal v, bool clamp = true)
80  { myEnd = v; myClampEnd = clamp; }
81  /// This variant will first clamp v to existing parameters
82  void setClampedEnd(fpreal v, bool clamp = true)
83  { myEnd = clampClipSeconds(v); myClampEnd = clamp; }
84  /// @}
85 
86  /// Trim the current range to the given (assumes we have valid range)
87  void trimRange(fpreal start, fpreal end);
88 
89  /// Returns true when we have both start/end and start > end
90  bool hasInvalidRange() const { return (myStart > myEnd); }
91 
92  /// Playback start time in scene seconds
93  /// @{
94  fpreal playbackStart() const { return myPlaybackStart; }
95  void setPlaybackStart(fpreal v) { myPlaybackStart = v; }
96  /// @}
97 
98  /// Speed at which to playback in the scene
99  /// @{
100  fpreal speed() const { return mySpeed; }
101  void setSpeed(fpreal v) { mySpeed = v; }
102  /// @}
103 
104  /// Convert from clip time to scene time
105  fpreal toSceneSeconds(fpreal clip_seconds) const;
106 
107  /// Convert from scene time to clip time
108  fpreal toClipSeconds(fpreal scene_seconds) const;
109 
110  /// Clamp clip time depending to available clip range
111  fpreal clampClipSeconds(fpreal clip_seconds) const;
112 
113 private:
114  /// clip time origin in seconds
115  fpreal myStart = CHgetManager()->getGlobalStart();
116 
117  /// max clip time in seconds
118  fpreal myEnd = CHgetManager()->getGlobalEnd();
119 
120  /// scene time origin in seconds
121  fpreal myPlaybackStart = CHgetManager()->getGlobalStart();
122 
123  /// scene playback speed
124  fpreal mySpeed = 1.0;
125 
126  bool myClampStart = false; /// clamp to start time?
127  bool myClampEnd = false; /// clamp to end time?
128 };
129 
131 {
132 public:
133  GU_MotionClipInfo() = default;
134 
135  /// Reset to default constructed state
136  void reset() { *this = GU_MotionClipInfo{}; }
137 
138  /// Initialize from given ClipTimeMap, filling in missing information
139  /// from CHgetManager() as required.
140  void initFromTimeMap(
141  const GU_MotionClipTimeMap& time_map,
142  fpreal source_rate);
143 
144  /// Load values from geometry
145  bool load(const GEO_Detail& geo);
146 
147  /// Save values to geometry
148  bool save(GEO_Detail& geo);
149 
150  /// Get name of clipinfo detail attribute
151  static UT_StringHolder attribName();
152 
153  /// Source clip range in seconds
154  /// @{
155  const UT_Vector2R& sourceRange() const { return mySourceRange; }
157  { mySourceRange = UT_Vector2R{start, end}; }
158  /// @}
159 
160  /// Source clip rate in frames per second
161  /// @{
162  fpreal sourceRate() const { return mySourceRate; }
164  { mySourceRate = rate; }
165  /// @}
166 
167  /// Scene clip range in seconds
168  /// @{
169  UT_Vector2R& range() { return myRange; }
170  const UT_Vector2R& range() const { return myRange; }
172  { myRange = UT_Vector2R{start, end}; }
173  /// @}
174 
175  /// Scene rate in frames per second
176  /// @{
177  fpreal rate() const { return myRate; }
178  void setRate(fpreal rate) { myRate = rate; }
179  /// @}
180 
181  /// Name of the clip.
182  /// @{
183  const UT_StringHolder &name() const { return myName; }
184  void setName(const UT_StringHolder &name)
185  /// @}
186  { myName = name; }
187 
188  /// SOP path used to create the clip.
189  /// @{
190  const UT_StringHolder &sopPath() const { return mySopPath; }
191  void setSopPath(const UT_StringHolder &path);
192  /// @}
193 
194  /// The end behavior should the clip be evaluate after the last frame
195  /// @{
197  { return myRightEndBehavior; }
198  GU_MotionClipEndBehavior rightEndBehaviorEnum() const;
199 
200  void setRightEndBehavior(const UT_StringHolder &behavior);
201  void setRightEndBehavior(const GU_MotionClipEndBehavior &behavior);
202  /// @}
203  /// @}
204 
205  /// The end behavior should the clip be evaluated before the first frame
206  /// @{
208  { return myLeftEndBehavior; }
209  GU_MotionClipEndBehavior leftEndBehaviorEnum() const;
210 
211  void setLeftEndBehavior(const UT_StringHolder &behavior);
212  void setLeftEndBehavior(const GU_MotionClipEndBehavior &behavior);
213  /// @}
214  /// @}
215  /// @}
216 
217  bool operator==(const GU_MotionClipInfo& other) const
218  {
219  return mySourceRange == other.mySourceRange
220  && mySourceRate == other.mySourceRate
221  && myRange == other.myRange
222  && myRate == other.myRate
223  && myName == other.myName
224  && mySopPathUsed == other.mySopPathUsed
225  && mySopPath == other.mySopPath
226  && myRightEndBehaviorUsed == other.myRightEndBehaviorUsed
227  && myRightEndBehavior == other.myRightEndBehavior
228  && myLeftEndBehaviorUsed == other.myLeftEndBehaviorUsed
229  && myLeftEndBehavior == other.myLeftEndBehavior;
230  }
231 
232  bool operator!=(const GU_MotionClipInfo& other) const
233  {
234  return (!operator==(other));
235  }
236 
237 private:
238  GU_MotionClipEndBehavior getEndBehaviorFromString(const UT_StringHolder &behavior) const;
239  UT_StringHolder getStringFromEndBehavior(
240  const GU_MotionClipEndBehavior &behavior) const;
241 
242  UT_Vector2R mySourceRange{0,0}; // source range in secs
243  fpreal mySourceRate{0.0}; // source sampling rate
244  UT_Vector2R myRange{0,0}; // anim range in seconds
245  fpreal myRate{0.0}; // anim sampling rate
246  UT_StringHolder myName; // anim clip name
247  UT_StringHolder mySopPath; // anim clip path
248  bool mySopPathUsed{false};
249 
250  // right end behavior
251  bool myRightEndBehaviorUsed{false};
252  UT_StringHolder myRightEndBehavior{""};
253 
254  // left end behavior
255  bool myLeftEndBehaviorUsed{false};
256  UT_StringHolder myLeftEndBehavior{""};
257 
258  // Keep a copy of the dict when calling gpd.load()
259  UT_OptionsHolder myOptionsHolder;
260 };
261 
262 /// Map between channel names and the attributes that the channel values are
263 /// stored in.
265 {
266 public:
267  /// Returns whether there are any channels in the map.
268  bool isEmpty() const { return myOptions.isEmpty(); }
269 
270  /// Load the channel map from a detail attribute.
271  bool load(const GU_Detail& detail);
272 
273  /// Save the channel map as a detail attribute.
274  bool save(GU_Detail& detail) const;
275 
276  /// Returns a sorted list of the channel names.
277  UT_StringArray channelNames() const;
278 
279  /// Returns the channel's value, using the attribute specified in the map.
280  fpreal getChannelValue(
281  const GU_Detail& detail,
282  const UT_StringHolder& channel_name) const;
283 
284  /// Add a channel where the value is provided by a detail attribute.
285  void addDetailAttrib(
286  const UT_StringHolder& channel_name,
287  const UT_StringHolder& attrib_name);
288 
289  /// Add a channel where the value is provided by a point attribute's value
290  /// for a specific joint.
291  void addPointAttrib(
292  const UT_StringHolder& attrib_name,
293  const UT_StringHolder& joint_name);
294 
295 private:
296  UT_OptionsHolder myOptions;
297 };
298 
299 // Keeps track of and compares the data ids of details that are important for
300 // the evaluation of motion clips.
302 {
303 public:
304  GU_MotionClipDataIds(const GU_Detail *gdp);
306 
307  bool update(const GU_Detail *gdp, bool &did_change);
308 
309 private:
310  GA_DataId myPrimitivesId;
311  GA_DataId myTopologyId;
312  GA_DataId myTimeAttribId;
313  GA_DataId myClipInfoAttribId;
314 };
315 
316 namespace GU_MotionClipNames
317 {
318  /// Attribute storing the channel name that provides the shape's weight.
320  /// Attribute storing the unique name of the blendshape input.
322  /// Attribute storing the name of a blendshape inbetween
324  /// Attribute storing the weight position of a blendshape inbetween
326 }
327 
328 ///////////////////////////////////////////////////////////////////////////////
329 //
330 // Inline Implementations
331 //
332 
333 inline void
335 {
336  if (myStart < start)
337  myStart = start;
338  if (myEnd > end)
339  myEnd = end;
340 }
341 
342 inline fpreal
344 {
346  if (myClampStart && clip_seconds < myStart)
347  clip_seconds = myStart;
348  else if (myClampEnd && clip_seconds > myEnd)
349  clip_seconds = myEnd;
350  return clip_seconds;
351 }
352 
353 inline fpreal
355 {
356  fpreal t = clampClipSeconds(clip_seconds);
357  return SYSsafediv(t - myStart, mySpeed) + myPlaybackStart;
358 }
359 
360 inline fpreal
362 {
363  fpreal t = (scene_seconds - myPlaybackStart)*mySpeed;
364  return clampClipSeconds(t + myStart);
365 }
366 
367 #endif // __GU_MOTIONCLIPUTIL_H_INCLUDED__
fpreal start() const
fpreal rate() const
UT_StringHolder leftEndBehavior() const
bool hasInvalidRange() const
Returns true when we have both start/end and start > end.
const UT_StringHolder & sopPath() const
const UT_Vector2R & range() const
fpreal playbackStart() const
void setSourceRate(fpreal rate)
void setClampedEnd(fpreal v, bool clamp=true)
This variant will first clamp v to existing parameters.
void setClampedStart(fpreal v, bool clamp=true)
This variant will first clamp v to existing parameters.
GLenum clamp
Definition: glcorearb.h:1234
const UT_Vector2R & sourceRange() const
void setSourceRange(fpreal start, fpreal end)
fpreal toClipSeconds(fpreal scene_seconds) const
Convert from scene time to clip time.
int64 GA_DataId
Definition: GA_Types.h:687
const GLdouble * v
Definition: glcorearb.h:837
GLuint start
Definition: glcorearb.h:475
GLsizei const GLchar *const * path
Definition: glcorearb.h:3341
void reset()
Reset to default constructed state.
fpreal sourceRate() const
void setPlaybackStart(fpreal v)
Mapper class for conversion between clip and scene time (in seconds)
UT_StringHolder rightEndBehavior() const
const UT_StringHolder & name() const
GU_API const UT_StringHolder blendshape_channel
Attribute storing the channel name that provides the shape's weight.
GU_API const UT_StringHolder blendshape_name
Attribute storing the unique name of the blendshape input.
GU_API const UT_StringHolder blendshape_inbetween_name
Attribute storing the name of a blendshape inbetween.
fpreal toSceneSeconds(fpreal clip_seconds) const
Convert from clip time to scene time.
CH_Manager * CHgetManager()
Definition: CH_Manager.h:2079
fpreal getGlobalStart() const
Definition: CH_Manager.h:1185
GU_MotionClipEndBehavior
fpreal clampClipSeconds(fpreal clip_seconds) const
Clamp clip time depending to available clip range.
void setRate(fpreal rate)
bool operator==(const GU_MotionClipInfo &other) const
GLuint GLuint end
Definition: glcorearb.h:475
UT_Vector2R & range()
fpreal getGlobalEnd() const
Definition: CH_Manager.h:1186
#define GU_API
Definition: GU_API.h:14
GLuint const GLchar * name
Definition: glcorearb.h:786
GLdouble t
Definition: glad.h:2397
bool isEmpty() const
Returns whether there are any channels in the map.
GU_API const UT_StringHolder blendshape_inbetween_weight
Attribute storing the weight position of a blendshape inbetween.
void setStart(fpreal v, bool clamp=true)
bool SYSequalZero(const UT_Vector3T< T > &v)
Definition: UT_Vector3.h:1069
bool GUsampleRatesNeedInterpolation(fpreal target_rate, fpreal source_rate)
Returns true if target_rate needs interpolation into source_rate.
void setRange(fpreal start, fpreal end)
bool operator!=(const GU_MotionClipInfo &other) const
fpreal64 fpreal
Definition: SYS_Types.h:277
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
void setEnd(fpreal v, bool clamp=true)
void trimRange(fpreal start, fpreal end)
Trim the current range to the given (assumes we have valid range)
void reset()
Reset to the default scene's global range, unclamped.
bool SYSisEqual(const UT_Vector2T< T > &a, const UT_Vector2T< T > &b, S tol=SYS_FTOLERANCE)
Componentwise equality.
Definition: UT_Vector2.h:674