our_dick/include/math/quat.hpp

164 lines
5.5 KiB
C++

/**
This file is a part of our_dick
Copyright (C) 2020 rexy712
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef REXY_QUAT_HPP
#define REXY_QUAT_HPP
#include <cstdlib> //size_t
#include <utility> //pair
#include <type_traits> //is_same, is_arithmetic, integral_constant
#include "math_common.hpp"
#include "fwd_declare.hpp"
namespace math{
//( ͡° ͜ʖ ͡°)
template<class T>
class quaternion
{
public:
using value_type = T;
using size_type = size_t;
using pointer = value_type*;
using const_pointer = const value_type*;
using reference = value_type&;
using const_reference = const value_type&;
private:
value_type m_data[4];
public:
constexpr quaternion(void);
//Construct from Euler angles
constexpr quaternion(detail::zero_initialize_t);
constexpr quaternion(detail::id_initialize_t);
constexpr quaternion(detail::no_initialize_t);
constexpr quaternion(detail::manual_initialize_t,
value_type w, value_type x,
value_type y, value_type z);
quaternion(const mat3<T>& rotmat);
quaternion(const mat4<T>& rotmat);
quaternion(value_type bank, value_type heading, value_type attitude);
quaternion(const vec3<value_type>& angles);
//Construct from axis-angle
quaternion(value_type angle, const vec3<value_type>& axis);
quaternion(value_type angle, value_type x, value_type y, value_type z);
//Copy ctor
constexpr quaternion(const quaternion&) = default;
constexpr quaternion(quaternion&&) = default;
~quaternion(void) = default;
//Assignment
constexpr quaternion& operator=(const quaternion&) = default;
constexpr quaternion& operator=(quaternion&&) = default;
//Direct array access
constexpr operator pointer(void);
constexpr operator const_pointer(void)const;
constexpr reference operator[](size_type i);
constexpr const_reference operator[](size_type i)const;
constexpr reference get(size_type i);
constexpr const_reference get(size_type i)const;
constexpr reference w(void);
constexpr const_reference w(void)const;
constexpr reference x(void);
constexpr const_reference x(void)const;
constexpr reference y(void);
constexpr const_reference y(void)const;
constexpr reference z(void);
constexpr const_reference z(void)const;
//Assign axis from angle-axis
void set_axis(value_type x, value_type y, value_type z);
void set_axis(const vec3<value_type>& axis);
vec3<value_type> get_axis(void)const;
void set_angle(value_type a);
value_type get_angle(void)const;
value_type norm(void)const;
quaternion conjugate(void)const;
quaternion inverse(void)const;
value_type magnitude(void)const;
quaternion normalize(void)const;
vec3<value_type> get_right(void)const;
vec3<value_type> get_up(void)const;
vec3<value_type> get_forward(void)const;
//Explicit Conversion1
vec3<value_type> to_vec3(void)const;
vec4<value_type> to_vec4(void)const;
mat3<value_type> to_mat3(void)const;
mat4<value_type> to_mat4(void)const;
vec3<value_type> to_euler_angles(void)const;
std::pair<value_type,vec3<value_type>> to_axis_angle(void)const;
};
namespace detail{
template<class T>
struct is_quat_helper {
template<class U>
static std::true_type test(quaternion<U>*);
static std::false_type test(void*);
static constexpr bool value = std::is_same<std::true_type,decltype(test(static_cast<std::decay_t<T>*>(nullptr)))>::value;
};
}
template<class... Qs>
struct is_quaternion {
static constexpr bool value = (detail::is_quat_helper<Qs>::value && ...);
};
template<class T, class U>
bool operator==(const quaternion<T>& left, const quaternion<U>& right);
template<class T, class U>
bool operator!=(const quaternion<T>& left, const quaternion<U>& right);
template<class T>
auto operator-(const quaternion<T>& left);
template<class T, class U>
auto operator-(const quaternion<T>& left, const quaternion<U>& right);
template<class T, class U>
auto operator+(const quaternion<T>& left, const quaternion<U>& right);
template<class T, class U>
auto operator*(const quaternion<T>& left, const quaternion<U>& right);
template<class T, class U>
auto operator*(const quaternion<T>& left, const vec3<U>& right);
template<class T, class U> requires Compatible_Scalar<U,T>
auto operator*(const quaternion<T>& left, U&& right);
template<class T, class U> requires Compatible_Scalar<U,T>
auto operator/(const quaternion<T>& left, U&& right);
template<class T, class U>
decltype(auto) operator+=(quaternion<T>& left, const quaternion<U>& right);
template<class T, class U>
decltype(auto) operator-=(quaternion<T>& left, const quaternion<U>& right);
template<class T, class U>
decltype(auto) operator*=(quaternion<T>& left, const quaternion<U>& right);
template<class T, class U> requires Compatible_Scalar<U,T>
decltype(auto) operator*=(quaternion<T>& left, U&& right);
template<class T, class U> requires Compatible_Scalar<U,T>
decltype(auto) operator/=(quaternion<T>& left, U&& right);
}
#include "quat.tpp"
#endif