summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--chickadee/math/bezier.scm82
2 files changed, 83 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 10b5e6c..4640581 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -47,6 +47,7 @@ SOURCES = \
chickadee/queue.scm \
chickadee/math.scm \
chickadee/math/vector.scm \
+ chickadee/math/bezier.scm \
chickadee/math/matrix.scm \
chickadee/math/quaternion.scm \
chickadee/math/rect.scm \
diff --git a/chickadee/math/bezier.scm b/chickadee/math/bezier.scm
new file mode 100644
index 0000000..e3dfbba
--- /dev/null
+++ b/chickadee/math/bezier.scm
@@ -0,0 +1,82 @@
+;;; Chickadee Game Toolkit
+;;; Copyright © 2018 David Thompson <davet@gnu.org>
+;;;
+;;; Chickadee is free software: you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published
+;;; by the Free Software Foundation, either version 3 of the License,
+;;; or (at your option) any later version.
+;;;
+;;; Chickadee is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Cubic Bezier curves in 2D space.
+;;
+;;; Code:
+
+(define-module (chickadee math bezier)
+ #:use-module (ice-9 match)
+ #:use-module (srfi srfi-9)
+ #:use-module (chickadee math vector)
+ #:export (make-bezier-curve
+ bezier-curve?
+ bezier-curve-p0
+ bezier-curve-p1
+ bezier-curve-p2
+ bezier-curve-p3
+ bezier-curve-point-at!
+ bezier-curve-point-at
+ bezier-path))
+
+(define-record-type <bezier-curve>
+ (make-bezier-curve p0 p1 p2 p3)
+ bezier-curve?
+ (p0 bezier-curve-p0)
+ (p1 bezier-curve-p1)
+ (p2 bezier-curve-p2)
+ (p3 bezier-curve-p3))
+
+(define (bezier-curve-point-at! dest bezier t)
+ "Write the coordinates for BEZIER at T (a value in the range [0, 1])
+to the 2D vector DEST."
+ (let* ((u (- 1.0 t))
+ (tt (* t t))
+ (uu (* u u))
+ (uuu (* uu u))
+ (ttt (* tt t))
+ (p0 (bezier-curve-p0 bezier))
+ (p1 (bezier-curve-p1 bezier))
+ (p2 (bezier-curve-p2 bezier))
+ (p3 (bezier-curve-p3 bezier)))
+ (set-vec2-x! dest (+ (* uuu (vec2-x p0))
+ (* 3 uu t (vec2-x p1))
+ (* 3 u tt (vec2-x p2))
+ (* ttt (vec2-x p3))))
+ (set-vec2-y! dest (+ (* uuu (vec2-y p0))
+ (* 3 uu t (vec2-y p1))
+ (* 3 u tt (vec2-y p2))
+ (* ttt (vec2-y p3))))))
+
+(define (bezier-curve-point-at bezier t)
+ "Return the coordinates for BEZIER at T (a value in the range [0,
+1]) as a 2D vector."
+ (let ((v #v(0.0 0.0)))
+ (bezier-curve-point-at! v bezier t)
+ v))
+
+(define (bezier-path . control-points)
+ "Return a list of connected bezier curves defined by CONTROL-POINTS.
+The first curve is defined by the first 4 arguments and every
+additional curve thereafter requires 3 additional arguments."
+ (match control-points
+ ((_) '())
+ ((p0 p1 p2 p3 . prest)
+ (cons (make-bezier-curve p0 p1 p2 p3)
+ (apply bezier-path p3 prest)))))