From 64274f4264ae5c86ac90ecfa41a36903bf100c59 Mon Sep 17 00:00:00 2001 From: David Thomas Date: Thu, 22 Feb 2024 10:46:19 +0000 Subject: [PATCH] Fixed point curve_bezier_cubic - first attempt --- include/framebuf/curve.h | 9 +- libraries/framebuf/curve/curve.c | 107 ++++++++++++++++++--- libraries/framebuf/curve/test/curve-test.c | 2 +- 3 files changed, 104 insertions(+), 14 deletions(-) diff --git a/include/framebuf/curve.h b/include/framebuf/curve.h index 004cafb..0fabe06 100644 --- a/include/framebuf/curve.h +++ b/include/framebuf/curve.h @@ -53,7 +53,7 @@ point_t curve_bezier_point_on_quartic_r(point_t p0, point_t p4, fix16_t t); -// written in terms of cubics (and in turn of quads) +// written in terms of quartics (and in turn of cubics, etc.) point_t curve_bezier_point_on_quintic_r(point_t p0, point_t p1, point_t p2, @@ -70,4 +70,11 @@ void curve_bezier_cubic_f(point_t p0, int nsteps, point_t *points); +void curve_bezier_cubic(point_t p0, + point_t p1, + point_t p2, + point_t p3, + int nsteps, + point_t *points); + #endif /* DPTLIB_CURVE_H */ diff --git a/libraries/framebuf/curve/curve.c b/libraries/framebuf/curve/curve.c index 97742d1..a64d908 100644 --- a/libraries/framebuf/curve/curve.c +++ b/libraries/framebuf/curve/curve.c @@ -1,8 +1,13 @@ /* bezier.c */ -// - Eliminate structure passing, or at least analyse some code with it inlined to see if it helps -// - Does these need to round to nearest? -// - Consider overflow too +// TODO +// +// - Eliminate structure passing, or at least analyse some code with it inlined +// to see if it hinders or helps +// - Consider rounding. +// - Consider overflow too. + +#include #include "base/utils.h" @@ -10,17 +15,12 @@ #include "framebuf/curve.h" -point_t curve_point_on_line(point_t p0, point_t p1, fix16_t t) -{ - point_t c; - - c.x = p0.x + (p1.x - p0.x) * t / 65536; - c.y = p0.y + (p1.y - p0.y) * t / 65536; +/* ----------------------------------------------------------------------- */ - return c; -} +#define LOG2SCALE (4) +#define SCALE (1 << LOG2SCALE) -#define SCALE (16) +/* ----------------------------------------------------------------------- */ static point_t scale_up(point_t p) { @@ -40,6 +40,20 @@ static point_t scale_down(point_t p) return q; } +/* ----------------------------------------------------------------------- */ + +point_t curve_point_on_line(point_t p0, point_t p1, fix16_t t) +{ + point_t c; + + c.x = p0.x + (p1.x - p0.x) * t / FIX16_ONE; + c.y = p0.y + (p1.y - p0.y) * t / FIX16_ONE; + + return c; +} + +/* ----------------------------------------------------------------------- */ + point_t curve_bezier_point_on_quad(point_t p0, point_t p1, point_t p2, @@ -291,3 +305,72 @@ void curve_bezier_cubic_f(point_t p0, d2y += d3y; } } + +// attempt at an integer version +void curve_bezier_cubic(point_t p0, + point_t p1, + point_t p2, + point_t p3, + int nsteps, + point_t *points) +{ + fix16_t cx, cy; + fix16_t bx, by; + fix16_t ax, ay; + fix16_t h, hh, hhh; + fix16_t d1x, d1y; + fix16_t d2x, d2y; + fix16_t d3x, d3y; + fix16_t curx, cury; + int i; + point_t *point; + + cx = 3 * (p1.x - p0.x) * FIX16_ONE; + cy = 3 * (p1.y - p0.y) * FIX16_ONE; + + bx = 3 * (p2.x - p1.x) * FIX16_ONE - cx; + by = 3 * (p2.y - p1.y) * FIX16_ONE - cy; + + ax = (p3.x - p0.x) * FIX16_ONE - cx - bx; + ay = (p3.y - p0.y) * FIX16_ONE - cy - by; + + h = FIX16_ONE / nsteps; + hh = h * h / FIX16_ONE; + hhh = hh * h / FIX16_ONE; + + /* first difference */ + d1x = (ax * (long long) hhh + bx * (long long) hh + cx * (long long) h) / FIX16_ONE; + d1y = (ay * (long long) hhh + by * (long long) hh + cy * (long long) h) / FIX16_ONE; + + /* second difference */ + d2x = (6 * ax * (long long) hhh + 2 * bx * (long long) hh) / FIX16_ONE; + d2y = (6 * ay * (long long) hhh + 2 * by * (long long) hh) / FIX16_ONE; + + /* third difference */ + d3x = (6 * ax * (long long) hhh) / FIX16_ONE; + d3y = (6 * ay * (long long) hhh) / FIX16_ONE; + + point = &points[0]; + + curx = p0.x * FIX16_ONE; + cury = p0.y * FIX16_ONE; + + for (i = 0; ; i++) + { + point->x = (int) (curx >> FIX16_SHIFT); + point->y = (int) (cury >> FIX16_SHIFT); + point++; + + if (i == nsteps) + break; + + curx += d1x; + cury += d1y; + + d1x += d2x; + d1y += d2y; + + d2x += d3x; + d2y += d3y; + } +} diff --git a/libraries/framebuf/curve/test/curve-test.c b/libraries/framebuf/curve/test/curve-test.c index f8b5208..9a1ee8f 100644 --- a/libraries/framebuf/curve/test/curve-test.c +++ b/libraries/framebuf/curve/test/curve-test.c @@ -411,7 +411,7 @@ static void calc_all_curves(curveteststate_t *state) if (curves[set].kind == FwdDiffCubic) { - curve_bezier_cubic_f(state->jitterfn(state->control_points[o + 0]), + curve_bezier_cubic(state->jitterfn(state->control_points[o + 0]), state->jitterfn(state->control_points[o + 1]), state->jitterfn(state->control_points[o + 2]), state->jitterfn(state->control_points[o + 3]),