23 Mode mode()
const {
return m_mode; }
24 bool active()
const {
return m_mode != Mode::Idle; }
25 double target()
const {
return m_target; }
26 unsigned long long revision()
const {
return m_revision; }
33 void fling(
double position,
double velocity,
double deceleration,
double now) {
37 m_velocity = velocity;
38 m_rate = std::max(1.0, deceleration);
40 m_target = position + velocity * std::abs(velocity) / (2 * m_rate);
43 void smooth(
double position,
double velocity,
double target,
double now) {
45 m_mode = Mode::Target;
47 m_velocity = velocity;
53 void translate(
double delta) {
59 Sample sample(
double now)
const {
60 const double elapsed = std::max(0.0, now - m_time);
61 if (m_mode == Mode::Idle)
return { m_start, 0,
true };
62 if (m_mode == Mode::Fling) {
63 const double duration = std::abs(m_velocity) / m_rate;
64 if (elapsed >= duration)
return { m_target, 0,
true };
65 const double acceleration = -std::copysign(m_rate, m_velocity);
66 return { m_start + m_velocity * elapsed + acceleration * elapsed * elapsed / 2,
67 m_velocity + acceleration * elapsed,
70 const double distance = m_start - m_target;
71 const double b = m_velocity + m_rate * distance;
72 const double decay = std::exp(-m_rate * elapsed);
73 const double offset = (distance + b * elapsed) * decay;
74 const double velocity = (b - m_rate * (distance + b * elapsed)) * decay;
75 if (std::abs(offset) < 0.01 && std::abs(velocity) < 0.1)
return { m_target, 0,
true };
76 return { m_target + offset, velocity,
false };
80 unsigned long long m_revision { 0 };
81 Mode m_mode { Mode::Idle };
83 double m_velocity { 0 };
84 double m_target { 0 };