1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_layers_AxisPhysicsModel_h 8 #define mozilla_layers_AxisPhysicsModel_h 9 10 #include <sys/types.h> // for int32_t 11 #include "mozilla/TimeStamp.h" // for TimeDuration 12 13 namespace mozilla { 14 namespace layers { 15 16 /** 17 * AxisPhysicsModel encapsulates a generic 1-dimensional physically-based motion 18 * model. 19 * 20 * It performs frame-rate independent interpolation and RK4 integration for 21 * smooth animation with stable, deterministic behavior. 22 * Implementations are expected to subclass and override the Acceleration() 23 * method. 24 */ 25 class AxisPhysicsModel { 26 public: 27 AxisPhysicsModel(double aInitialPosition, double aInitialVelocity); 28 virtual ~AxisPhysicsModel(); 29 30 /** 31 * Advance the physics simulation. 32 * |aDelta| is the time since the last sample. 33 */ 34 void Simulate(const TimeDuration& aDeltaTime); 35 36 /** 37 * Gets the raw velocity of this axis at this moment. 38 */ 39 double GetVelocity() const; 40 41 /** 42 * Sets the raw velocity of this axis at this moment. 43 */ 44 void SetVelocity(double aVelocity); 45 46 /** 47 * Gets the raw position of this axis at this moment. 48 */ 49 double GetPosition() const; 50 51 /** 52 * Sets the raw position of this axis at this moment. 53 */ 54 void SetPosition(double aPosition); 55 56 protected: 57 struct State { StateState58 State(double ap, double av) : p(ap), v(av){}; 59 double p; // Position 60 double v; // Velocity 61 }; 62 63 struct Derivative { DerivativeDerivative64 Derivative() : dp(0.0), dv(0.0){}; DerivativeDerivative65 Derivative(double aDp, double aDv) : dp(aDp), dv(aDv){}; 66 double dp; // dp / delta time = Position 67 double dv; // dv / delta time = Velocity 68 }; 69 70 /** 71 * Acceleration must be overridden and return the number of 72 * axis-position-units / second that should be added or removed from the 73 * velocity. 74 */ 75 virtual double Acceleration(const State& aState) = 0; 76 77 private: 78 /** 79 * Duration of fixed delta time step (seconds) 80 */ 81 static const double kFixedTimestep; 82 83 /** 84 * 0.0 - 1.0 value indicating progress between current and next simulation 85 * sample. Normalized to units of kFixedTimestep duration. 86 */ 87 double mProgress; 88 89 /** 90 * Sample of simulation state as it existed 91 * (1.0 - mProgress) * kFixedTimestep seconds in the past. 92 */ 93 State mPrevState; 94 95 /** 96 * Sample of simulation state as it will be in mProgress * kFixedTimestep 97 * seconds in the future. 98 */ 99 State mNextState; 100 101 /** 102 * Perform RK4 (Runge-Kutta method) Integration to calculate the next 103 * simulation sample. 104 */ 105 void Integrate(double aDeltaTime); 106 107 /** 108 * Apply delta velocity and position represented by aDerivative over 109 * aDeltaTime seconds, calculate new acceleration, and return new deltas. 110 */ 111 Derivative Evaluate(const State& aInitState, double aDeltaTime, 112 const Derivative& aDerivative); 113 114 /** 115 * Helper function for performing linear interpolation (lerp) of double's 116 */ 117 static double LinearInterpolate(double aV1, double aV2, double aBlend); 118 }; 119 120 } // namespace layers 121 } // namespace mozilla 122 123 #endif 124