Add quaternions. Move math to separate directory

This commit is contained in:
rexy712 2020-08-17 09:30:42 -07:00
parent f79a3cc9bd
commit 71278c460a
15 changed files with 1117 additions and 330 deletions

View File

@ -1,37 +0,0 @@
/**
This file is a part of the rexy/r0nk/atlas project
Copyright (C) 2020 rexy712
This program 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.
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 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/>.
*/
#ifndef REXY_DETAIL_MATH_HPP
#define REXY_DETAIL_MATH_HPP
namespace math{
namespace detail{
struct zero_initialize_t{};
struct no_initialize_t{};
struct id_initialize_t{};
}
static inline constexpr detail::zero_initialize_t zero_initialize;
static inline constexpr detail::no_initialize_t no_initialize;
static inline constexpr detail::id_initialize_t id_initialize;
}
#endif

View File

@ -1,227 +0,0 @@
/**
This file is a part of the rexy/r0nk/atlas project
Copyright (C) 2020 rexy712
This program 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.
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 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/>.
*/
#ifndef REXY_DETAIL_MATRIX_HPP
#define REXY_DETAIL_MATRIX_HPP
#include <cstdlib> //size_t
#include <utility> //integer_sequence
namespace math::detail{
template<size_t SW, size_t W = SW, size_t H = SW-1, size_t... Args>
struct gen_id_tup {
using tup = typename gen_id_tup<SW, W-1, H, Args..., 0>::tup;
};
template<size_t SW, size_t H, size_t... Args>
struct gen_id_tup<SW,SW,H,Args...> {
using tup = typename gen_id_tup<SW, SW-1, H, Args..., 1>::tup;
};
template<size_t SW, size_t H, size_t... Args>
struct gen_id_tup<SW,0,H,Args...> {
using tup = typename gen_id_tup<SW, SW, H-1, Args..., 0>::tup;
};
template<size_t SW, size_t... Args>
struct gen_id_tup<SW,SW,0,Args...> {
using tup = std::integer_sequence<size_t,Args...,1>;
};
template<size_t N, size_t... Args>
struct gen_zero_tup {
using tup = typename gen_zero_tup<N-1,Args...,0>::tup;
};
template<size_t... Args>
struct gen_zero_tup<0,Args...> {
using tup = std::integer_sequence<size_t,Args...>;
};
template<size_t W>
struct id_initialization_matrix {
using tuple = typename gen_id_tup<W>::tup;
};
template<size_t W, size_t H>
struct default_initialization_matrix {
using tuple = typename gen_zero_tup<W>::tup;
};
template<size_t W>
struct default_initialization_matrix<W,W> {
using tuple = typename id_initialization_matrix<W>::tuple;
};
template<typename T, size_t R>
class mat_ref_obj
{
public:
using size_type = size_t;
protected:
T* m_data = nullptr;
public:
constexpr mat_ref_obj(T* d, size_type i);
constexpr T& operator[](size_type i);
constexpr const T& operator[](size_type i)const;
};
template<typename T, size_t R>
struct determinate_helper {
static constexpr T perform(const matrix<T,R,R>& m){
T sum = 0;
T op = 1;
for(size_t i = 0;i < R;++i){
T item = op * m[0][i];
matrix<T,R-1,R-1> mul(no_initialize);
for(size_t j = 1, mj = 0;j < R;++j){
for(size_t k = 0, mk = 0;k < R;++k){
if(k == i)
continue;
mul[mj][mk] = m[j][k];
++mk;
}
++mj;
}
sum += item * determinate_helper<T,R-1>::perform(mul);
op = -op;
}
return sum;
}
};
template<typename T>
struct determinate_helper<T,3> {
static constexpr T perform(const matrix<T,3,3>& m){
return (m.get(0) * ((m.get(4) * m.get(8)) - (m.get(5) * m.get(7))) -
m.get(1) * ((m.get(3) * m.get(8)) - (m.get(5) * m.get(6))) +
m.get(2) * ((m.get(3) * m.get(7)) - (m.get(4) * m.get(6))));
}
};
template<typename T>
struct determinate_helper<T,2> {
static constexpr T perform(const matrix<T,2,2>& m){
return m.get(0) * m.get(3) - m.get(1) * m.get(2);
}
};
template<typename T, size_t R>
struct inverse_helper {
//TODO generalized inverse
};
template<typename T>
struct inverse_helper<T,2> {
static constexpr matrix<T,2,2> perform(const matrix<T,2,2>& m){
T det = m.determinate();
if(!det)
return matrix<T,2,2>(zero_initialize);
return matrix<T,2,2>(m.get(3) / det, -(m.get(1)) / det, -(m.get(2)) / det, m.get(0) / det);
}
};
template<typename T>
struct inverse_helper<T,3> {
static constexpr matrix<T,3,3> perform(const matrix<T,3,3>& m){
T det = m.determinate();
if(!det)
return matrix<T,3,3>(zero_initialize);
return matrix<T,3,3>(((m.get(4) * m.get(8)) - (m.get(5) * m.get(7))) / det,
-((m.get(1) * m.get(8)) - (m.get(2) * m.get(7))) / det,
((m.get(1) * m.get(5)) - (m.get(2) * m.get(4))) / det,
-((m.get(3) * m.get(8)) - (m.get(5) * m.get(6))) / det,
((m.get(0) * m.get(8)) - (m.get(2) * m.get(6))) / det,
-((m.get(0) * m.get(5)) - (m.get(2) * m.get(3))) / det,
((m.get(3) * m.get(7)) - (m.get(4) * m.get(6))) / det,
-((m.get(0) * m.get(7)) - (m.get(1) * m.get(6))) / det,
((m.get(0) * m.get(4)) - (m.get(1) * m.get(3))) / det);
}
};
template<typename T>
struct inverse_helper<T,4> {
static constexpr matrix<T,4,4> perform(const matrix<T,4,4>& m){
T det = m.determinate();
if(!det)
return matrix<T,4,4>(zero_initialize);
//Math is power
return matrix<T,4,4>((m.get(5) * ((m.get(10) * m.get(15)) - (m.get(11) * m.get(14))) -
m.get(6) * ((m.get(9) * m.get(15)) - (m.get(11) * m.get(13))) +
m.get(7) * ((m.get(9) * m.get(14)) - (m.get(10) * m.get(13)))) / det,
-(m.get(1) * ((m.get(10) * m.get(15)) - (m.get(11) * m.get(14))) -
m.get(2) * ((m.get(9) * m.get(15)) - (m.get(11) * m.get(13))) +
m.get(3) * ((m.get(9) * m.get(14)) - (m.get(10) * m.get(13)))) / det,
(m.get(1) * ((m.get(6) * m.get(15)) - (m.get(7) * m.get(14))) -
m.get(2) * ((m.get(5) * m.get(15)) - (m.get(7) * m.get(13))) +
m.get(3) * ((m.get(5) * m.get(14)) - (m.get(6) * m.get(13)))) / det,
-(m.get(1) * ((m.get(6) * m.get(11)) - (m.get(7) * m.get(10))) -
m.get(2) * ((m.get(5) * m.get(11)) - (m.get(7) * m.get(9))) +
m.get(3) * ((m.get(5) * m.get(10)) - (m.get(6) * m.get(9)))) / det,
-(m.get(4) * ((m.get(10) * m.get(15)) - (m.get(11) * m.get(14))) -
m.get(6) * ((m.get(8) * m.get(15)) - (m.get(11) * m.get(12))) +
m.get(7) * ((m.get(8) * m.get(14)) - (m.get(10) * m.get(12)))) / det,
(m.get(0) * ((m.get(10) * m.get(15)) - (m.get(11) * m.get(14))) -
m.get(2) * ((m.get(8) * m.get(15)) - (m.get(11) * m.get(12))) +
m.get(3) * ((m.get(8) * m.get(14)) - (m.get(10) * m.get(12)))) / det,
-(m.get(0) * ((m.get(6) * m.get(15)) - (m.get(7) * m.get(14))) -
m.get(2) * ((m.get(4) * m.get(15)) - (m.get(7) * m.get(12))) +
m.get(3) * ((m.get(4) * m.get(14)) - (m.get(6) * m.get(12)))) / det,
(m.get(0) * ((m.get(6) * m.get(11)) - (m.get(7) * m.get(10))) -
m.get(2) * ((m.get(4) * m.get(11)) - (m.get(7) * m.get(8))) +
m.get(3) * ((m.get(4) * m.get(10)) - (m.get(6) * m.get(8)))) / det,
(m.get(4) * ((m.get(9) * m.get(15)) - (m.get(11) * m.get(13))) -
m.get(5) * ((m.get(8) * m.get(15)) - (m.get(11) * m.get(12))) +
m.get(7) * ((m.get(8) * m.get(13)) - (m.get(9) * m.get(12)))) / det,
-(m.get(0) * ((m.get(9) * m.get(15)) - (m.get(11) * m.get(13))) -
m.get(1) * ((m.get(8) * m.get(15)) - (m.get(11) * m.get(12))) +
m.get(3) * ((m.get(8) * m.get(13)) - (m.get(9) * m.get(12)))) / det,
(m.get(0) * ((m.get(5) * m.get(15)) - (m.get(7) * m.get(13))) -
m.get(1) * ((m.get(4) * m.get(15)) - (m.get(7) * m.get(12))) +
m.get(3) * ((m.get(4) * m.get(13)) - (m.get(5) * m.get(12)))) / det,
-(m.get(0) * ((m.get(5) * m.get(11)) - (m.get(7) * m.get(9))) -
m.get(1) * ((m.get(4) * m.get(11)) - (m.get(7) * m.get(8))) +
m.get(3) * ((m.get(4) * m.get(9)) - (m.get(5) * m.get(8)))) / det,
-(m.get(4) * ((m.get(9) * m.get(14)) - (m.get(10) * m.get(13))) -
m.get(5) * ((m.get(8) * m.get(14)) - (m.get(10) * m.get(12))) +
m.get(6) * ((m.get(8) * m.get(13)) - (m.get(9) * m.get(12)))) / det,
(m.get(0) * ((m.get(9) * m.get(14)) - (m.get(10) * m.get(13))) -
m.get(1) * ((m.get(8) * m.get(14)) - (m.get(10) * m.get(12))) +
m.get(2) * ((m.get(8) * m.get(13)) - (m.get(9) * m.get(12)))) / det,
-(m.get(0) * ((m.get(5) * m.get(14)) - (m.get(6) * m.get(13))) -
m.get(1) * ((m.get(4) * m.get(14)) - (m.get(6) * m.get(12))) +
m.get(2) * ((m.get(4) * m.get(13)) - (m.get(5) * m.get(12)))) / det,
(m.get(0) * ((m.get(5) * m.get(10)) - (m.get(6) * m.get(9))) -
m.get(1) * ((m.get(4) * m.get(10)) - (m.get(6) * m.get(8))) +
m.get(2) * ((m.get(4) * m.get(9)) - (m.get(5) * m.get(8)))) / det);
}
};
}
#include "matrix.tpp"
#endif

