utils: added bezier shaping functions from flong

This commit is contained in:
2017-06-05 20:15:27 -04:00
parent cb46e2a602
commit 82905fcb61

View File

@@ -136,3 +136,132 @@ float normalized_log_sigmoid(float x, float a) {
a = 1. / (1. + exp(0. -((x-.5)*a*2.)));
return (a-b)/(c-b);
}
// bezier shaping
float quad_bezier(float x, vec2 ab) {
float e = 0.00001;
float a = clamp(ab.x, 0., 1.);
float b = clamp(ab.y, 0., 1.);
if (a == 0.5) a += e;
float om2a = 1. - 2.*a;
float t = (sqrt(a*a + om2a*x) - a)/om2a;
return (1.-2.*b)*(t*t) + (2.*b)*t;
}
// cubic bezier begin
float slope_from_t(float t, float A, float B, float C) {
return 1.0/(3.0*A*t*t + 2.0*B*t + C);
}
float x_from_t(float t, float A, float B, float C, float D) {
return A*(t*t*t) + B*(t*t) + C*t + D;
}
float y_from_t(float t, float E, float F, float G, float H) {
return E*(t*t*t) + F*(t*t) + G*t + H;
}
float cubic_bezier(float x, vec2 a, vec2 b) {
float y0a = 0.00;
float x0a = 0.00;
float y1a = a.y;
float x1a = a.x;
float y2a = b.y;
float x2a = b.x;
float y3a = 1.00;
float x3a = 1.00;
float A = x3a - 3.*x2a + 3.*x1a - x0a;
float B = 3.*x2a - 6.*x1a + 3.*x0a;
float C = 3.*x1a - 3.*x0a;
float D = x0a;
float E = y3a - 3.*y2a + 3.*y1a - y0a;
float F = 3.*y2a - 6.*y1a + 3.*y0a;
float G = 3.*y1a - 3.*y0a;
float H = y0a;
float currentt = x;
for (int i=0; i < 5; i++){
float currentx = x_from_t(currentt, A, B, C, D);
float currentslope = slope_from_t(currentt, A, B, C);
currentt -= (currentx - x)*(currentslope);
currentt = clamp(currentt, 0., 1.);
}
float y = y_from_t(currentt, E, F, G, H);
return y;
}
// cubic bezier end
// cubic bezier through points (requires cubic bezier) begin
float b0 (float t){
return (1.-t)*(1.-t)*(1.-t);
}
float b1 (float t){
return 3.*t* (1.-t)*(1.-t);
}
float b2 (float t){
return 3.*t*t* (1.-t);
}
float b3 (float t){
return t*t*t;
}
float findx(float t, float x0, float x1, float x2, float x3) {
return x0*b0(t) + x1*b1(t) + x2*b2(t) + x3*b3(t);
}
float findy(float t, float y0, float y1, float y2, float y3) {
return y0*b0(t) + y1*b1(t) + y2*b2(t) + y3*b3(t);
}
float cubic_bezier_through(float x, vec2 a, vec2 b) {
float y = 0.;
float e = 0.00001;
float minp = 0. + e;
float maxp = 1. - e;
a = clamp(a, minp, maxp);
b = clamp(b, minp, maxp);
float x0 = 0.;
float y0 = 0.;
float x4 = a.x;
float y4 = a.y;
float x5 = b.x;
float y5 = b.y;
float x3 = 1.;
float y3 = 1.;
float x1,y1,x2,y2;
// arbitrary but reasonable
float t1 = 0.3;
float t2 = 0.7;
float b0t1 = b0(t1);
float b1t1 = b1(t1);
float b2t1 = b2(t1);
float b3t1 = b3(t1);
float b0t2 = b0(t2);
float b1t2 = b1(t2);
float b2t2 = b2(t2);
float b3t2 = b3(t2);
float ccx = x4 - x0*b0t1 - x3*b3t1;
float ccy = y4 - y0*b0t1 - y3*b3t1;
float ffx = x5 - x0*b0t2 - x3*b3t2;
float ffy = y5 - y0*b0t2 - y3*b3t2;
x2 = (ccx - (ffx*b1t1)/b1t2) / (b2t1 - (b1t1*b2t2)/b1t2);
y2 = (ccy - (ffy*b1t1)/b1t2) / (b2t1 - (b1t1*b2t2)/b1t2);
x1 = (ccx - x2*b2t1) / b1t1;
y1 = (ccy - y2*b2t1) / b1t1;
x1 = clamp(x1, minp, maxp);
x2 = clamp(x2, minp, maxp);
y = cubic_bezier(x, vec2(x1,y1), vec2(x2,y2));
return clamp(y, 0., 1.);
}
// cubic bezier through points end