HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
rotate.hpp
1// Copyright Take Vos 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "matrix.hpp"
8#include "identity.hpp"
9
10namespace tt {
11namespace geo {
12
13template<int D>
14class rotate {
15public:
16 static_assert(D == 2 || D == 3, "Only 2D or 3D rotation-matrices are supported");
17
18 rotate(rotate const &) noexcept = default;
19 rotate(rotate &&) noexcept = default;
20 rotate &operator=(rotate const &) noexcept = default;
21 rotate &operator=(rotate &&) noexcept = default;
22
23 [[nodiscard]] rotate(float angle, vector<3> axis) noexcept requires(D == 3) : _v()
24 {
25 tt_axiom(axis.is_valid());
26 tt_axiom(std::abs(hypot(axis) - 1.0f) < 0.0001f);
27
28 ttlet half_angle = angle * 0.5f;
29 ttlet C = std::cos(half_angle);
30 ttlet S = std::sin(half_angle);
31
32 _v = static_cast<f32x4>(axis) * S;
33 _v.w() = C;
34 }
35
39 [[nodiscard]] constexpr operator matrix<D>() const noexcept
40 {
41 // Original from https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation
42 // 1 - 2(yy + zz) | 2(xy - zw) | 2(xz + yw)
43 // 2(xy + zw) | 1 - 2(xx + zz) | 2(yz - xw)
44 // 2(xz - yw) | 2(yz + xw) | 1 - 2(xx + yy)
45
46 // Flipping adds and multiplies:
47 // 1 - 2(zz + yy) | 2(xy - zw) | 2(yw + xz)
48 // 2(zw + yx) | 1 - 2(xx + zz) | 2(yz - xw)
49 // 2(zx - yw) | 2(xw + zy) | 1 - 2(yy + xx)
50
51 // All multiplies.
52 ttlet x_mul = _v.xxxx() * _v;
53 ttlet y_mul = _v.yyyy() * _v;
54 ttlet z_mul = _v.zzzz() * _v;
55
56 auto twos = f32x4(-2.0f, 2.0f, 2.0f, 0.0f);
57 auto one = f32x4(1.0f, 0.0f, 0.0f, 0.0f);
58 ttlet col0 = one + addsub<0b0011>(z_mul.zwxy(), y_mul.yxwz()) * twos;
59 one = one.yxzw();
60 twos = twos.yxzw();
61 ttlet col1 = one + addsub<0b0110>(x_mul.yxwz(), z_mul.wzyx()) * twos;
62 one = one.xzyw();
63 twos = twos.xzyw();
64 ttlet col2 = one + addsub<0b0101>(y_mul.wzyx(), x_mul.zwxy()) * twos;
65 one = one.xywz();
66 return matrix<D>{col0, col1, col2, one};
67 }
68
69 std::pair<float, vector<3>> angle_and_axis() const noexcept requires(D == 3)
70 {
71 ttlet rcp_length = rcp_hypot<0b0111>(_v);
72 ttlet length = 1.0f / rcp_length;
73
74 return {2.0f * std::atan2(length), vector<3>{_v.xyz0() * rcp_length}};
75 }
76
77private:
81 f32x4 _v;
82};
83
84}
85
86using rotate2 = geo::rotate<2>;
87using rotate3 = geo::rotate<3>;
88
89}
Definition matrix.hpp:18
Definition rotate.hpp:14
A high-level geometric vector Part of the high-level vector, point, mat and color types.
Definition vector.hpp:20
constexpr bool is_valid() const noexcept
Check if the vector is valid.
Definition vector.hpp:234
T atan2(T... args)
T cos(T... args)
T sin(T... args)