## ~pbatch/gest

9673cd5d04b75d9e02994c225e53a41fdb0efca6 — Paul Batchelor 2 months ago
```added bezier behavior
```
```3 files changed, 123 insertions(+), 4 deletions(-)

M gest.org
M l_gest.c
M test.lil
```
`M gest.org => gest.org +95 -3`
```@@ 617,7 617,7 @@ void gest_loopit(gest_d *g)
* Behavior Commands
Behaviors are the means by which one target gets to thep
next target.
-** Linear behavior
+** Linear
Linear: converts the last target to use linear behavior.

#+NAME: funcdefs

@@ 637,7 637,7 @@ void gest_behavior_linear(gest_d *g)
g->curtarget->tick = linear;
}
#+END_SRC
-** Step behavior
+** Step
Step: converts the last target to be a step (no line, just
the value).

@@ 721,7 721,7 @@ void gest_behavior_smallgliss(gest_d *g)
}
#+END_SRC

-** Exponential behavior
+** Exponential
Exponential: converts the last target to use exponential
behavior with slope =slope=.

@@ 756,6 756,98 @@ void gest_behavior_exponential(gest_d *g, SKFLT slope)
*s = slope;
}
#+END_SRC
+** Bezier
+Applies a quadratic Bezier line segment between to two
+targets. Bezier takes in two control values that are
+control targets.
+
+#+NAME: funcdefs
+#+BEGIN_SRC c
+void gest_behavior_bezier(gest_d *g, SKFLT cx, SKFLT cy);
+#+END_SRC
+
+Explanation for how this works is already done in
+the sndkit Bezier algorithm where this is
+code is based, so it's worth checking
+that out for the mathematical derivation.
+
+#+NAME: funcs
+#+BEGIN_SRC c
+struct bezier_data {
+    SKFLT cx;
+    SKFLT cy;
+};
+
+/* https://pbat.ch/sndkit/bezier/ */
+
+static SKFLT quadratic_equation(SKFLT a, SKFLT b, SKFLT c)
+{
+    SKFLT det; /* determinant */
+
+    det = b*b - 4*a*c;
+
+    if (det >= 0) {
+        return ((-b + sqrt(det))/(2.0*a));
+    } else {
+        return 0;
+    }
+}
+
+static SKFLT find_t(SKFLT x0, SKFLT x1, SKFLT x2, SKFLT x)
+{
+    SKFLT a, b, c;
+
+    a = (x0 - 2.0 * x1 + x2);
+    b = 2.0 * (-x0 + x1);
+    c = x0 - x;
+
+    if (a) {
+    } else {
+        return (x - x0) / b;
+    }
+}
+
+static SKFLT bezier_curve(SKFLT xpos, SKFLT cx, SKFLT cy)
+{
+    SKFLT x[3];
+    SKFLT y[3];
+    SKFLT t;
+    SKFLT val;
+
+    x[0] = 0;
+    x[1] = cx;
+    x[2] = 1;
+
+    y[0] = 0;
+    y[1] = cy;
+    y[2] = 1;
+
+    t = find_t(x[0], x[1], x[2], xpos);
+
+    val = (1.0-t)*(1.0-t)*y[0] + 2.0*(1 - t)*t*y[1] + t*t*y[2];
+    return val;
+}
+
+static SKFLT bezier(gest_d *g, SKFLT x, SKFLT y, SKFLT a, void *ud)
+{
+
+    struct bezier_data *bd;
+    bd = ud;
+    a = bezier_curve(a, bd->cx, bd->cy);
+    return (1 - a)*x + a*y;
+}
+
+void gest_behavior_bezier(gest_d *g, SKFLT cx, SKFLT cy)
+{
+    struct bezier_data *bd;
+    g->curtarget->tick = bezier;
+    g->curtarget->ud = gest_alloc(g, sizeof(struct bezier_data));
+    bd = (struct bezier_data *)g->curtarget->ud;
+    bd->cx = cx;
+    bd->cy = cy;
+}
+#+END_SRC
* Temporal Weight Commands
** mass
=gest_mass= the global mass to an absolute value.

```
`M l_gest.c => l_gest.c +26 -1`
```@@ 321,7 321,7 @@ static lil_value_t l_gest_exponential(lil_t lil,
SKFLT val;

core = lil_get_data(lil);
-    SKLIL_ARITY_CHECK(lil, "gest_target", argc, 1);
+    SKLIL_ARITY_CHECK(lil, "gest_exponential", argc, 1);
rc = sk_core_generic_pop(core, (void **)&g);
SKLIL_ERROR_CHECK(lil, rc, "couldn't get gest data.");

@@ 333,6 333,30 @@ static lil_value_t l_gest_exponential(lil_t lil,
return NULL;
}

+static lil_value_t l_gest_bezier(lil_t lil,
+                                 size_t argc,
+                                 lil_value_t *argv)
+{
+    sk_core *core;
+    gest_d *g;
+    int rc;
+    SKFLT cx;
+    SKFLT cy;
+
+    core = lil_get_data(lil);
+    SKLIL_ARITY_CHECK(lil, "gest_bezier", argc, 2);
+    rc = sk_core_generic_pop(core, (void **)&g);
+    SKLIL_ERROR_CHECK(lil, rc, "couldn't get gest data.");
+
+    cx = lil_to_double(argv[0]);
+    cy = lil_to_double(argv[1]);
+
+    gest_behavior_bezier(g, cx, cy);
+
+    sk_core_generic_push(core, g);
+    return NULL;
+}
+

{

@@ 353,4 377,5 @@ void sklil_load_gest(lil_t lil)
lil_register(lil, "gest_gliss", l_gest_gliss);
lil_register(lil, "gest_smallgliss", l_gest_smallgliss);
lil_register(lil, "gest_exponential", l_gest_exponential);
+    lil_register(lil, "gest_bezier", l_gest_bezier);
}

```
`M test.lil => test.lil +2 -0`
```@@ 42,8 42,10 @@ func modindex {} {
gest_begin 3 3
gest_monoramp 2
gest_target 0
+    gest_bezier 0.4 1

gest_target 2
+    gest_exponential 3
gest_end
gest_loopit
gest_finish

```