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