• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright 2011 See AUTHORS file.
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.badlogic.gdx.math;
18 
19 /** Takes a linear value in the range of 0-1 and outputs a (usually) non-linear, interpolated value.
20  * @author Nathan Sweet */
21 public abstract class Interpolation {
22 	/** @param a Alpha value between 0 and 1. */
apply(float a)23 	abstract public float apply (float a);
24 
25 	/** @param a Alpha value between 0 and 1. */
apply(float start, float end, float a)26 	public float apply (float start, float end, float a) {
27 		return start + (end - start) * apply(a);
28 	}
29 
30 	//
31 
32 	static public final Interpolation linear = new Interpolation() {
33 		public float apply (float a) {
34 			return a;
35 		}
36 	};
37 
38 	static public final Interpolation fade = new Interpolation() {
39 		public float apply (float a) {
40 			return MathUtils.clamp(a * a * a * (a * (a * 6 - 15) + 10), 0, 1);
41 		}
42 	};
43 
44 	static public final Pow pow2 = new Pow(2);
45 	/** Slow, then fast. */
46 	static public final PowIn pow2In = new PowIn(2);
47 	/** Fast, then slow. */
48 	static public final PowOut pow2Out = new PowOut(2);
49 
50 	static public final Pow pow3 = new Pow(3);
51 	static public final PowIn pow3In = new PowIn(3);
52 	static public final PowOut pow3Out = new PowOut(3);
53 
54 	static public final Pow pow4 = new Pow(4);
55 	static public final PowIn pow4In = new PowIn(4);
56 	static public final PowOut pow4Out = new PowOut(4);
57 
58 	static public final Pow pow5 = new Pow(5);
59 	static public final PowIn pow5In = new PowIn(5);
60 	static public final PowOut pow5Out = new PowOut(5);
61 
62 	static public final Interpolation sine = new Interpolation() {
63 		public float apply (float a) {
64 			return (1 - MathUtils.cos(a * MathUtils.PI)) / 2;
65 		}
66 	};
67 
68 	static public final Interpolation sineIn = new Interpolation() {
69 		public float apply (float a) {
70 			return 1 - MathUtils.cos(a * MathUtils.PI / 2);
71 		}
72 	};
73 
74 	static public final Interpolation sineOut = new Interpolation() {
75 		public float apply (float a) {
76 			return MathUtils.sin(a * MathUtils.PI / 2);
77 		}
78 	};
79 
80 	static public final Exp exp10 = new Exp(2, 10);
81 	static public final ExpIn exp10In = new ExpIn(2, 10);
82 	static public final ExpOut exp10Out = new ExpOut(2, 10);
83 
84 	static public final Exp exp5 = new Exp(2, 5);
85 	static public final ExpIn exp5In = new ExpIn(2, 5);
86 	static public final ExpOut exp5Out = new ExpOut(2, 5);
87 
88 	static public final Interpolation circle = new Interpolation() {
89 		public float apply (float a) {
90 			if (a <= 0.5f) {
91 				a *= 2;
92 				return (1 - (float)Math.sqrt(1 - a * a)) / 2;
93 			}
94 			a--;
95 			a *= 2;
96 			return ((float)Math.sqrt(1 - a * a) + 1) / 2;
97 		}
98 	};
99 
100 	static public final Interpolation circleIn = new Interpolation() {
101 		public float apply (float a) {
102 			return 1 - (float)Math.sqrt(1 - a * a);
103 		}
104 	};
105 
106 	static public final Interpolation circleOut = new Interpolation() {
107 		public float apply (float a) {
108 			a--;
109 			return (float)Math.sqrt(1 - a * a);
110 		}
111 	};
112 
113 	static public final Elastic elastic = new Elastic(2, 10, 7, 1);
114 	static public final ElasticIn elasticIn = new ElasticIn(2, 10, 6, 1);
115 	static public final ElasticOut elasticOut = new ElasticOut(2, 10, 7, 1);
116 
117 	static public final Swing swing = new Swing(1.5f);
118 	static public final SwingIn swingIn = new SwingIn(2f);
119 	static public final SwingOut swingOut = new SwingOut(2f);
120 
121 	static public final Bounce bounce = new Bounce(4);
122 	static public final BounceIn bounceIn = new BounceIn(4);
123 	static public final BounceOut bounceOut = new BounceOut(4);
124 
125 	//
126 
127 	static public class Pow extends Interpolation {
128 		final int power;
129 
Pow(int power)130 		public Pow (int power) {
131 			this.power = power;
132 		}
133 
apply(float a)134 		public float apply (float a) {
135 			if (a <= 0.5f) return (float)Math.pow(a * 2, power) / 2;
136 			return (float)Math.pow((a - 1) * 2, power) / (power % 2 == 0 ? -2 : 2) + 1;
137 		}
138 	}
139 
140 	static public class PowIn extends Pow {
PowIn(int power)141 		public PowIn (int power) {
142 			super(power);
143 		}
144 
apply(float a)145 		public float apply (float a) {
146 			return (float)Math.pow(a, power);
147 		}
148 	}
149 
150 	static public class PowOut extends Pow {
PowOut(int power)151 		public PowOut (int power) {
152 			super(power);
153 		}
154 
apply(float a)155 		public float apply (float a) {
156 			return (float)Math.pow(a - 1, power) * (power % 2 == 0 ? -1 : 1) + 1;
157 		}
158 	}
159 
160 	//
161 
162 	static public class Exp extends Interpolation {
163 		final float value, power, min, scale;
164 
Exp(float value, float power)165 		public Exp (float value, float power) {
166 			this.value = value;
167 			this.power = power;
168 			min = (float)Math.pow(value, -power);
169 			scale = 1 / (1 - min);
170 		}
171 
apply(float a)172 		public float apply (float a) {
173 			if (a <= 0.5f) return ((float)Math.pow(value, power * (a * 2 - 1)) - min) * scale / 2;
174 			return (2 - ((float)Math.pow(value, -power * (a * 2 - 1)) - min) * scale) / 2;
175 		}
176 	};
177 
178 	static public class ExpIn extends Exp {
ExpIn(float value, float power)179 		public ExpIn (float value, float power) {
180 			super(value, power);
181 		}
182 
apply(float a)183 		public float apply (float a) {
184 			return ((float)Math.pow(value, power * (a - 1)) - min) * scale;
185 		}
186 	}
187 
188 	static public class ExpOut extends Exp {
ExpOut(float value, float power)189 		public ExpOut (float value, float power) {
190 			super(value, power);
191 		}
192 
apply(float a)193 		public float apply (float a) {
194 			return 1 - ((float)Math.pow(value, -power * a) - min) * scale;
195 		}
196 	}
197 
198 	//
199 
200 	static public class Elastic extends Interpolation {
201 		final float value, power, scale, bounces;
202 
Elastic(float value, float power, int bounces, float scale)203 		public Elastic (float value, float power, int bounces, float scale) {
204 			this.value = value;
205 			this.power = power;
206 			this.scale = scale;
207 			this.bounces = bounces * MathUtils.PI * (bounces % 2 == 0 ? 1 : -1);
208 		}
209 
apply(float a)210 		public float apply (float a) {
211 			if (a <= 0.5f) {
212 				a *= 2;
213 				return (float)Math.pow(value, power * (a - 1)) * MathUtils.sin(a * bounces) * scale / 2;
214 			}
215 			a = 1 - a;
216 			a *= 2;
217 			return 1 - (float)Math.pow(value, power * (a - 1)) * MathUtils.sin((a) * bounces) * scale / 2;
218 		}
219 	}
220 
221 	static public class ElasticIn extends Elastic {
ElasticIn(float value, float power, int bounces, float scale)222 		public ElasticIn (float value, float power, int bounces, float scale) {
223 			super(value, power, bounces, scale);
224 		}
225 
apply(float a)226 		public float apply (float a) {
227 			if (a >= 0.99) return 1;
228 			return (float)Math.pow(value, power * (a - 1)) * MathUtils.sin(a * bounces) * scale;
229 		}
230 	}
231 
232 	static public class ElasticOut extends Elastic {
ElasticOut(float value, float power, int bounces, float scale)233 		public ElasticOut (float value, float power, int bounces, float scale) {
234 			super(value, power, bounces, scale);
235 		}
236 
apply(float a)237 		public float apply (float a) {
238 			a = 1 - a;
239 			return (1 - (float)Math.pow(value, power * (a - 1)) * MathUtils.sin(a * bounces) * scale);
240 		}
241 	}
242 
243 	//
244 
245 	static public class Bounce extends BounceOut {
Bounce(float[] widths, float[] heights)246 		public Bounce (float[] widths, float[] heights) {
247 			super(widths, heights);
248 		}
249 
Bounce(int bounces)250 		public Bounce (int bounces) {
251 			super(bounces);
252 		}
253 
out(float a)254 		private float out (float a) {
255 			float test = a + widths[0] / 2;
256 			if (test < widths[0]) return test / (widths[0] / 2) - 1;
257 			return super.apply(a);
258 		}
259 
apply(float a)260 		public float apply (float a) {
261 			if (a <= 0.5f) return (1 - out(1 - a * 2)) / 2;
262 			return out(a * 2 - 1) / 2 + 0.5f;
263 		}
264 	}
265 
266 	static public class BounceOut extends Interpolation {
267 		final float[] widths, heights;
268 
BounceOut(float[] widths, float[] heights)269 		public BounceOut (float[] widths, float[] heights) {
270 			if (widths.length != heights.length)
271 				throw new IllegalArgumentException("Must be the same number of widths and heights.");
272 			this.widths = widths;
273 			this.heights = heights;
274 		}
275 
BounceOut(int bounces)276 		public BounceOut (int bounces) {
277 			if (bounces < 2 || bounces > 5) throw new IllegalArgumentException("bounces cannot be < 2 or > 5: " + bounces);
278 			widths = new float[bounces];
279 			heights = new float[bounces];
280 			heights[0] = 1;
281 			switch (bounces) {
282 			case 2:
283 				widths[0] = 0.6f;
284 				widths[1] = 0.4f;
285 				heights[1] = 0.33f;
286 				break;
287 			case 3:
288 				widths[0] = 0.4f;
289 				widths[1] = 0.4f;
290 				widths[2] = 0.2f;
291 				heights[1] = 0.33f;
292 				heights[2] = 0.1f;
293 				break;
294 			case 4:
295 				widths[0] = 0.34f;
296 				widths[1] = 0.34f;
297 				widths[2] = 0.2f;
298 				widths[3] = 0.15f;
299 				heights[1] = 0.26f;
300 				heights[2] = 0.11f;
301 				heights[3] = 0.03f;
302 				break;
303 			case 5:
304 				widths[0] = 0.3f;
305 				widths[1] = 0.3f;
306 				widths[2] = 0.2f;
307 				widths[3] = 0.1f;
308 				widths[4] = 0.1f;
309 				heights[1] = 0.45f;
310 				heights[2] = 0.3f;
311 				heights[3] = 0.15f;
312 				heights[4] = 0.06f;
313 				break;
314 			}
315 			widths[0] *= 2;
316 		}
317 
apply(float a)318 		public float apply (float a) {
319 			a += widths[0] / 2;
320 			float width = 0, height = 0;
321 			for (int i = 0, n = widths.length; i < n; i++) {
322 				width = widths[i];
323 				if (a <= width) {
324 					height = heights[i];
325 					break;
326 				}
327 				a -= width;
328 			}
329 			a /= width;
330 			float z = 4 / width * height * a;
331 			return 1 - (z - z * a) * width;
332 		}
333 	}
334 
335 	static public class BounceIn extends BounceOut {
BounceIn(float[] widths, float[] heights)336 		public BounceIn (float[] widths, float[] heights) {
337 			super(widths, heights);
338 		}
339 
BounceIn(int bounces)340 		public BounceIn (int bounces) {
341 			super(bounces);
342 		}
343 
apply(float a)344 		public float apply (float a) {
345 			return 1 - super.apply(1 - a);
346 		}
347 	}
348 
349 	//
350 
351 	static public class Swing extends Interpolation {
352 		private final float scale;
353 
Swing(float scale)354 		public Swing (float scale) {
355 			this.scale = scale * 2;
356 		}
357 
apply(float a)358 		public float apply (float a) {
359 			if (a <= 0.5f) {
360 				a *= 2;
361 				return a * a * ((scale + 1) * a - scale) / 2;
362 			}
363 			a--;
364 			a *= 2;
365 			return a * a * ((scale + 1) * a + scale) / 2 + 1;
366 		}
367 	}
368 
369 	static public class SwingOut extends Interpolation {
370 		private final float scale;
371 
SwingOut(float scale)372 		public SwingOut (float scale) {
373 			this.scale = scale;
374 		}
375 
apply(float a)376 		public float apply (float a) {
377 			a--;
378 			return a * a * ((scale + 1) * a + scale) + 1;
379 		}
380 	}
381 
382 	static public class SwingIn extends Interpolation {
383 		private final float scale;
384 
SwingIn(float scale)385 		public SwingIn (float scale) {
386 			this.scale = scale;
387 		}
388 
apply(float a)389 		public float apply (float a) {
390 			return a * a * ((scale + 1) * a - scale);
391 		}
392 	}
393 }
394