View File

@ -1,42 +0,0 @@
/**
This file is a part of the rexy/r0nk/atlas project
Copyright (C) 2020 rexy712
This program 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.
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 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/>.
*/
#ifndef REXY_DETAIL_MATRIX_TPP
#define REXY_DETAIL_MATRIX_TPP
#include <cstdlib> //size_t
#include <utility> //integer_sequence
namespace math::detail{
template<typename T, size_t R>
constexpr mat_ref_obj<T,R>::mat_ref_obj(T* d, size_type i):
m_data(d+i){}
template<typename T, size_t R>
constexpr T& mat_ref_obj<T,R>::operator[](size_type i){
return m_data[i*R];
}
template<typename T, size_t R>
constexpr const T& mat_ref_obj<T,R>::operator[](size_type i)const{
return m_data[i*R];
}
}
#endif

View File

@ -0,0 +1,116 @@
/**
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_DETAIL_MATRIX_HPP
#define REXY_DETAIL_MATRIX_HPP
#include <cstdlib> //size_t
#include <utility> //integer_sequence
namespace math::detail{
template<size_t SW, size_t W = SW, size_t H = SW-1, size_t... Args>
struct gen_id_tup {
using tup = typename gen_id_tup<SW, W-1, H, Args..., 0>::tup;
};
template<size_t SW, size_t H, size_t... Args>
struct gen_id_tup<SW,SW,H,Args...> {
using tup = typename gen_id_tup<SW, SW-1, H, Args..., 1>::tup;
};
template<size_t SW, size_t H, size_t... Args>
struct gen_id_tup<SW,0,H,Args...> {
using tup = typename gen_id_tup<SW, SW, H-1, Args..., 0>::tup;
};
template<size_t SW, size_t... Args>
struct gen_id_tup<SW,SW,0,Args...> {
using tup = std::integer_sequence<size_t,Args...,1>;
};
template<size_t N, size_t... Args>
struct gen_zero_tup {
using tup = typename gen_zero_tup<N-1,Args...,0>::tup;
};
template<size_t... Args>
struct gen_zero_tup<0,Args...> {
using tup = std::integer_sequence<size_t,Args...>;
};
template<size_t W>
struct id_initialization_matrix {
using tuple = typename gen_id_tup<W>::tup;
};
template<size_t W, size_t H>
struct default_initialization_matrix {
using tuple = typename gen_zero_tup<W>::tup;
};
template<size_t W>
struct default_initialization_matrix<W,W> {
using tuple = typename id_initialization_matrix<W>::tuple;
};
template<typename T, size_t R>
class mat_ref_obj
{
public:
using size_type = size_t;
protected:
T* m_data = nullptr;
public:
constexpr mat_ref_obj(T* d, size_type i);
constexpr T& operator[](size_type i);
constexpr const T& operator[](size_type i)const;
};
template<typename T, size_t R>
struct determinate_helper {
static constexpr T perform(const matrix<T,R,R>& m);
};
template<typename T>
struct determinate_helper<T,3> {
static constexpr T perform(const matrix<T,3,3>& m);
};
template<typename T>
struct determinate_helper<T,2> {
static constexpr T perform(const matrix<T,2,2>& m);
};
template<typename T, size_t R>
struct inverse_helper {
//TODO generalized inverse
};
template<typename T>
struct inverse_helper<T,2> {
static constexpr matrix<T,2,2> perform(const matrix<T,2,2>& m);
};
template<typename T>
struct inverse_helper<T,3> {
static constexpr matrix<T,3,3> perform(const matrix<T,3,3>& m);
};
template<typename T>
struct inverse_helper<T,4> {
static constexpr matrix<T,4,4> perform(const matrix<T,4,4>& m);
};
}
#include "matrix.tpp"
#endif

View File

@ -0,0 +1,166 @@
/**
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_DETAIL_MATRIX_TPP
#define REXY_DETAIL_MATRIX_TPP
#include <cstdlib> //size_t
#include <utility> //integer_sequence
namespace math::detail{
template<typename T, size_t R>
constexpr mat_ref_obj<T,R>::mat_ref_obj(T* d, size_type i):
m_data(d+i){}
template<typename T, size_t R>
constexpr T& mat_ref_obj<T,R>::operator[](size_type i){
return m_data[i*R];
}
template<typename T, size_t R>
constexpr const T& mat_ref_obj<T,R>::operator[](size_type i)const{
return m_data[i*R];
}
template<typename T, size_t R>
constexpr T determinate_helper<T,R>::perform(const matrix<T,R,R>& m){
T sum = 0;
T op = 1;
for(size_t i = 0;i < R;++i){
T item = op * m[0][i];
matrix<T,R-1,R-1> mul(no_initialize);
for(size_t j = 1, mj = 0;j < R;++j){
for(size_t k = 0, mk = 0;k < R;++k){
if(k == i)
continue;
mul[mj][mk] = m[j][k];
++mk;
}
++mj;
}
sum += item * determinate_helper<T,R-1>::perform(mul);
op = -op;
}
return sum;
}
template<typename T>
constexpr T determinate_helper<T,3>::perform(const matrix<T,3,3>& m){
return (m.get(0) * ((m.get(4) * m.get(8)) - (m.get(5) * m.get(7))) -
m.get(1) * ((m.get(3) * m.get(8)) - (m.get(5) * m.get(6))) +
m.get(2) * ((m.get(3) * m.get(7)) - (m.get(4) * m.get(6))));
}
template<typename T>
constexpr T determinate_helper<T,2>::perform(const matrix<T,2,2>& m){
return m.get(0) * m.get(3) - m.get(1) * m.get(2);
}
template<typename T>
constexpr matrix<T,2,2> inverse_helper<T,2>::perform(const matrix<T,2,2>& m){
T det = m.determinate();
if(!det)
return matrix<T,2,2>(zero_initialize);
return matrix<T,2,2>(m.get(3) / det, -(m.get(1)) / det, -(m.get(2)) / det, m.get(0) / det);
}
template<typename T>
constexpr matrix<T,3,3> inverse_helper<T,3>::perform(const matrix<T,3,3>& m){
T det = m.determinate();
if(!det)
return matrix<T,3,3>(zero_initialize);
return matrix<T,3,3>(((m.get(4) * m.get(8)) - (m.get(5) * m.get(7))) / det,
-((m.get(1) * m.get(8)) - (m.get(2) * m.get(7))) / det,
((m.get(1) * m.get(5)) - (m.get(2) * m.get(4))) / det,
-((m.get(3) * m.get(8)) - (m.get(5) * m.get(6))) / det,
((m.get(0) * m.get(8)) - (m.get(2) * m.get(6))) / det,
-((m.get(0) * m.get(5)) - (m.get(2) * m.get(3))) / det,
((m.get(3) * m.get(7)) - (m.get(4) * m.get(6))) / det,
-((m.get(0) * m.get(7)) - (m.get(1) * m.get(6))) / det,
((m.get(0) * m.get(4)) - (m.get(1) * m.get(3))) / det);
}
template<typename T>
constexpr matrix<T,4,4> inverse_helper<T,4>::perform(const matrix<T,4,4>& m){
T det = m.determinate();
if(!det)
return matrix<T,4,4>(zero_initialize);
//Math is power
return matrix<T,4,4>((m.get(5) * ((m.get(10) * m.get(15)) - (m.get(11) * m.get(14))) -
m.get(6) * ((m.get(9) * m.get(15)) - (m.get(11) * m.get(13))) +
m.get(7) * ((m.get(9) * m.get(14)) - (m.get(10) * m.get(13)))) / det,
-(m.get(1) * ((m.get(10) * m.get(15)) - (m.get(11) * m.get(14))) -
m.get(2) * ((m.get(9) * m.get(15)) - (m.get(11) * m.get(13))) +
m.get(3) * ((m.get(9) * m.get(14)) - (m.get(10) * m.get(13)))) / det,
(m.get(1) * ((m.get(6) * m.get(15)) - (m.get(7) * m.get(14))) -
m.get(2) * ((m.get(5) * m.get(15)) - (m.get(7) * m.get(13))) +
m.get(3) * ((m.get(5) * m.get(14)) - (m.get(6) * m.get(13)))) / det,
-(m.get(1) * ((m.get(6) * m.get(11)) - (m.get(7) * m.get(10))) -
m.get(2) * ((m.get(5) * m.get(11)) - (m.get(7) * m.get(9))) +
m.get(3) * ((m.get(5) * m.get(10)) - (m.get(6) * m.get(9)))) / det,
-(m.get(4) * ((m.get(10) * m.get(15)) - (m.get(11) * m.get(14))) -
m.get(6) * ((m.get(8) * m.get(15)) - (m.get(11) * m.get(12))) +
m.get(7) * ((m.get(8) * m.get(14)) - (m.get(10) * m.get(12)))) / det,
(m.get(0) * ((m.get(10) * m.get(15)) - (m.get(11) * m.get(14))) -
m.get(2) * ((m.get(8) * m.get(15)) - (m.get(11) * m.get(12))) +
m.get(3) * ((m.get(8) * m.get(14)) - (m.get(10) * m.get(12)))) / det,
-(m.get(0) * ((m.get(6) * m.get(15)) - (m.get(7) * m.get(14))) -
m.get(2) * ((m.get(4) * m.get(15)) - (m.get(7) * m.get(12))) +
m.get(3) * ((m.get(4) * m.get(14)) - (m.get(6) * m.get(12)))) / det,
(m.get(0) * ((m.get(6) * m.get(11)) - (m.get(7) * m.get(10))) -
m.get(2) * ((m.get(4) * m.get(11)) - (m.get(7) * m.get(8))) +
m.get(3) * ((m.get(4) * m.get(10)) - (m.get(6) * m.get(8)))) / det,
(m.get(4) * ((m.get(9) * m.get(15)) - (m.get(11) * m.get(13))) -
m.get(5) * ((m.get(8) * m.get(15)) - (m.get(11) * m.get(12))) +
m.get(7) * ((m.get(8) * m.get(13)) - (m.get(9) * m.get(12)))) / det,
-(m.get(0) * ((m.get(9) * m.get(15)) - (m.get(11) * m.get(13))) -
m.get(1) * ((m.get(8) * m.get(15)) - (m.get(11) * m.get(12))) +
m.get(3) * ((m.get(8) * m.get(13)) - (m.get(9) * m.get(12)))) / det,
(m.get(0) * ((m.get(5) * m.get(15)) - (m.get(7) * m.get(13))) -
m.get(1) * ((m.get(4) * m.get(15)) - (m.get(7) * m.get(12))) +
m.get(3) * ((m.get(4) * m.get(13)) - (m.get(5) * m.get(12)))) / det,
-(m.get(0) * ((m.get(5) * m.get(11)) - (m.get(7) * m.get(9))) -
m.get(1) * ((m.get(4) * m.get(11)) - (m.get(7) * m.get(8))) +
m.get(3) * ((m.get(4) * m.get(9)) - (m.get(5) * m.get(8)))) / det,
-(m.get(4) * ((m.get(9) * m.get(14)) - (m.get(10) * m.get(13))) -
m.get(5) * ((m.get(8) * m.get(14)) - (m.get(10) * m.get(12))) +
m.get(6) * ((m.get(8) * m.get(13)) - (m.get(9) * m.get(12)))) / det,
(m.get(0) * ((m.get(9) * m.get(14)) - (m.get(10) * m.get(13))) -
m.get(1) * ((m.get(8) * m.get(14)) - (m.get(10) * m.get(12))) +
m.get(2) * ((m.get(8) * m.get(13)) - (m.get(9) * m.get(12)))) / det,
-(m.get(0) * ((m.get(5) * m.get(14)) - (m.get(6) * m.get(13))) -
m.get(1) * ((m.get(4) * m.get(14)) - (m.get(6) * m.get(12))) +
m.get(2) * ((m.get(4) * m.get(13)) - (m.get(5) * m.get(12)))) / det,
(m.get(0) * ((m.get(5) * m.get(10)) - (m.get(6) * m.get(9))) -
m.get(1) * ((m.get(4) * m.get(10)) - (m.get(6) * m.get(8))) +
m.get(2) * ((m.get(4) * m.get(9)) - (m.get(5) * m.get(8)))) / det);
}
}
#endif

View File

@ -0,0 +1,49 @@
/**
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_MATH_FWD_DECLARE_HPP
#define REXY_MATH_FWD_DECLARE_HPP
#include <cstdlib> //size_t
namespace math{
template<typename T, size_t R, size_t C>
class matrix;
template<typename T, size_t R>
class vector;
template<typename T>
class quaternion;
template<typename T>
using mat2 = matrix<T,2,2>;
template<typename T>
using mat3 = matrix<T,3,3>;
template<typename T>
using mat4 = matrix<T,4,4>;
template<typename T>
using vec2 = vector<T,2>;
template<typename T>
using vec3 = vector<T,3>;
template<typename T>
using vec4 = vector<T,4>;
}
#endif

View File

@ -1,19 +1,19 @@
/**
This file is a part of the rexy/r0nk/atlas project
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 General Public License as published by
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 General Public License for more details.
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 General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
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_MAT_HPP
@ -22,7 +22,8 @@
#include <cstdlib> //size_t
#include <utility> //integer_sequence
#include <type_traits> //decay_t, is_same, integral_constant
#include "detail/math.hpp"
#include "math_common.hpp"
#include "fwd_declare.hpp"
namespace math{
@ -228,11 +229,11 @@ namespace math{
template<typename T, typename U, size_t R1, size_t C1, size_t R2>
constexpr auto operator*(const matrix<T,R1,C1>& left, const matrix<U,C1,R2>& right);
template<typename T, typename U, size_t C, size_t R, std::enable_if_t<!is_matrix<U>::value,int> = 0>
template<typename T, typename U, size_t C, size_t R, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int> = 0>
constexpr auto operator*(const matrix<T,R,C>& left, U&& right);
template<typename T, typename U, size_t C, size_t R, std::enable_if_t<!is_matrix<U>::value,int> = 0>
template<typename T, typename U, size_t C, size_t R, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int> = 0>
constexpr auto operator*(U&& left, const matrix<T,R,C>& right);
template<typename T, typename U, size_t C, size_t R, std::enable_if_t<!is_matrix<U>::value,int> = 0>
template<typename T, typename U, size_t C, size_t R, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int> = 0>
constexpr auto operator/(const matrix<T,R,C>& left, U&& right);
template<typename T, typename U, size_t C, size_t R>
constexpr auto operator+(const matrix<T,R,C>& left, const matrix<U,R,C>& right);
@ -243,15 +244,23 @@ namespace math{
template<typename T, typename U, size_t R>
constexpr decltype(auto) operator*=(matrix<T,R,R>& left, const matrix<U,R,R>& right);
template<typename T, typename U, size_t C, size_t R, std::enable_if_t<!is_matrix<U>::value,int> = 0>
template<typename T, typename U, size_t C, size_t R, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int> = 0>
constexpr decltype(auto) operator*=(matrix<T,R,C>& left, U&& right);
template<typename T, typename U, size_t C, size_t R, std::enable_if_t<!is_matrix<U>::value,int> = 0>
template<typename T, typename U, size_t C, size_t R, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int> = 0>
constexpr decltype(auto) operator/=(matrix<T,R,C>& left, U&& right);
template<typename T, typename U, size_t C, size_t R>
constexpr decltype(auto) operator+=(matrix<T,R,C>& left, const matrix<U,R,C>& right);
template<typename T, typename U, size_t C, size_t R>
constexpr decltype(auto) operator-=(matrix<T,R,C>& left, const matrix<U,R,C>& right);
template<typename T>
using mat2 = matrix<T,2,2>;
template<typename T>
using mat3 = matrix<T,3,3>;
template<typename T>
using mat4 = matrix<T,4,4>;
}
#include "mat.tpp"

View File

@ -1,19 +1,19 @@
/**
This file is a part of the rexy/r0nk/atlas project
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 General Public License as published by
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 General Public License for more details.
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 General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
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_MAT_TPP
@ -23,6 +23,7 @@
#include <cmath> //sin, cos
#include <type_traits> //decay_t, declval
#include "detail/matrix.hpp"
#include "quat.hpp"
namespace math{
@ -202,8 +203,8 @@ namespace math{
}
template<typename T>
matrix<T,3,3> rotation2d(T x, T y, T z){
//TODO
return {};
quaternion<T> q(x, y, z);
return q.to_mat3();
}
template<typename T>
@ -242,8 +243,8 @@ namespace math{
}
template<typename T>
constexpr matrix<T,4,4> rotation3d(T angle_x, T angle_y, T angle_z){
//TODO
return {};
quaternion<T> q(angle_x, angle_y, angle_z);
return q.to_mat4();
}
template<typename T>
constexpr matrix<T,4,4> translation3d(T x, T y, T z){

27
include/math/math.hpp Normal file
View File

@ -0,0 +1,27 @@
/**
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_MATH_HPP
#define REXY_MATH_HPP
#include "math_common.hpp"
#include "vec.hpp"
#include "mat.hpp"
#include "quat.hpp"
#endif

View File

@ -0,0 +1,58 @@
/**
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_DETAIL_MATH_HPP
#define REXY_DETAIL_MATH_HPP
namespace math{
namespace detail{
struct zero_initialize_t{};
struct no_initialize_t{};
struct id_initialize_t{};
struct manual_initialize_t{};
}
static inline constexpr detail::zero_initialize_t zero_initialize;
static inline constexpr detail::no_initialize_t no_initialize;
static inline constexpr detail::id_initialize_t id_initialize;
static inline constexpr detail::manual_initialize_t manual_initialize;
template<typename T>
static constexpr T pi(){
return static_cast<T>(3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821);
}
template<typename T>
static constexpr T to_degrees(T t){
return (t * 180.0) / pi<T>();
}
template<typename T>
static constexpr T to_radians(T t){
return (t * pi<T>()) / 180.0;
}
constexpr long double operator"" _rad(long double f){
return f;
}
constexpr long double operator"" _deg(long double f){
return to_radians(f);
}
}
#endif

160
include/math/quat.hpp Normal file
View File

@ -0,0 +1,160 @@
/**
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<typename 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();
//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(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() = default;
//Assignment
constexpr quaternion& operator=(const quaternion&) = default;
constexpr quaternion& operator=(quaternion&&) = default;
//Direct array access
constexpr operator pointer();
constexpr operator const_pointer()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();
constexpr const_reference w()const;
constexpr reference x();
constexpr const_reference x()const;
constexpr reference y();
constexpr const_reference y()const;
constexpr reference z();
constexpr const_reference z()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()const;
void set_angle(value_type a);
value_type get_angle()const;
value_type norm()const;
quaternion conjugate()const;
quaternion inverse()const;
value_type magnitude()const;
quaternion normalize()const;
vec3<value_type> get_right()const;
vec3<value_type> get_up()const;
vec3<value_type> get_forward()const;
//Explicit Conversion1
vec3<value_type> to_vec3()const;
vec4<value_type> to_vec4()const;
mat3<value_type> to_mat3()const;
mat4<value_type> to_mat4()const;
vec3<value_type> to_euler_angles()const;
std::pair<value_type,vec3<value_type>> to_axis_angle()const;
};
namespace detail{
template<typename 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<typename... Qs>
struct is_quaternion {
static constexpr bool value = (detail::is_quat_helper<Qs>::value && ...);
};
template<typename T, typename U>
bool operator==(const quaternion<T>& left, const quaternion<U>& right);
template<typename T, typename U>
bool operator!=(const quaternion<T>& left, const quaternion<U>& right);
template<typename T>
auto operator-(const quaternion<T>& left);
template<typename T, typename U>
auto operator-(const quaternion<T>& left, const quaternion<U>& right);
template<typename T, typename U>
auto operator+(const quaternion<T>& left, const quaternion<U>& right);
template<typename T, typename U>
auto operator*(const quaternion<T>& left, const quaternion<U>& right);
template<typename T, typename U>
auto operator*(const quaternion<T>& left, const vec3<U>& right);
template<typename T, typename U, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int> = 0>
auto operator*(const quaternion<T>& left, U&& right);
template<typename T, typename U, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int> = 0>
auto operator/(const quaternion<T>& left, U&& right);
template<typename T, typename U>
decltype(auto) operator+=(quaternion<T>& left, const quaternion<U>& right);
template<typename T, typename U>
decltype(auto) operator-=(quaternion<T>& left, const quaternion<U>& right);
template<typename T, typename U>
decltype(auto) operator*=(quaternion<T>& left, const quaternion<U>& right);
template<typename T, typename U, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int> = 0>
decltype(auto) operator*=(quaternion<T>& left, U&& right);
template<typename T, typename U, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int> = 0>
decltype(auto) operator/=(quaternion<T>& left, U&& right);
}
#include "quat.tpp"
#endif

403
include/math/quat.tpp Normal file
View File

@ -0,0 +1,403 @@
/**
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_TPP
#define REXY_QUAT_TPP
#include <cmath> //sin, cos, tan, sqrt, etc
#include "mat.hpp"
#include "vec.hpp"
namespace math{
template<typename T>
constexpr quaternion<T>::quaternion():
quaternion(id_initialize){}
template<typename T>
constexpr quaternion<T>::quaternion(detail::zero_initialize_t):
m_data{0, 0, 0, 0}{}
template<typename T>
constexpr quaternion<T>::quaternion(detail::id_initialize_t):
m_data{1, 0, 0, 0}{}
template<typename T>
constexpr quaternion<T>::quaternion(detail::no_initialize_t){}
template<typename T>
constexpr quaternion<T>::quaternion(detail::manual_initialize_t,
value_type w, value_type x,
value_type y, value_type z):
m_data{w, x, y, z}{}
template<typename T>
quaternion<T>::quaternion(value_type bank, value_type heading, value_type attitude){
bank /= value_type{2};
heading /= value_type{2};
attitude /= value_type{2};
value_type cos_heading = std::cos(heading);
value_type sin_heading = std::sin(heading);
value_type cos_attitude = std::cos(attitude);
value_type sin_attitude = std::sin(attitude);
value_type cos_bank = std::cos(bank);
value_type sin_bank = std::sin(bank);
m_data[0] = (cos_heading * cos_attitude * cos_bank) - (sin_heading * sin_attitude * sin_bank);
m_data[1] = (sin_heading * sin_attitude * cos_bank) + (cos_heading * cos_attitude * sin_bank);
m_data[2] = (sin_heading * cos_attitude * cos_bank) + (cos_heading * sin_attitude * sin_bank);
m_data[3] = (cos_heading * sin_attitude * cos_bank) - (sin_heading * cos_attitude * sin_bank);
}
template<typename T>
quaternion<T>::quaternion(const vec3<T>& angles):
quaternion(angles.x(), angles.y(), angles.z()){}
template<typename T>
quaternion<T>::quaternion(value_type angle, const vec3<value_type>& axis):
quaternion(angle, axis.get_x(), axis.get_y(), axis.get_z()){}
template<typename T>
quaternion<T>::quaternion(value_type angle, value_type x, value_type y, value_type z){
angle /= value_type{2.0};
value_type sin_angle = std::sin(angle);
m_data[0] = std::cos(angle);
m_data[1] = sin_angle * x;
m_data[2] = sin_angle * y;
m_data[3] = sin_angle * z;
}
template<typename T>
constexpr quaternion<T>::operator pointer(void){
return m_data;
}
template<typename T>
constexpr quaternion<T>::operator const_pointer(void)const{
return m_data;
}
template<typename T>
constexpr auto quaternion<T>::operator[](size_type i) -> reference{
return m_data[i];
}
template<typename T>
constexpr auto quaternion<T>::operator[](size_type i)const -> const_reference{
return m_data[i];
}
template<typename T>
constexpr auto quaternion<T>::get(size_type i) -> reference{
return m_data[i];
}
template<typename T>
constexpr auto quaternion<T>::get(size_type i)const -> const_reference{
return m_data[i];
}
template<typename T>
constexpr auto quaternion<T>::w() -> reference{
return m_data[0];
}
template<typename T>
constexpr auto quaternion<T>::w()const -> const_reference{
return m_data[0];
}
template<typename T>
constexpr auto quaternion<T>::x() -> reference{
return m_data[1];
}
template<typename T>
constexpr auto quaternion<T>::x()const -> const_reference{
return m_data[1];
}
template<typename T>
constexpr auto quaternion<T>::y() -> reference{
return m_data[2];
}
template<typename T>
constexpr auto quaternion<T>::y()const -> const_reference{
return m_data[2];
}
template<typename T>
constexpr auto quaternion<T>::z() -> reference{
return m_data[3];
}
template<typename T>
constexpr auto quaternion<T>::z()const -> const_reference{
return m_data[3];
}
template<typename T>
void quaternion<T>::set_axis(value_type x, value_type y, value_type z){
value_type sin_angle = std::sin(std::acos(m_data[0]));
m_data[1] = sin_angle * x;
m_data[2] = sin_angle * y;
m_data[3] = sin_angle * z;
}
template<typename T>
void quaternion<T>::set_axis(const vec3<value_type>& v){
set_axis(v.x(), v.y(), v.z());
}
template<typename T>
auto quaternion<T>::get_axis()const -> vec3<value_type>{
quaternion tmp(*this);
if(m_data[0] > value_type{1.0})
tmp.set_normalized();
value_type s = std::sqrt(1 - tmp.m_data[0] * tmp.m_data[0]);
if(s <= value_type{0.001})
return vec3<T>(1, 0, 0);
return vec3<T>(tmp.data[1] / s, tmp.data[2] / s, tmp.data[3] / s);
}
template<typename T>
void quaternion<T>::set_angle(value_type t){
t /= value_type{2.0};
value_type old_sin_angle = std::sin(std::acos(m_data[0]));
value_type sin_angle = std::sin(t);
m_data[0] = std::cos(t);
m_data[1] = (m_data[1] / old_sin_angle) * sin_angle;
m_data[2] = (m_data[2] / old_sin_angle) * sin_angle;
m_data[3] = (m_data[3] / old_sin_angle) * sin_angle;
}
template<typename T>
auto quaternion<T>::get_angle(void)const -> value_type{
return 2.0 * std::acos(m_data[0]);
}
template<typename T>
auto quaternion<T>::norm(void)const -> value_type{
return m_data[0] * m_data[0] + m_data[1] * m_data[1] + m_data[2] * m_data[2] + m_data[3] * m_data[3];
}
template<typename T>
quaternion<T> quaternion<T>::conjugate(void)const{
return quaternion(manual_initialize, m_data[0], -m_data[1], -m_data[2], -m_data[3]);
}
template<typename T>
quaternion<T> quaternion<T>::inverse(void)const{
return conjugate() / norm();
}
template<typename T>
auto quaternion<T>::magnitude(void)const -> value_type{
return std::sqrt(norm());
}
template<typename T>
quaternion<T> quaternion<T>::normalize(void)const{
value_type mag = magnitude();
return quaternion(manual_initialize, m_data[0] / mag, m_data[1] / mag, m_data[2] / mag, m_data[3] / mag);
}
template<typename T>
auto quaternion<T>::get_right(void)const -> vec3<value_type>{
return vec3<value_type>(1 - 2 * ((m_data[2] * m_data[2]) + (m_data[3] * m_data[3])),
2 * ((m_data[1] * m_data[2]) - (m_data[3] * m_data[0])),
2 * ((m_data[1] * m_data[3]) + (m_data[2] * m_data[0])));
}
template<typename T>
auto quaternion<T>::get_up(void)const -> vec3<value_type>{
return vec3<value_type>( 2 * ((m_data[1] * m_data[2]) + (m_data[3] * m_data[0])),
1 - 2 * ((m_data[1] * m_data[1]) + (m_data[3] * m_data[3])),
2 * ((m_data[2] * m_data[3]) - (m_data[1] * m_data[0])));
}
template<typename T>
auto quaternion<T>::get_forward(void)const -> vec3<value_type>{
return vec3<value_type>( 2 * ((m_data[1] * m_data[3]) - (m_data[2] * m_data[0])),
2 * ((m_data[2] * m_data[3]) + (m_data[1] * m_data[0])),
1 - 2 * ((m_data[1] * m_data[1]) + (m_data[2] * m_data[2])));
}
template<typename T>
auto quaternion<T>::to_vec3(void)const -> vec3<value_type>{
return vec3<value_type>(m_data[1], m_data[2], m_data[3]);
}
template<typename T>
auto quaternion<T>::to_vec4(void)const -> vec4<value_type>{
return vec4<value_type>(m_data[1], m_data[2], m_data[3]);
}
template<typename T>
auto quaternion<T>::to_mat3(void)const -> mat3<value_type>{
mat3<value_type> m;
value_type xx = m_data[1] * m_data[1];
value_type yy = m_data[2] * m_data[2];
value_type zz = m_data[3] * m_data[3];
value_type xy = m_data[1] * m_data[2];
value_type xz = m_data[1] * m_data[3];
value_type xw = m_data[1] * m_data[0];
value_type yz = m_data[2] * m_data[3];
value_type yw = m_data[2] * m_data[0];
value_type zw = m_data[3] * m_data[0];
m[0] = 1 - 2 * (yy + zz);
m[1] = 2 * (xy + zw);
m[2] = 2 * (xz - yw);
m[3] = 2 * (xy - zw);
m[4] = 1 - 2 * (xx + zz);
m[5] = 2 * (yz + xw);
m[6] = 2 * (xz + yw);
m[7] = 2 * (yz - xw);
m[8] = 1 - 2 * (xx + yy);
return m;
}
template<typename T>
auto quaternion<T>::to_mat4(void)const -> mat4<value_type>{
mat4<value_type> m;
value_type xx = m_data[1] * m_data[1];
value_type yy = m_data[2] * m_data[2];
value_type zz = m_data[3] * m_data[3];
value_type xy = m_data[1] * m_data[2];
value_type xz = m_data[1] * m_data[3];
value_type xw = m_data[1] * m_data[0];
value_type yz = m_data[2] * m_data[3];
value_type yw = m_data[2] * m_data[0];
value_type zw = m_data[3] * m_data[0];
m[0] = 1 - 2 * (yy + zz);
m[1] = 2 * (xy + zw);
m[2] = 2 * (xz - yw);
m[3] = 0;
m[4] = 2 * (xy - zw);
m[5] = 1 - 2 * (xx + zz);
m[6] = 2 * (yz + xw);
m[7] = 0;
m[8] = 2 * (xz + yw);
m[9] = 2 * (yz - xw);
m[10] = 1 - 2 * (xx + yy);
m[11] = 0;
m[12] = 0;
m[13] = 0;
m[14] = 0;
m[15] = 1;
return m;
}
template<typename T>
auto quaternion<T>::to_euler_angles(void)const -> vec3<value_type>{
value_type ww = m_data[0] * m_data[0];
value_type xx = m_data[1] * m_data[1];
value_type yy = m_data[2] * m_data[2];
value_type zz = m_data[3] * m_data[3];
value_type correction = ww + xx + yy + zz;
value_type test = m_data[1] * m_data[2] + m_data[3] * m_data[0];
if(test > 0.499 * correction){
return vec3<value_type>(0, 2 * std::atan2(m_data[1], m_data[0]), pi<value_type>() / 2.0);
}else if(test < -0.499 * correction){
return vec3<value_type>(0, -2 * std::atan2(m_data[1], m_data[0]), -pi<value_type>() / 2.0);
}
return vec3<value_type>(std::atan2((2 * m_data[1] * m_data[0]) - (2 * m_data[2] * m_data[3]), ww - xx + yy - zz),
std::atan2((2 * m_data[2] * m_data[0]) - (2 * m_data[1] * m_data[3]), xx - yy - zz + ww),
std::asin(2 * test / correction));
}
template<typename T>
auto quaternion<T>::to_axis_angle()const -> std::pair<value_type,vec3<value_type>>{
quaternion q(*this);
if(m_data[0] > 1.0)
q = q.normalize();
value_type s = std::sqrt(1 - q.m_data[0] * q.m_data[0]);
if(s <= value_type{0.001}){
return {2 * std::acos(q.m_data[0]), {1, 0, 0}};
}
return {2 * std::acos(q.m_data[0]), {q.m_data[1] / s, q.m_data[2] / s, q.m_data[3] / s}};
}
template<typename T, typename U>
bool operator==(const quaternion<T>& left, const quaternion<U>& right){
return left.w() == right.w() &&
left.x() == right.x() &&
left.y() == right.y() &&
left.z() == right.z();
}
template<typename T, typename U>
bool operator!=(const quaternion<T>& left, const quaternion<U>& right){
return !(left == right);
}
template<typename T>
auto operator-(const quaternion<T>& left){
using res_t = T;
return quaternion<res_t>(manual_initialize, -left.w(), -left.x(), -left.y(), -left.z());
}
template<typename T, typename U>
auto operator-(const quaternion<T>& left, const quaternion<U>& right){
using res_t = decltype(std::declval<T>() - std::declval<U>());
return quaternion<res_t>(manual_initialize, left.w() - right.w(), left.x() - right.x(),
left.y() - right.y(), left.z() - right.z());
}
template<typename T, typename U>
auto operator+(const quaternion<T>& left, const quaternion<U>& right){
using res_t = decltype(std::declval<T>() + std::declval<U>());
return quaternion<res_t>(manual_initialize, left.w() + right.w(), left.x() + right.x(),
left.y() + right.y(), left.z() + right.z());
}
template<typename T, typename U>
auto operator*(const quaternion<T>& left, const quaternion<U>& right){
using res_t = decltype(std::declval<T>() * std::declval<U>());
return quaternion<res_t>(manual_initialize,
(right.w() * left.w()) - (right.x() * left.x()) -
(right.y() * left.y()) - (right.z() * left.z()),
(right.w() * left.x()) + (right.x() * left.w()) +
(right.y() * left.z()) - (right.z() * left.y()),
(right.w() * left.y()) - (right.x() * left.z()) +
(right.y() * left.w()) + (right.z() * left.x()),
(right.w() * left.z()) + (right.x() * left.y()) -
(right.y() * left.x()) + (right.z() * left.w()));
}
template<typename T, typename U>
auto operator*(const quaternion<T>& left, const vec3<U>& right){
return left.to_mat3() * right;
}
template<typename T, typename U, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int>>
auto operator*(const quaternion<T>& left, U&& right){
using res_t = decltype(std::declval<T>() * std::declval<U>());
return quaternion<res_t>(manual_initialize, left.w() * right, left.x() * right, left.y() * right, left.z() * right);
}
template<typename T, typename U, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int>>
auto operator/(const quaternion<T>& left, U&& right){
using res_t = decltype(std::declval<T>() / std::declval<U>());
return quaternion<res_t>(manual_initialize, left.w() / right, left.x() / right, left.y() / right, left.z() / right);
}
template<typename T, typename U>
decltype(auto) operator+=(quaternion<T>& left, const quaternion<U>& right){
left.w() += right.w();
left.x() += right.x();
left.y() += right.y();
left.z() += right.z();
return left;
}
template<typename T, typename U>
decltype(auto) operator-=(quaternion<T>& left, const quaternion<U>& right){
left.w() -= right.w();
left.x() -= right.x();
left.y() -= right.y();
left.z() -= right.z();
return left;
}
template<typename T, typename U>
decltype(auto) operator*=(quaternion<T>& left, const quaternion<U>& right){
left = left * right;
return left;
}
template<typename T, typename U, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int>>
decltype(auto) operator*=(quaternion<T>& left, U&& right){
left.w() *= right;
left.x() *= right;
left.y() *= right;
left.z() *= right;
return left;
}
template<typename T, typename U, std::enable_if_t<std::is_arithmetic_v<std::decay_t<U>>,int>>
decltype(auto) operator/=(quaternion<T>& left, U&& right){
left.w() /= right;
left.x() /= right;
left.y() /= right;
left.z() /= right;
return left;
}
}
#endif

View File

@ -1,3 +1,21 @@
/**
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_VEC_HPP
#define REXY_VEC_HPP
@ -5,7 +23,7 @@
namespace math{
template<class T, size_t R>
template<typename T, size_t R>
class vector : public matrix_base<T,R,1>
{
private:
@ -33,6 +51,21 @@ namespace math{
constexpr reference operator[](size_type i);
constexpr const_reference operator[](size_type i)const;
constexpr reference x();
constexpr const_reference x()const;
template<typename U = T>
constexpr reference y();
template<typename U = T>
constexpr const_reference y()const;
template<typename U = T>
constexpr reference z();
template<typename U = T>
constexpr const_reference z()const;
template<typename U = T>
constexpr reference w();
template<typename U = T>
constexpr const_reference w()const;
};
@ -61,6 +94,14 @@ namespace math{
constexpr decltype(auto) operator+=(vector<T,R>& left, const vector<U,R>& right);
template<typename T, typename U, size_t R>
constexpr decltype(auto) operator-=(vector<T,R>& left, const vector<U,R>& right);
template<typename T>
using vec2 = vector<T,2>;
template<typename T>
using vec3 = vector<T,3>;
template<typename T>
using vec4 = vector<T,4>;
}
#include "vec.tpp"

View File

@ -1,3 +1,21 @@
/**
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_VEC_TPP
#define REXY_VEC_TPP
@ -18,6 +36,51 @@ namespace math{
return this->m_data[i];
}
template<typename T, size_t R>
constexpr auto vector<T,R>::x() -> reference{
return this->m_data[0];
}
template<typename T, size_t R>
constexpr auto vector<T,R>::x()const -> const_reference{
return this->m_data[0];
}
template<typename T, size_t R>
template<typename U>
constexpr auto vector<T,R>::y() -> reference{
static_assert(R > 1, "Vector does not contain a 2nd element");
return this->m_data[1];
}
template<typename T, size_t R>
template<typename U>
constexpr auto vector<T,R>::y()const -> const_reference{
static_assert(R > 1, "Vector does not contain a 2nd element");
return this->m_data[1];
}
template<typename T, size_t R>
template<typename U>
constexpr auto vector<T,R>::z() -> reference{
static_assert(R > 2, "Vector does not contain a 3rd element");
return this->m_data[2];
}
template<typename T, size_t R>
template<typename U>
constexpr auto vector<T,R>::z()const -> const_reference{
static_assert(R > 2, "Vector does not contain a 3rd element");
return this->m_data[2];
}
template<typename T, size_t R>
template<typename U>
constexpr auto vector<T,R>::w() -> reference{
static_assert(R > 3, "Vector does not contain a 4th element");
return this->m_data[3];
}
template<typename T, size_t R>
template<typename U>
constexpr auto vector<T,R>::w()const -> const_reference{
static_assert(R > 3, "Vector does not contain a 4th element");
return this->m_data[3];
}
template<typename T, typename U, size_t C, size_t R>
constexpr auto operator*(const matrix<U,R,C>& left, const vector<T,C>& right){
using res_t = decltype(std::declval<T>() * std::declval<U>());

View File

@ -4,7 +4,7 @@
#include "render.hpp"
#include "game_state.hpp"
#include "mat.hpp"
#include "math/math.hpp"
// 0 | 1 | 2
// ---------