blob: 6ed59d45584f587e07bc7a327391c149c3646030 [file] [log] [blame]
// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef COBALT_RENDERER_SMOOTHED_VALUE_H_
#define COBALT_RENDERER_SMOOTHED_VALUE_H_
#include "base/optional.h"
#include "base/time.h"
namespace cobalt {
namespace renderer {
// Smooths a value over time. Currently implemented using bezier curve.
class SmoothedValue {
public:
// |time_to_converge| indicates how long it takes for the current value
// to converge to a newly set target value. A |max_slope_magnitude| can
// be provided to dictate the maximum slope the value will move by as it
// transitions from one value to another. It must be greater than 0, if
// provided, and it can result in convergence times larger than
// |time_to_converge|.
explicit SmoothedValue(
base::TimeDelta time_to_converge,
base::optional<double> max_slope_magnitude = base::optional<double>());
// Sets the target value that GetCurrentValue() will smoothly converge
// towards.
void SetTarget(double target, const base::TimeTicks& time);
// Snaps GetCurrentValue() to the last set target value.
void SnapToTarget();
// Returns the current value, which is always converging slowly towards
// the last set target value.
double GetValueAtTime(const base::TimeTicks& time) const;
private:
// The following methods return the parameters for the cubic bezier equation.
// https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves
// Returns the value of t to be used in cubic bezier equations.
double t(const base::TimeTicks& time) const;
double P0() const { return *previous_value_; }
// Returns the value of P1 to be used in cubic bezier equations.
// Here, we calculate it from |previous_derivative_| and |previous_value_|
// in such a way that it results in a curve that at t = 0 has a derivative
// equal to |previous_deriviative_|.
double P1() const;
// Returns the value of P2 to be used in cubic bezier equations.
// For us, we set it in such a way that the derivative at t = 1 is 0.
double P2() const;
double P3() const { return *target_; }
// Returns the current derivative of GetCurrentValue() over time.
double GetCurrentDerivative(const base::TimeTicks& time) const;
// Returns the derivative of the function that has the highest magnitude
// between 0 and 1.
double GetDerivativeWithLargestMagnitude() const;
const base::TimeDelta time_to_converge_;
// The current target value that we are converging towards.
base::optional<double> target_;
// Tracks when |target_| was last set.
base::TimeTicks target_set_time_;
// The value returned by GetCurrentValue() at the time that the target was
// last set.
base::optional<double> previous_value_;
// The derivative of GetCurrentValue() when target was last set.
double previous_derivative_;
base::optional<double> max_slope_magnitude_;
};
} // namespace renderer
} // namespace cobalt
#endif // COBALT_RENDERER_SMOOTHED_VALUE_H_