Motive Animation System
An open source project by FPL.
 All Classes Functions Variables Typedefs Friends Pages
motivator.h
1 // Copyright 2014 Google Inc. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef MOTIVE_MOTIVATOR_H
16 #define MOTIVE_MOTIVATOR_H
17 
18 #include "motive/processor.h"
19 
20 namespace motive {
21 
22 class MotiveEngine;
23 
24 /// @class Motivator
25 /// @brief Drives a value towards a target value, or along a path.
26 ///
27 /// The value can be one-dimensional (e.g. a float), or multi-dimensional
28 /// (e.g. a matrix). The dimension is determined by the sub-class:
29 /// Motivator1f drives a float, MatrixMotivator4f drives a 4x4 float matrix.
30 ///
31 /// Although you can instantiate a Motivator, you probably will not, since
32 /// there is no mechanism to read data out of a Motivator. Generally, you
33 /// will instantiate a derived class like Motivator1f, which provides
34 /// accessor functions.
35 ///
36 /// The way a Motivator's value moves towards its target is determined by the
37 /// **type** of a motivator. The type is specified in Motivator::Initialize().
38 ///
39 /// Note that a Motivator does not store any data itself. It is a handle into
40 /// a MotiveProcessor. Each MotiveProcessor holds all data for motivators
41 /// of its **type**.
42 ///
43 /// Only one Motivator can reference a specific index in a MotiveProcessor.
44 /// Therefore, when you copy a Motivator, the original motivator will become
45 /// invalid.
46 ///
47 class Motivator {
48  public:
49  Motivator() : processor_(nullptr), index_(kMotiveIndexInvalid) {}
50 
51  /// Transfer ownership of `original` motivator to `this` motivator.
52  /// `original` motivator is reset and must be initialized again before being
53  /// read. We want to allow moves primarily so that we can have vectors of
54  /// Motivators.
55  ///
56  /// Note: This should be a move constructor instead of a copy constructor.
57  /// However, VS2010~2012 requires move constructors to exist in any
58  /// class that has a move constructed member. That would be a burden
59  /// for users of Motivator, so we chose to be practical here instead of
60  /// pedantically correct. We use the copy constructor and copy operator
61  /// to do move behavior.
62  /// See http://en.cppreference.com/w/cpp/language/move_operator
63  Motivator(const Motivator& original) {
64  if (original.Valid()) {
65  original.processor_->TransferMotivator(original.index_, this);
66  } else {
67  processor_ = nullptr;
68  index_ = kMotiveIndexInvalid;
69  }
70  }
71 
72  /// Allow Motivators to be moved. `original` is reset.
73  /// See the copy constructor for details.
74  Motivator& operator=(const Motivator& original) {
75  Invalidate();
76  if (original.processor_ != nullptr) {
77  original.processor_->TransferMotivator(original.index_, this);
78  }
79  return *this;
80  }
81 
82  /// Remove ourselves from the MotiveProcessor when we're deleted.
84 
85  /// Detatch this Motivator from its MotiveProcessor. Functions other than
86  /// Initialize() and Valid() can no longer be called afterwards.
87  void Invalidate() {
88  if (processor_ != nullptr) {
90  }
91  }
92 
93  /// Return true if this Motivator is currently being driven by a
94  /// MotiveProcessor. That is, if it has been successfully initialized.
95  bool Valid() const { return processor_ != nullptr; }
96 
97  /// Check consistency of internal state. Useful for debugging.
98  /// If this function ever returns false, there has been some sort of memory
99  /// corruption or similar bug.
100  bool Sane() const {
101  return (processor_ == nullptr && index_ == kMotiveIndexInvalid) ||
102  (processor_ != nullptr && processor_->ValidMotivator(index_, this));
103  }
104 
105  /// Return the type of Motivator we've been initilized to.
106  /// A Motivator can take on any type that matches its dimension.
107  /// The Motivator's type is determined by the `init` param in Initialize().
108  MotivatorType Type() const {
109  return Valid() ? processor_->Type() : kMotivatorTypeInvalid;
110  }
111 
112  /// The number of basic values that this Motivator is driving. For example,
113  /// a 3D position would return 3, since it drives three floats. A single
114  /// 4x4 matrix would return 1, since it's driving one matrix. The basic
115  /// value is determined by the MotiveProcessor backing this motivator.
116  MotiveDimension Dimensions() const { return processor_->Dimensions(index_); }
117 
118  protected:
119  Motivator(const MotivatorInit& init, MotiveEngine* engine,
120  MotiveDimension dimensions)
121  : processor_(nullptr), index_(kMotiveIndexInvalid) {
122  InitializeWithDimension(init, engine, dimensions);
123  }
124 
125  void InitializeWithDimension(const MotivatorInit& init, MotiveEngine* engine,
126  MotiveDimension dimensions);
127 
128  /// The MotiveProcessor uses the functions below. It does not modify data
129  /// directly.
130  friend class MotiveProcessor;
131 
132  /// These should only be called by MotiveProcessor!
133  void Init(MotiveProcessor* processor, MotiveIndex index) {
134  processor_ = processor;
135  index_ = index;
136  }
137  void Reset() { Init(nullptr, kMotiveIndexInvalid); }
138  const MotiveProcessor* Processor() const { return processor_; }
139 
140  /// All calls to an Motivator are proxied to an MotivatorProcessor. Motivator
141  /// data and processing is centralized to allow for scalable optimizations
142  /// (e.g. SIMD or parallelization).
144 
145  /// A MotiveProcessor processes one MotivatorType, and hosts every Motivator
146  /// of that type. This index here uniquely identifies this Motivator to the
147  /// MotiveProcessor.
148  MotiveIndex index_;
149 };
150 
151 /// @class MotivatorNfBase
152 /// @brief Animate an array of N-floats, where N is set by the `dimension` in
153 /// the constructor.
154 class MotivatorNf : public Motivator {
155  public:
156  /// Motivator is created in a reset state. When in the reset state,
157  /// it is not being driven, and Value(), Velocity(), etc. cannot be called.
159 
160  /// Initialize to the motion algorithm specified by `init`.
161  /// Current and target values are not set.
162  MotivatorNf(const MotivatorInit& init, MotiveEngine* engine,
163  MotiveDimension dimensions)
164  : Motivator(init, engine, dimensions) {}
165 
166  /// Initialize to the motion algorithm specified by `init`.
167  /// Set current and target values as specified by `ts`.
168  MotivatorNf(const MotivatorInit& init, MotiveEngine* engine,
169  MotiveDimension dimensions, const MotiveTarget1f* ts)
170  : Motivator(init, engine, dimensions) {
171  SetTargets(ts);
172  }
173 
174  /// Initialize this Motivator to the type specified in init.type.
175  /// @param init Defines the type and initial state of the Motivator.
176  /// @param engine The engine that will update this Motivator when
177  /// engine->AdvanceFrame() is called.
178  /// @param dimensions The number of slots to occupy. For example, a 3D
179  /// position would occupy three slots.
180  void Initialize(const MotivatorInit& init, MotiveEngine* engine,
181  MotiveDimension dimensions) {
182  InitializeWithDimension(init, engine, dimensions);
183  }
184 
185  /// Initialize to the motion algorithm specified by `init`.
186  /// Set current and target values as specified by `targets`, an array of
187  /// length `dimensions`.
189  MotiveDimension dimensions,
190  const MotiveTarget1f* targets) {
191  Initialize(init, engine, dimensions);
192  SetTargets(targets);
193  }
194 
195  /// Initialize to the motion algorithm specified by `init`.
196  /// Set target values and velocities as specified by 'target_values' and
197  /// 'target_velocities', arrays of length `dimensions`, with shape specified
198  /// by 'shape'.
200  MotiveEngine* engine,
201  MotiveDimension dimensions,
202  const MotiveCurveShape& shape,
203  const float* target_values,
204  const float* target_velocities) {
205  InitializeWithDimension(init, engine, dimensions);
206  SetTargetWithShape(target_values, target_velocities, shape);
207  }
208 
209  /// Initialize to the motion algorithm specified by `init`.
210  /// Set movement to follow the curves specified in `splines`, an array of
211  /// length `dimensions, and modified by `playback`.
213  MotiveDimension dimensions,
214  const CompactSpline* splines,
215  const SplinePlayback& playback) {
216  Initialize(init, engine, dimensions);
217  SetSplines(splines, playback);
218  }
219 
220  // Get array of length `dimensions`.
221  const float* Values() const { return Processor().Values(index_); }
222  void Velocities(float* out) const {
223  return Processor().Velocities(index_, Dimensions(), out);
224  }
225  void Directions(float* out) const {
226  return Processor().Directions(index_, Dimensions(), out);
227  }
228  void TargetValues(float* out) const {
229  return Processor().TargetValues(index_, Dimensions(), out);
230  }
231  void TargetVelocities(float* out) const {
232  return Processor().TargetVelocities(index_, Dimensions(), out);
233  }
234  void Differences(float* out) const {
235  return Processor().Differences(index_, Dimensions(), out);
236  }
237 
238  /// Returns time remaining until target is reached.
239  /// The unit of time is determined by the calling program.
240  MotiveTime TargetTime() const {
241  return Processor().TargetTime(index_, Dimensions());
242  }
243 
244  /// Returns the shape of the current curve.
246  return Processor().MotiveShape(index_);
247  }
248 
249  /// Returns the current time (i.e. the x-value) in the current spline.
250  /// If Motivator is not being driven by a spline, returns 0.
251  /// Whenever SetSpline() is called, this value will be reset to the
252  /// start_time specified in SplinePlayback. Every time
253  /// MotiveEngine::AdvanceFrame() is called, it will increment by
254  /// `delta_time` * `playback_rate`. If the SplinePlayback has repeat=true,
255  /// then SplineTime() will periodically loop back to time 0.
256  MotiveTime SplineTime() const { return Processor().SplineTime(index_); }
257 
258  /// Gather pointers to the splines currently being played, on each dimension.
259  /// @param splines Output array of length Dimensions().
260  void Splines(const CompactSpline** splines) const {
261  Processor().Splines(index_, Dimensions(), splines);
262  }
263 
264  /// Follow the curve specified in `spline`. Overrides the existing current
265  /// value.
266  /// @param spline The spline to follow. Array of length Dimensions().
267  /// @param playback The time into the splines to initiate playback,
268  /// the blend time to the splines, and whether to repeat
269  /// from the beginning after the end of the spline is reached.
270  void SetSpline(const CompactSpline& spline, const SplinePlayback& playback) {
271  assert(Dimensions() == 1);
272  Processor().SetSplines(index_, Dimensions(), &spline, playback);
273  }
274 
275  /// Follow the curves specified in `splines`. Overrides the existing current
276  /// value.
277  /// @param splines The splines that the curves should follow.
278  /// Array of length Dimensions().
279  /// @param playback The time into the splines to initiate playback,
280  /// the blend time to the splines, and whether to repeat
281  /// from the beginning after the end of the spline is reached.
282  void SetSplines(const CompactSpline* splines,
283  const SplinePlayback& playback) {
284  Processor().SetSplines(index_, Dimensions(), splines, playback);
285  }
286 
287  /// Seek to a specific time in the spline.
288  /// @param time The time (in the spline's x-axis) to seek to.
289  void SetSplineTime(MotiveTime time) {
290  Processor().SetSplineTime(index_, Dimensions(), time);
291  }
292 
293  /// Set rate at which we consume the spline set in SetSpline().
294  /// 0 ==> paused
295  /// 0.5 ==> half speed (slow motion)
296  /// 1 ==> authored speed
297  /// 2 ==> double speed (fast forward)
298  void SetSplinePlaybackRate(float playback_rate) {
299  Processor().SetSplinePlaybackRate(index_, Dimensions(), playback_rate);
300  }
301 
302  /// Set the target and (optionally the current) motivator values.
303  /// Use this call to procedurally drive the Motivator towards a specific
304  /// target. The Motivator will transition smoothly to the new target.
305  /// @param targets The targets that each value should achieve.
306  /// An array of length Dimensions().
307  void SetTargets(const MotiveTarget1f* targets) {
308  Processor().SetTargets(index_, Dimensions(), targets);
309  }
310 
311  /// Set the target values, velocities, and curve shape for the motivator.
312  /// Procedurally drive the Motivator to 'target_values' and
313  /// 'target_velocities' following a curve defined by 'shape'.
314  /// Setting the target with the shape makes it so that a time does not need
315  /// to be specified, as it will be calculated. In contrast, if the time needed
316  /// to achieve a value is to be user-provided, @ref SetTarget should be used
317  /// instead.
318  /// @param target_value Array of target values with length Dimensions.
319  /// @param target_velocity Array of target velocities with length Dimensions.
320  /// @param shape The shape of the curve we'll create, as determined by the
321  /// curve's typical delta value, typical total time, and bias.
322  void SetTargetWithShape(const float* target_values,
323  const float* target_velocities,
324  const MotiveCurveShape& shape) {
325  Processor().SetTargetWithShape(index_, Dimensions(), target_values,
326  target_velocities, shape);
327  }
328 
329  /// Drive some channels with splines and others with targets.
330  /// For i between 0 and Dimensions()-1, if splines[i] != NULL drive
331  /// channel i with splines[i]. Otherwise, drive channel i with targets[i].
332  /// @param splines Array of pointers to splines, length Dimensions().
333  /// Pointers can be NULL.
334  /// @param playback Various parameters for `splines`.
335  /// @param targets Array of targets that are used when splines are not
336  /// specified. Length Dimensions().
337  void SetSplinesAndTargets(const CompactSpline* const* splines,
338  const SplinePlayback& playback,
339  const MotiveTarget1f* targets) {
340  Processor().SetSplinesAndTargets(index_, Dimensions(), splines, playback,
341  targets);
342  }
343 
344  protected:
345  MotiveProcessorNf& Processor() {
346  return *static_cast<MotiveProcessorNf*>(processor_);
347  }
348  const MotiveProcessorNf& Processor() const {
349  return *static_cast<const MotiveProcessorNf*>(processor_);
350  }
351 };
352 
353 /// @class MotivatorXfTemplate
354 /// @brief Animate a vector of floating-point values.
355 ///
356 /// Wraps `MotivatorNf` to return by value, instead of using `out` arrays.
357 /// For `kDimension = 1`, the vector type is just `float`.
358 /// For `kDimension > 1`, the vector type is determined by `VectorConverter`.
359 /// We use `MathFuVectorConverter` below to create 2, 3, and 4 dimensional
360 /// motivators (see Motivator2f, Motivator3f, and Motivator4f).
361 /// You can use your own VectorConverter to create Motivators of that match
362 /// your vector types.
363 ///
364 template <class VectorConverter, MotiveDimension kDimensionsParam>
366  public:
367  typedef VectorConverter C;
368  static const MotiveDimension kDimensions = kDimensionsParam;
369  typedef typename VectorT<C, kDimensions>::type Vec;
370  typedef typename MotiveTargetT<kDimensions>::type Target;
372 
373  /// Motivator is created in a reset state. When in the reset state,
374  /// it is not being driven, and Value(), Velocity(), etc. cannot be called.
376 
377  /// Initialize to the motion algorithm specified by `init`.
378  /// Current and target values are not set.
380  : MotivatorNf(init, engine, kDimensions) {}
381 
382  /// Initialize to the motion algorithm specified by `init`.
383  /// Set current and target values as specified by `t`.
385  const Target& t)
386  : MotivatorNf(init, engine, kDimensions) {
387  SetTarget(t);
388  }
389 
390  /// Initialize to the motion algorithm specified by `init`.
391  void Initialize(const MotivatorInit& init, MotiveEngine* engine) {
392  InitializeWithDimension(init, engine, kDimensions);
393  }
394 
395  /// Initialize to the motion algorithm specified by `init`.
396  /// Set current and target values as specified by `t`.
398  const Target& t) {
399  InitializeWithDimension(init, engine, kDimensions);
400  SetTarget(t);
401  }
402 
403  /// Initialize to the motion algorithm specified by `init`.
404  /// Set target values and velocities as specified by 'target_values' and
405  /// 'target_velocities', arrays of length `dimensions`, with shape specified
406  /// by 'shape'.
408  MotiveEngine* engine,
409  MotiveDimension dimensions,
410  const MotiveCurveShape& shape,
411  const Vec& target_values,
412  const Vec& target_velocities) {
413  InitializeWithDimension(init, engine, dimensions);
414  SetTargetWithShape(target_values, target_velocities, shape);
415  }
416 
417  /// Returns the current motivator value. The current value is updated when
418  /// engine->AdvanceFrame() is called on the `engine` that initialized this
419  /// Motivator.
420  /// Note that the "Vec()" parameter is just a syntactic hack used to access
421  /// the correct overloaded function in the processor.
422  Vec Value() const { return C::FromPtr(Processor().Values(index_), Vec()); }
423 
424  /// Returns the current rate of change of this motivator. For example,
425  /// if this Motivator is being driven by a spline, returns the derivative
426  /// at the current time in the spline curve.
427  Vec Velocity() const {
428  Vec r;
429  Processor().Velocities(index_, kDimensions, C::ToPtr(r));
430  return r;
431  }
432 
433  /// Returns the velocity when playback rate is 1. Useful to know the
434  /// direction of a multi-dimensional motivator, even when playback rate
435  /// is 0.
436  Vec Direction() const {
437  Vec r;
438  Processor().Directions(index_, kDimensions, C::ToPtr(r));
439  return r;
440  }
441 
442  /// Returns the value this Motivator is driving towards.
443  /// If being driven by a spline, returns the value at the end of the spline.
444  Vec TargetValue() const {
445  Vec r;
446  Processor().TargetValues(index_, kDimensions, C::ToPtr(r));
447  return r;
448  }
449 
450  /// Returns the rate-of-change of this Motivator once it reaches
451  /// TargetValue().
452  Vec TargetVelocity() const {
453  Vec r;
454  Processor().TargetVelocities(index_, kDimensions, C::ToPtr(r));
455  return r;
456  }
457 
458  /// Returns TargetValue() minus Value(). If we're driving a
459  /// modular type (e.g. an angle), this may not be the naive subtraction.
460  /// For example, if TargetValue() = 170 degrees, Value() = -170 degrees,
461  /// then Difference() = -20 degrees.
462  Vec Difference() const {
463  Vec r;
464  Processor().Differences(index_, kDimensions, C::ToPtr(r));
465  return r;
466  }
467 
468  /// Set the target and (optionally the current) motivator values.
469  /// Use this call to procedurally drive the Motivator towards a specific
470  /// target. The Motivator will transition smoothly to the new target.
471  /// You can change the target value every frame if you like, and the
472  /// Motivator value should behave calmly but responsively, with the
473  /// movement qualities of the underlying MotiveProcessor.
474  /// Note that the underlying MotiveProcessor is allowed to ignore
475  /// parts of `t` that are irrelevent to its algorithm.
476  /// Note also that if the time needed to achieve a value is to be
477  /// user-provided, this function should be used. If the time should
478  /// be calculated instead of user-specified, @ref SetTargetWithShape
479  /// should be used instead.
480  /// @param t A set of waypoints to hit, optionally including the current
481  /// value. If the current value is not included, maintain the
482  /// existing current value.
483  void SetTarget(const Target& t) {
484  Processor().SetTargets(index_, kDimensions, t.targets());
485  }
486 
487  /// Set the target values, velocity, and curve shape for the motivator.
488  /// Use this call to procedurally drive the Motivator towards that target.
489  /// Setting the target with the shape makes it so that a time does not need
490  /// to be specified, as it will be calculated. In contrast, if the time needed
491  /// to achieve a value is to be user-provided, @ref SetTarget should be used
492  /// instead.
493  /// @param target_value The target value to hit.
494  /// @param target_velocity The velocity with which to hit the target value.
495  /// @param shape The shape of the curve we'll create, such as the curve's
496  /// typical delta value, typical total time, and bias.
497  void SetTargetWithShape(const Vec& target_value, const Vec& target_velocity,
498  const MotiveCurveShape& shape) {
499  Processor().SetTargetWithShape(index_, kDimensions, C::ToPtr(target_value),
500  C::ToPtr(target_velocity), shape);
501  }
502 
503  MotiveDimension Dimensions() const { return kDimensions; }
504 };
505 
506 /// @class MatrixMotivator4fTemplate
507 /// @brief Drive a 4x4 float matrix from a series of basic transformations.
508 ///
509 /// The underlying basic transformations can be animated with
510 /// SetChildTarget1f(), and set to fixed values with SetChildValue1f() and
511 /// SetChildValue3f().
512 ///
513 /// Internally, we use mathfu::mat4 as our matrix type and mathfu::vec3 as
514 /// our vector type, but external we allow any matrix type to be specified
515 /// via the VectorConverter template parameter.
516 ///
517 template <class VectorConverter>
519  public:
520  typedef VectorConverter C;
521  typedef typename VectorConverter::Matrix4 Mat4;
522  typedef typename VectorConverter::Vector3 Vec3;
524 
527  : Motivator(init, engine, 1) {}
528 
529  /// Initialize to the type specified by `init`.
530  void Initialize(const MotivatorInit& init, MotiveEngine* engine) {
531  InitializeWithDimension(init, engine, 1);
532  }
533 
534  /// Return the current value of the Motivator. The processor returns a
535  /// vector-aligned matrix, so the cast should be valid for any user-defined
536  /// matrix type.
537  const Mat4& Value() const {
538  // TODO: Return by value here. Necessary for matrix formats that are not
539  // byte-wise compatible. For example, row-major matrices.
540  return reinterpret_cast<const Mat4&>(Processor().Value(index_));
541  }
542 
543  /// Return the translation component of the matrix.
544  /// The matrix is a 3D affine transform, so the translation component is the
545  /// fourth column.
546  Vec3 Position() const {
547  const mathfu::vec3 position =
548  Processor().Value(index_).TranslationVector3D();
549  return C::FromPtr(&position[0], Vec3());
550  }
551 
552  /// Return the time remaining in the current spline animation.
553  /// Time units are defined by the user.
554  MotiveTime TimeRemaining() const { return Processor().TimeRemaining(index_); }
555 
556  /// Query the number of matrix operations. This equals the number of
557  /// operations in the `init` initializer.
558  int NumChildren() const { return Processor().NumChildren(index_); }
559 
560  /// Return the current value of the `child_index`th basic transform that
561  /// drives this matrix.
562  /// @param child_index The index into MatrixInit::ops(). The ops() array
563  /// is a series of basic transformation operations that
564  /// compose this matrix. Each basic transformation has
565  /// a current value. We gather this value here.
566  float ChildValue1f(MotiveChildIndex child_index) const {
567  float r;
568  Processor().ChildValues(index_, child_index, 1, &r);
569  return r;
570  }
571 
572  /// Returns the current values of the basic transforms at indices
573  /// (child_index, child_index + 1, child_index + 2).
574  /// Useful when you drive all the (x,y,z) components of a translation, scale,
575  /// or rotation.
576  /// @param child_index The first index into MatrixInit::ops(). The value at
577  /// this index is returned in the x component of Vec3.
578  /// y gets child_index + 1's value, and
579  /// z gets child_index + 2's value.
580  Vec3 ChildValue3f(MotiveChildIndex child_index) const {
581  Vec3 r;
582  Processor().ChildValues(index_, child_index, 3, C::ToPtr(r));
583  return r;
584  }
585 
586  /// Returns the Motivator1f that's driving this child, if it's driven by
587  /// a Motivator1f. Otherwise, returns nullptr.
588  const Mot1f* ChildMotivator1f(MotiveChildIndex child_index) const {
589  return static_cast<const Mot1f*>(
590  Processor().ChildMotivator1f(index_, child_index));
591  }
592 
593  /// Set the target the 'child_index'th basic transform.
594  /// Each basic transform can be driven by a child motivator.
595  /// This call lets us control those child motivators.
596  /// @param child_index The index into the MatrixInit::ops() that was passed
597  /// into Initialize(). This operation must have been
598  /// initialized with a MotivatorInit, not a constant value.
599  /// @param t The target values for the basic transform to animate towards.
600  /// Also, optionally, the current value for it to jump to.
601  void SetChildTarget1f(MotiveChildIndex child_index, const MotiveTarget1f& t) {
602  Processor().SetChildTarget1f(index_, child_index, t);
603  }
604 
605  /// Set the constant value of a child. Each basic matrix transformation
606  /// can be driven by a constant value instead of a Motivator.
607  /// This call lets us set those constant values.
608  /// @param child_index The index into the MatrixInit::ops() that was passed
609  /// into Initialize(). This operation must have been
610  /// initialized with a constant value, not a MotivatorInit.
611  /// @param value The new constant value of this operation.
612  void SetChildValue1f(MotiveChildIndex child_index, float value) {
613  Processor().SetChildValues(index_, child_index, 1, &value);
614  }
615 
616  /// Set the constant values of the basic transforms at indices
617  /// (child_index, child_index + 1, child_index + 2).
618  /// @param child_index The first index into MatrixInit::ops(). The constant
619  /// value at this index is set to the x component of
620  /// `value`.
621  /// child_index + 1's constant is set to value.y, and
622  /// child_index + 2's constant is set to value.z.
623  /// @param value The new constant value for this 3-dimensional operation.
624  void SetChildValue3f(MotiveChildIndex child_index, const Vec3& value) {
625  Processor().SetChildValues(index_, child_index, 3, C::ToPtr(value));
626  }
627 
628  /// Match existing MatrixOps with those in `ops` and smoothly transition
629  /// to the new parameters in `ops`.
630  void BlendToOps(const MatrixOpArray& ops, const SplinePlayback& playback) {
631  Processor().BlendToOps(index_, ops, playback);
632  }
633 
634  void SetPlaybackRate(float playback_rate) {
635  Processor().SetPlaybackRate(index_, playback_rate);
636  }
637 
638  private:
639  MatrixProcessor4f& Processor() {
640  return *static_cast<MatrixProcessor4f*>(processor_);
641  }
642  const MatrixProcessor4f& Processor() const {
643  return *static_cast<const MatrixProcessor4f*>(processor_);
644  }
645 };
646 
647 class RigMotivator : public Motivator {
648  public:
649  RigMotivator() {}
650  RigMotivator(const MotivatorInit& init, MotiveEngine* engine)
651  : Motivator(init, engine, 1) {}
652 
653  /// Initialize to the type specified by `init`. The only type defined
654  /// within Motive for `init` is RigInit, but you can register your
655  /// own RigProcessor classes if you like.
656  void Initialize(const MotivatorInit& init, MotiveEngine* engine) {
657  InitializeWithDimension(init, engine, 1);
658  }
659 
660  /// Blend from the current state to the animation specified in `anim`.
661  /// Blend time is specified in `anim` itself.
662  /// If the current state is unspecified because no animation
663  /// has yet been played, snap to `anim`.
664  void BlendToAnim(const RigAnim& anim, const SplinePlayback& playback) {
665  Processor().BlendToAnim(index_, anim, playback);
666  }
667 
668  void SetPlaybackRate(float playback_rate) {
669  Processor().SetPlaybackRate(index_, playback_rate);
670  }
671 
672  /// Returns array of matricies: one for each bone position. The matrices are
673  /// all in the space of the root bones. That is, the bone hierarchy has been
674  /// flattened.
675  const mathfu::AffineTransform* GlobalTransforms() const {
676  return Processor().GlobalTransforms(index_);
677  }
678 
679  /// Returns the shell aniamtion that defines this rig. It contains all the
680  /// bones and operations-on-those-bones that can be animated.
681  ///
682  /// Distinction,
683  /// Rig: defines the bone heirarchy.
684  /// Defining animation: defines the bone heirarchy + operations on each bone.
685  /// Operations-on-bone: one of MatrixOperationType, for example, a rotation
686  /// about the x-axis, or a translation along the y-axis. Animations are
687  /// composed of several such operations on each bone. Not every animation
688  /// has all the operations, however. The defining animation is the union
689  /// of all possible operations on each bone.
690  const RigAnim* DefiningAnim() const {
691  return Processor().DefiningAnim(index_);
692  }
693 
694  /// Return the time remaining in the current spline animation.
695  /// Time units are defined by the user.
696  MotiveTime TimeRemaining() const { return Processor().TimeRemaining(index_); }
697 
698  std::string CsvHeaderForDebugging() const {
699  return Processor().CsvHeaderForDebugging(index_);
700  }
701  std::string CsvValuesForDebugging() const {
702  return Processor().CsvValuesForDebugging(index_);
703  }
704  std::string LocalTransformsForDebugging(BoneIndex bone) const {
705  return Processor().LocalTransformsForDebugging(index_, bone);
706  }
707 
708  private:
709  RigProcessor& Processor() { return *static_cast<RigProcessor*>(processor_); }
710  const RigProcessor& Processor() const {
711  return *static_cast<const RigProcessor*>(processor_);
712  }
713 };
714 
715 // These Motivator types use mathfu in their external API.
716 typedef MotivatorXfTemplate<MathFuVectorConverter, 1> Motivator1f;
717 typedef MotivatorXfTemplate<MathFuVectorConverter, 2> Motivator2f;
718 typedef MotivatorXfTemplate<MathFuVectorConverter, 3> Motivator3f;
719 typedef MotivatorXfTemplate<MathFuVectorConverter, 4> Motivator4f;
720 typedef MatrixMotivator4fTemplate<MathFuVectorConverter> MatrixMotivator4f;
721 
722 } // namespace motive
723 
724 #endif // MOTIVE_MOTIVATOR_H
virtual const Motivator * ChildMotivator1f(MotiveIndex index, MotiveChildIndex child_index) const =0
Interface for motivator types that drive a single float value.
Definition: processor.h:264
void SetTargetWithShape(const float *target_values, const float *target_velocities, const MotiveCurveShape &shape)
Definition: motivator.h:322
virtual void SetChildTarget1f(MotiveIndex, MotiveChildIndex, const MotiveTarget1f &)
Set child values. Matrices are composed from child components.
Definition: processor.h:383
void BlendToAnim(const RigAnim &anim, const SplinePlayback &playback)
Definition: motivator.h:664
Vec TargetVelocity() const
Definition: motivator.h:452
virtual int NumChildren(MotiveIndex index) const =0
Get the number of matrix operations performed by this motivator.
MotiveCurveShape MotiveShape() const
Returns the shape of the current curve.
Definition: motivator.h:245
void SetSplines(const CompactSpline *splines, const SplinePlayback &playback)
Definition: motivator.h:282
void Initialize(const MotivatorInit &init, MotiveEngine *engine)
Definition: motivator.h:656
void InitializeWithTarget(const MotivatorInit &init, MotiveEngine *engine, const Target &t)
Definition: motivator.h:397
float ChildValue1f(MotiveChildIndex child_index) const
Definition: motivator.h:566
void InitializeWithSplines(const MotivatorInit &init, MotiveEngine *engine, MotiveDimension dimensions, const CompactSpline *splines, const SplinePlayback &playback)
Definition: motivator.h:212
void BlendToOps(const MatrixOpArray &ops, const SplinePlayback &playback)
Definition: motivator.h:630
Utility functions to construct MotiveTargets of dimension >= 2.
Definition: target.h:297
Definition: motivator.h:154
virtual void BlendToAnim(MotiveIndex index, const RigAnim &anim, const motive::SplinePlayback &playback)=0
Smoothly transition to the animation in anim.
virtual void SetPlaybackRate(MotiveIndex index, float playback_rate)=0
Instantly change the playback speed of this animation.
virtual const mathfu::AffineTransform * GlobalTransforms(MotiveIndex index) const =0
void SetSplinesAndTargets(const CompactSpline *const *splines, const SplinePlayback &playback, const MotiveTarget1f *targets)
Definition: motivator.h:337
Drive a 4x4 float matrix from a series of basic transformations.
Definition: motivator.h:518
virtual const mathfu::mat4 & Value(MotiveIndex index) const =0
Get the current matrix value from the processor.
virtual MotiveTime TimeRemaining(MotiveIndex index) const =0
Return the time remaining in the current matrix animation.
A MotiveProcessor processes all instances of one type of Motivator.
Definition: processor.h:58
MotiveTime TimeRemaining() const
Definition: motivator.h:554
MotiveTime TimeRemaining() const
Definition: motivator.h:696
Vec Direction() const
Definition: motivator.h:436
void InitializeWithTargetShape(const MotivatorInit &init, MotiveEngine *engine, MotiveDimension dimensions, const MotiveCurveShape &shape, const Vec &target_values, const Vec &target_velocities)
Definition: motivator.h:407
Animation for a RigMotivator. Drives a fully rigged model.
Definition: anim.h:72
bool ValidMotivator(MotiveIndex index, const Motivator *motivator) const
Definition: processor.h:128
virtual MotivatorType Type() const =0
A target curve shape for the motivator.
Definition: target.h:29
void SetChildValue1f(MotiveChildIndex child_index, float value)
Definition: motivator.h:612
~Motivator()
Remove ourselves from the MotiveProcessor when we're deleted.
Definition: motivator.h:83
Vec3 Position() const
Definition: motivator.h:546
bool Valid() const
Definition: motivator.h:95
Vec3 ChildValue3f(MotiveChildIndex child_index) const
Definition: motivator.h:580
Motivator(const Motivator &original)
Definition: motivator.h:63
const RigAnim * DefiningAnim() const
Definition: motivator.h:690
void Initialize(const MotivatorInit &init, MotiveEngine *engine)
Initialize to the type specified by init.
Definition: motivator.h:530
MotivatorXfTemplate(const MotivatorInit &init, MotiveEngine *engine)
Definition: motivator.h:379
void RemoveMotivator(MotiveIndex index)
void Init(MotiveProcessor *processor, MotiveIndex index)
These should only be called by MotiveProcessor!
Definition: motivator.h:133
virtual void BlendToOps(MotiveIndex, const MatrixOpArray &, const motive::SplinePlayback &)
Smoothly transition to the operations specified in ops.
Definition: processor.h:390
MotiveDimension Dimensions() const
Definition: motivator.h:116
MotiveTime TargetTime() const
Definition: motivator.h:240
Hold and update all animation data.
Definition: engine.h:36
void SetTargets(const MotiveTarget1f *targets)
Definition: motivator.h:307
void Invalidate()
Definition: motivator.h:87
const Mat4 & Value() const
Definition: motivator.h:537
void SetChildTarget1f(MotiveChildIndex child_index, const MotiveTarget1f &t)
Definition: motivator.h:601
virtual void ChildValues(MotiveIndex index, MotiveChildIndex child_index, MotiveChildIndex count, float *values) const =0
Get current values of the components that create the matrix.
friend class MotiveProcessor
Definition: motivator.h:130
Vec TargetValue() const
Definition: motivator.h:444
MotivatorNf(const MotivatorInit &init, MotiveEngine *engine, MotiveDimension dimensions, const MotiveTarget1f *ts)
Definition: motivator.h:168
Parameters to specify how a spline should be traversed.
Definition: compact_spline.h:590
void SetSplineTime(MotiveTime time)
Definition: motivator.h:289
Vec Difference() const
Definition: motivator.h:462
MotivatorXfTemplate(const MotivatorInit &init, MotiveEngine *engine, const Target &t)
Definition: motivator.h:384
MotiveDimension Dimensions(MotiveIndex index) const
Definition: processor.h:153
MotivatorNf()
Definition: motivator.h:158
Drives a value towards a target value, or along a path.
Definition: motivator.h:47
void Initialize(const MotivatorInit &init, MotiveEngine *engine, MotiveDimension dimensions)
Definition: motivator.h:180
Definition: motivator.h:647
Definition: common.h:92
const Mot1f * ChildMotivator1f(MotiveChildIndex child_index) const
Definition: motivator.h:588
void TransferMotivator(MotiveIndex index, Motivator *new_motivator)
Set the current and/or target state for a one-dimensional Motivator.
Definition: target.h:98
MotivatorNf(const MotivatorInit &init, MotiveEngine *engine, MotiveDimension dimensions)
Definition: motivator.h:162
int NumChildren() const
Definition: motivator.h:558
Motivator & operator=(const Motivator &original)
Definition: motivator.h:74
Represent a smooth curve in a small amount of memory.
Definition: compact_spline.h:73
void InitializeWithTargetShape(const MotivatorInit &init, MotiveEngine *engine, MotiveDimension dimensions, const MotiveCurveShape &shape, const float *target_values, const float *target_velocities)
Definition: motivator.h:199
MotiveTime SplineTime() const
Definition: motivator.h:256
const mathfu::AffineTransform * GlobalTransforms() const
Definition: motivator.h:675
void Splines(const CompactSpline **splines) const
Definition: motivator.h:260
Vec Velocity() const
Definition: motivator.h:427
void Initialize(const MotivatorInit &init, MotiveEngine *engine)
Initialize to the motion algorithm specified by init.
Definition: motivator.h:391
void SetTarget(const Target &t)
Definition: motivator.h:483
MotiveProcessor * processor_
Definition: motivator.h:143
virtual const RigAnim * DefiningAnim(MotiveIndex index) const =0
Return the animation that defines the rig.
Definition: init.h:424
void SetChildValue3f(MotiveChildIndex child_index, const Vec3 &value)
Definition: motivator.h:624
void InitializeWithTargets(const MotivatorInit &init, MotiveEngine *engine, MotiveDimension dimensions, const MotiveTarget1f *targets)
Definition: motivator.h:188
void SetTargetWithShape(const Vec &target_value, const Vec &target_velocity, const MotiveCurveShape &shape)
Definition: motivator.h:497
MotivatorXfTemplate()
Definition: motivator.h:375
Vec Value() const
Definition: motivator.h:422
MotivatorType Type() const
Definition: motivator.h:108
void SetSplinePlaybackRate(float playback_rate)
Definition: motivator.h:298
Animate a vector of floating-point values.
Definition: motivator.h:365
bool Sane() const
Definition: motivator.h:100
void SetSpline(const CompactSpline &spline, const SplinePlayback &playback)
Definition: motivator.h:270
virtual void SetPlaybackRate(MotiveIndex index, float playback_rate)=0
Instantly change the playback speed of this animation.
MotiveIndex index_
Definition: motivator.h:148