1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-03 09:57:46 +01:00
Telegram/thirdparty/RMIntro/core/timing.c
2014-07-10 18:11:09 +04:00

132 lines
3.5 KiB
C

//
// timing.c
// IntroOpenGL
//
// Created by Ilya Rimchikov on 03/05/14.
// Copyright (c) 2014 IntroOpenGL. All rights reserved.
//
#include "timing.h"
static inline float evaluateAtParameterWithCoefficients(float t, float coefficients[])
{
return coefficients[0] + t*coefficients[1] + t*t*coefficients[2] + t*t*t*coefficients[3];
}
static inline float evaluateDerivationAtParameterWithCoefficients(float t, float coefficients[])
{
return coefficients[1] + 2*t*coefficients[2] + 3*t*t*coefficients[3];
}
static inline float calcParameterViaNewtonRaphsonUsingXAndCoefficientsForX(float x, float coefficientsX[])
{
// see http://en.wikipedia.org/wiki/Newton's_method
// start with X being the correct value
float t = x;
// iterate several times
//const float epsilon = 0.00001;
int i;
for(i = 0; i < 10; i++)
{
float x2 = evaluateAtParameterWithCoefficients(t, coefficientsX) - x;
float d = evaluateDerivationAtParameterWithCoefficients(t, coefficientsX);
float dt = x2/d;
t = t - dt;
}
return t;
}
static inline float calcParameterUsingXAndCoefficientsForX (float x, float coefficientsX[])
{
// for the time being, we'll guess Newton-Raphson always
// returns the correct value.
// if we find it doesn't find the solution often enough,
// we can add additional calculation methods.
float t = calcParameterViaNewtonRaphsonUsingXAndCoefficientsForX(x, coefficientsX);
return t;
}
static int is_initialized=0;
static float _coefficientsX[TIMING_NUM][4], _coefficientsY[TIMING_NUM][4];
static const float _c0x = 0.0;
static const float _c0y = 0.0;
static const float _c3x = 1.0;
static const float _c3y = 1.0;
float timing(float x, timing_type type)
{
if (is_initialized==0) {
is_initialized=1;
float c[TIMING_NUM][4];
c[Default][0]=0.25;
c[Default][1]=0.1;
c[Default][2]=0.25;
c[Default][3]=1.0;
c[EaseInEaseOut][0]=0.42;
c[EaseInEaseOut][1]=0.0;
c[EaseInEaseOut][2]=0.58;
c[EaseInEaseOut][3]=1.0;
c[EaseIn][0]=0.42;
c[EaseIn][1]=0.0;
c[EaseIn][2]=1.0;
c[EaseIn][3]=1.0;
c[EaseOut][0]=0.0;
c[EaseOut][1]=0.0;
c[EaseOut][2]=0.58;
c[EaseOut][3]=1.0;
c[Linear][0]=0.0;
c[Linear][1]=0.0;
c[Linear][2]=1.0;
c[Linear][3]=1.0;
int i;
for (i=0; i<TIMING_NUM; i++) {
float _c1x = c[i][0];
float _c1y = c[i][1];
float _c2x = c[i][2];
float _c2y = c[i][3];
_coefficientsX[i][0] = _c0x; // t^0
_coefficientsX[i][1] = -3.0*_c0x + 3.0*_c1x; // t^1
_coefficientsX[i][2] = 3.0*_c0x - 6.0*_c1x + 3.0*_c2x; // t^2
_coefficientsX[i][3] = -_c0x + 3.0*_c1x - 3.0*_c2x + _c3x; // t^3
_coefficientsY[i][0] = _c0y; // t^0
_coefficientsY[i][1] = -3.0*_c0y + 3.0*_c1y; // t^1
_coefficientsY[i][2] = 3.0*_c0y - 6.0*_c1y + 3.0*_c2y; // t^2
_coefficientsY[i][3] = -_c0y + 3.0*_c1y - 3.0*_c2y + _c3y; // t^3
}
}
if (x==0.0 || x==1.0) {
return x;
}
float t = calcParameterUsingXAndCoefficientsForX(x, _coefficientsX[type]);
float y = evaluateAtParameterWithCoefficients(t, _coefficientsY[type]);
return y;
}