• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.replica.replicaisland;
18 
19 /**
20  * Helper class for interpolating velocity over time given a target velocity and acceleration.
21  * The current velocity will be accelerated towards the target until the target is reached.
22  * Note that acceleration is effectively an absolute value--it always points in the direction of
23  * the target velocity.
24  */
25 public class Interpolator extends AllocationGuard {
26 
27     private float mCurrent;
28     private float mTarget;
29     private float mAcceleration;
30 
Interpolator()31     public Interpolator() {
32         super();
33     }
34 
35     // Rather than simply interpolating acceleration and velocity for each time step
36     // (as in, position += (velocity * time); velocity += (acceleration * time);),
37     // we actually perform the work needed to calculate the integral of velocity with respect to
38     // time.
39     //
40     // The integral of velocity is:
41     //
42     // integral[(v + aT)dT]
43     //
44     // Simplified to:
45     //
46     // vT + 1/2 * aT^2
47     //
48     // Thus:
49     // change in position = velocity * time + (0.5 * acceleration * (time^2))
50     // change in velocity = acceleration * time
51 
set(float current, float target, float acceleration)52     public void set(float current, float target, float acceleration) {
53         mCurrent = current;
54         mTarget = target;
55         mAcceleration = acceleration;
56     }
57 
58     // While this function writes directly to velocity, it doesn't affect
59     // position.  Instead, the position offset is returned so that it can be blended.
interpolate(float secondsDelta)60     public float interpolate(float secondsDelta) {
61         float oldVelocity = mCurrent;
62 
63         // point the acceleration at the target, or zero it if we are already
64         // there
65         float directionalAcceleration = calculateAcceleration(oldVelocity, mAcceleration, mTarget);
66 
67         // calculate scaled acceleration (0.5 * acceleration * (time^2))
68         float scaledAcceleration;
69         scaledAcceleration = scaleAcceleration(directionalAcceleration, secondsDelta);
70 
71         // calculate the change in position
72         float positionOffset = (oldVelocity * secondsDelta) + scaledAcceleration;
73 
74         // change in velocity = v + aT
75         float newVelocity = oldVelocity + (directionalAcceleration * secondsDelta);
76 
77         // check to see if we've passed our target velocity since the last time
78         // step.  If so, clamp to the target
79         if (passedTarget(oldVelocity, newVelocity, mTarget)) {
80             newVelocity = mTarget;
81         }
82 
83         mCurrent = newVelocity;
84 
85         return positionOffset;
86     }
87 
getCurrent()88     public float getCurrent() {
89         return mCurrent;
90     }
91 
passedTarget(float oldVelocity, float newVelocity, float targetVelocity)92     private boolean passedTarget(float oldVelocity, float newVelocity, float targetVelocity) {
93         boolean result = false;
94 
95         if (oldVelocity < targetVelocity && newVelocity > targetVelocity) {
96             result = true;
97         } else if (oldVelocity > targetVelocity && newVelocity < targetVelocity) {
98             result = true;
99         }
100 
101         return result;
102     }
103 
104     // find the magnitude and direction of acceleration.
105     // in this system, acceleration always points toward target velocity
calculateAcceleration(float velocity, float acceleration, float target)106     private float calculateAcceleration(float velocity, float acceleration, float target) {
107         if (Math.abs(velocity - target) < 0.0001f) {
108             // no accel needed
109             acceleration = 0.0f;
110         } else if (velocity > target) {
111             // accel must be negative
112             acceleration *= -1.0f;
113         }
114 
115         return acceleration;
116     }
117 
118     // calculates 1/2 aT^2
scaleAcceleration(float acceleration, float secondsDelta)119     private float scaleAcceleration(float acceleration, float secondsDelta) {
120         float timeSquared = (secondsDelta * secondsDelta);
121         float scaledAccel = acceleration * timeSquared;
122         scaledAccel *= 0.5f;
123 
124         return scaledAccel;
125     }
126 }
127