aboutsummaryrefslogtreecommitdiff
path: root/quaternion.c
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2023-01-27 22:57:21 +0000
committerrodri <rgl@antares-labs.eu>2023-01-27 22:57:21 +0000
commitfdeaa2423c582df8d9e9ae6b0e26d386b5531262 (patch)
tree26762f0636448354a5c8e6c62756009120dd353e /quaternion.c
parent278c3d3be924246488226ae89e67616955dce661 (diff)
downloadlibgeometry-fdeaa2423c582df8d9e9ae6b0e26d386b5531262.tar.gz
libgeometry-fdeaa2423c582df8d9e9ae6b0e26d386b5531262.tar.bz2
libgeometry-fdeaa2423c582df8d9e9ae6b0e26d386b5531262.zip
bring the slerp function, make ptinpoly public and clean some of the code.
Diffstat (limited to 'quaternion.c')
-rw-r--r--quaternion.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/quaternion.c b/quaternion.c
index 686c04e..ca44747 100644
--- a/quaternion.c
+++ b/quaternion.c
@@ -78,6 +78,24 @@ normq(Quaternion q)
return sdivq(q, qlen(q));
}
+/*
+ * based on the implementation from:
+ *
+ * Jonathan Blow, “Understanding Slerp, Then Not Using it”,
+ * The Inner Product, April 2004.
+ */
+Quaternion
+slerp(Quaternion q, Quaternion r, double t)
+{
+ Quaternion v;
+ double θ, q·r;
+
+ q·r = fclamp(dotq(q, r), -1, 1); /* stay within the domain of acos(2) */
+ θ = acos(q·r)*t;
+ v = normq(subq(r, smulq(q, q·r))); /* v = r - (q·r)q / |v| */
+ return addq(smulq(q, cos(θ)), smulq(v, sin(θ))); /* q cos(θ) + v sin(θ) */
+}
+
Point3
qrotate(Point3 p, Point3 axis, double θ)
{