summaryrefslogtreecommitdiff
path: root/src/modules/shapes/shapes.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/shapes/shapes.c')
-rw-r--r--src/modules/shapes/shapes.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/modules/shapes/shapes.c b/src/modules/shapes/shapes.c
index 6de14ee..236861c 100644
--- a/src/modules/shapes/shapes.c
+++ b/src/modules/shapes/shapes.c
@@ -113,6 +113,45 @@ static void shapes_prepare_frame(til_module_context_t *context, til_stream_t *st
}
+/* simple approximation taken from https://mazzo.li/posts/vectorized-atan2.html */
+static inline float atan_scalar_approximation(float x) {
+ /* TODO: this is probably more terms/precision than needed, but when I try just dropping some,
+ * the circle+slight pinches gets artifacts. So leaving for now, probably needs slightly different
+ * values for fewer terms.
+ */
+ float a1 = 0.99997726f;
+ float a3 = -0.33262347f;
+ float a5 = 0.19354346f;
+ float a7 = -0.11643287f;
+ float a9 = 0.05265332f;
+ float a11 = -0.01172120f;
+ float x_sq = x*x;
+
+ return x * (a1 + x_sq * (a3 + x_sq * (a5 + x_sq * (a7 + x_sq * (a9 + x_sq * a11)))));
+}
+
+
+static float atan2_approx(float y, float x) {
+ // Ensure input is in [-1, +1]
+ int swap = fabs(x) < fabs(y);
+ float atan_input = (swap ? x : y) / (swap ? y : x);
+
+ // Approximate atan
+ float res = atan_scalar_approximation(atan_input);
+
+ // If swapped, adjust atan output
+ res = swap ? (atan_input >= 0.0f ? M_PI_2 : -M_PI_2) - res : res;
+
+ // Adjust quadrants
+ if (x < 0.0f && y >= 0.0f)
+ res = M_PI + res; // 2nd quadrant
+ else if (x < 0.0f && y < 0.0f)
+ res = -M_PI + res; // 3rd quadrant
+
+ return res;
+}
+
+
static void shapes_render_fragment(til_module_context_t *context, til_stream_t *stream, unsigned ticks, unsigned cpu, til_fb_fragment_t **fragment_ptr)
{
shapes_context_t *ctxt = (shapes_context_t *)context;
© All Rights Reserved