Bug 1018255 - Use spring physics for snap-back animation. r=kats

--HG--
extra : source : f7f4c40fc818c2342fe6c49c0351c1573f6e9f3d
This commit is contained in:
Botond Ballo 2014-06-03 13:59:35 -04:00
parent 4bcd1d61cd
commit 81fc6320fa
5 changed files with 35 additions and 32 deletions

View File

@ -960,8 +960,9 @@ pref("apz.overscroll.fling_friction", "0.02");
pref("apz.overscroll.fling_stopped_threshold", "0.4");
pref("apz.overscroll.clamping", "0.5");
pref("apz.overscroll.z_effect", "0.2");
pref("apz.overscroll.snap_back_accel", "0.003");
pref("apz.overscroll.snap_back_init_vel", "1");
pref("apz.overscroll.snap_back.spring_stiffness", "0.6");
pref("apz.overscroll.snap_back.spring_friction", "0.1");
pref("apz.overscroll.snap_back.mass", "1000");
// This preference allows FirefoxOS apps (and content, I think) to force
// the use of software (instead of hardware accelerated) 2D canvases by

View File

@ -235,13 +235,17 @@ typedef GeckoContentController::APZStateChange APZStateChange;
* opposite axis creates the effect of the page moving away from you along a
* "z" axis.
*
* "apz.overscroll.snap_back_accel"
* Amount of acceleration applied during the snap-back animation.
* "apz.overscroll.snap_back.spring_stiffness"
* The stiffness of the spring used in the physics model for the overscroll
* snap-back animation.
*
* "apz.overscroll.snap_back_init_vel"
* Initial velocity of a snap-back animation along one axis.
* Units: screen pixels per millisecond
* requests.
* "apz.overscroll.snap_back.spring_damping"
* The friction of the spring used in the physics model for the overscroll
* snap-back animation.
*
* "apz.overscroll.snap_back.mass"
* The mass of the page in the physics model for the overscroll snap-back
* animation.
*
* "apz.pan_repaint_interval"
* Maximum amount of time while panning before sending a viewport change. This
@ -490,11 +494,7 @@ private:
class OverscrollSnapBackAnimation: public AsyncPanZoomAnimation {
public:
OverscrollSnapBackAnimation(AsyncPanZoomController& aApzc)
: mApzc(aApzc)
{
mApzc.mX.StartSnapBack();
mApzc.mY.StartSnapBack();
}
: mApzc(aApzc) {}
virtual bool Sample(FrameMetrics& aFrameMetrics,
const TimeDuration& aDelta) MOZ_OVERRIDE

View File

@ -121,21 +121,27 @@ float Axis::GetOverscroll() const {
return mOverscroll;
}
void Axis::StartSnapBack() {
float initialSnapBackVelocity = gfxPrefs::APZSnapBackInitialVelocity();
if (mOverscroll > 0) {
mVelocity = -initialSnapBackVelocity;
} else {
mVelocity = initialSnapBackVelocity;
}
}
bool Axis::SampleSnapBack(const TimeDuration& aDelta) {
// Accelerate the snap-back as time goes on.
// Note: this method of acceleration isn't perfectly smooth, as it assumes
// Apply spring physics to the snap-back as time goes on.
// Note: this method of sampling isn't perfectly smooth, as it assumes
// a constant velocity over 'aDelta', instead of an accelerating velocity.
// (The way we applying friction to flings has the same issue.)
mVelocity *= pow(1.0f + gfxPrefs::APZSnapBackAcceleration(), float(aDelta.ToMilliseconds()));
// Hooke's law with damping:
// F = -kx - bv
// where
// k is a constant related to the stiffness of the spring
// The larger the constant, the stiffer the spring.
// x is the displacement of the end of the spring from its equilibrium
// In our scenario, it's the amount of overscroll on the axis.
// b is a constant that provides damping (friction)
// v is the velocity of the point at the end of the spring
// See http://gafferongames.com/game-physics/spring-physics/
const float kSpringStiffness = gfxPrefs::APZOverscrollSnapBackSpringStiffness();
const float kSpringFriction = gfxPrefs::APZOverscrollSnapBackSpringFriction();
const float kMass = gfxPrefs::APZOverscrollSnapBackMass();
float force = -1 * kSpringStiffness * mOverscroll - kSpringFriction * mVelocity;
float acceleration = force / kMass;
mVelocity += acceleration * aDelta.ToMilliseconds();
float screenDisplacement = mVelocity * aDelta.ToMilliseconds();
float cssDisplacement = screenDisplacement / GetFrameMetrics().GetZoom().scale;
if (mOverscroll > 0) {

View File

@ -98,11 +98,6 @@ public:
*/
float GetOverscroll() const;
/**
* Start a snap-back animation to relieve overscroll.
*/
void StartSnapBack();
/**
* Sample the snap-back animation to relieve overscroll.
* |aDelta| is the time since the last sample.

View File

@ -126,8 +126,9 @@ private:
DECL_GFX_PREF(Live, "apz.overscroll.fling_stopped_threshold", APZOverscrollFlingStoppedThreshold, float, 0.4f);
DECL_GFX_PREF(Live, "apz.overscroll.clamping", APZOverscrollClamping, float, 0.5f);
DECL_GFX_PREF(Live, "apz.overscroll.z_effect", APZOverscrollZEffect, float, 0.2f);
DECL_GFX_PREF(Once, "apz.overscroll.snap_back_accel", APZSnapBackAcceleration, float, 0.002f);
DECL_GFX_PREF(Live, "apz.overscroll.snap_back_init_vel", APZSnapBackInitialVelocity, float, 1.0f);
DECL_GFX_PREF(Live, "apz.overscroll.snap_back.spring_stiffness", APZOverscrollSnapBackSpringStiffness, float, 0.6f);
DECL_GFX_PREF(Live, "apz.overscroll.snap_back.spring_friction", APZOverscrollSnapBackSpringFriction, float, 0.1f);
DECL_GFX_PREF(Live, "apz.overscroll.snap_back.mass", APZOverscrollSnapBackMass, float, 1000.0f);
DECL_GFX_PREF(Live, "apz.pan_repaint_interval", APZPanRepaintInterval, int32_t, 250);
DECL_GFX_PREF(Live, "apz.subframe.enabled", APZSubframeEnabled, bool, false);
DECL_GFX_PREF(Once, "apz.test.logging_enabled", APZTestLoggingEnabled, bool, false);