From 26fea26f87427b1ac179f0ed77c6fc9bbc155b13 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 20 Mar 2019 16:26:43 -0700 Subject: [PATCH] Allow construction of a `Transform3DF32` from a quaternion describing a rotation. Closes #111. --- geometry/src/basic/transform3d.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/geometry/src/basic/transform3d.rs b/geometry/src/basic/transform3d.rs index c6ed90a0..5abf477a 100644 --- a/geometry/src/basic/transform3d.rs +++ b/geometry/src/basic/transform3d.rs @@ -97,6 +97,23 @@ impl Transform3DF32 { 0.0, 0.0, 0.0, 1.0) } + /// Creates a rotation matrix from the given quaternion. + /// + /// The quaternion is expected to be packed into a SIMD type (x, y, z, w) corresponding to + /// x + yi + zj + wk. + pub fn from_rotation_quaternion(q: F32x4) -> Transform3DF32 { + // TODO(pcwalton): Optimize better with more shuffles. + let (mut sq, mut w, mut xy_xz_yz) = (q * q, q.wwww() * q, q.xxyy() * q.yzzy()); + sq += sq; w += w; xy_xz_yz += xy_xz_yz; + let diag = F32x4::splat(1.0) - (sq.yxxy() + sq.zzyy()); + let (wx2, wy2, wz2) = (w.x(), w.y(), w.z()); + let (xy2, xz2, yz2) = (xy_xz_yz.x(), xy_xz_yz.y(), xy_xz_yz.z()); + Transform3DF32::row_major(diag.x(), xy2 - wz2, xz2 + wy2, 0.0, + xy2 + wz2, diag.y(), yz2 - wx2, 0.0, + xz2 - wy2, yz2 + wx2, diag.z(), 0.0, + 0.0, 0.0, 0.0, 1.0) + } + /// Just like `glOrtho()`. #[inline] pub fn from_ortho(left: f32, right: f32, bottom: f32, top: f32, near_val: f32, far_val: f32)