This commit is contained in:
jeanlemotan
2024-07-02 18:27:05 +02:00
commit bc037aa2bd
83 changed files with 13236 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
out
+49
View File
@@ -0,0 +1,49 @@
cmake_minimum_required(VERSION 3.16.5)
project(VMath)
include(${PROJECT_SOURCE_DIR}/../build-utils/cmake/compiler_settings.cmake)
if(NOT TARGET TL)
add_subdirectory("${PROJECT_SOURCE_DIR}/../TL" "./TL")
endif()
file(GLOB_RECURSE SRC "src/*.cpp")
file(GLOB_RECURSE HEADERS "include/*.h" "include/*.hpp" "include/*.inl")
foreach(_source IN ITEMS ${HEADERS})
get_filename_component(_source_path "${_source}" PATH)
file(RELATIVE_PATH _source_path_rel "${PROJECT_SOURCE_DIR}" "${_source_path}")
string(REPLACE "/" "\\" _group_path "${_source_path_rel}")
source_group("${_group_path}" FILES "${_source}")
endforeach()
foreach(_source IN ITEMS ${SRC})
get_filename_component(_source_path "${_source}" PATH)
file(RELATIVE_PATH _source_path_rel "${PROJECT_SOURCE_DIR}" "${_source_path}")
string(REPLACE "/" "\\" _group_path "${_source_path_rel}")
source_group("${_group_path}" FILES "${_source}")
endforeach()
add_library(VMath STATIC ${SRC} ${HEADERS})
target_include_directories(VMath PUBLIC "include")
target_link_libraries(VMath TL)
if (0)
#//////////////////////////////////
set(Boost_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../boost")
set(Boost_LIBRARY_DIR "${PROJECT_SOURCE_DIR}/../boost/stage/lib")
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.69 COMPONENTS unit_test_framework)
file(GLOB_RECURSE TEST_SRC "test/*.cpp" "test/*.h")
add_executable(VMath_Test ${TEST_SRC})
target_link_libraries(VMath_Test VMath)
target_link_libraries(VMath_Test ${Boost_LIBRARIES})
target_include_directories(VMath_Test PUBLIC ${Boost_INCLUDE_DIRS})
endif()
+269
View File
@@ -0,0 +1,269 @@
#pragma once
#include <tl/assert.h>
#include <tl/string.h>
#include <tl/numeric_limits.h>
#include <cmath>
#if defined(_MSC_VER) && _MSC_VER >= 1900
# define MATH_RESTRICT __restrict
#elif (defined(__clang__) || defined(__GNUC__))
# define MATH_RESTRICT __restrict__
#else
# define MATH_RESTRICT
#endif
namespace math
{
static struct ZUninitialized {} uninitialized;
//standard precision
struct standard {};
//fast but less precise
struct fast {};
//standard precision but safe assumptions
struct safe {};
}
#include "VMath/angle.h"
#include "VMath/vec2.h"
#include "VMath/vec3.h"
#include "VMath/vec4.h"
#include "VMath/rect.h"
#include "VMath/mat2.h"
#include "VMath/mat3.h"
#include "VMath/mat4.h"
#include "VMath/trans2.h"
#include "VMath/trans3.h"
#include "VMath/rigid2.h"
#include "VMath/rigid3.h"
#include "VMath/quat.h"
#include "VMath/plane.h"
#include "VMath/line2.h"
#include "VMath/line3.h"
#include "VMath/ray2.h"
#include "VMath/ray3.h"
#include "VMath/segment2.h"
#include "VMath/segment3.h"
#include "VMath/circle2.h"
#include "VMath/triangle3.h"
#include "VMath/aabb3.h"
#include "VMath/aabb2.h"
#include "VMath/range.h"
#include "VMath/clamped_value.h"
namespace math
{
typedef angle<float> anglef;
typedef angle<double> angled;
typedef vec2<int8_t> byte2;
typedef vec2<uint8_t> ubyte2;
typedef vec2<int16_t> short2;
typedef vec2<uint16_t> ushort2;
typedef vec2<int32_t> int2;
typedef vec2<uint32_t> uint2;
typedef vec2<float> float2;
typedef vec2<double> double2;
typedef vec2<int8_t> vec2b;
typedef vec2<uint8_t> vec2ub;
typedef vec2<int16_t> vec2s;
typedef vec2<uint16_t> vec2us;
typedef vec2<int32_t> vec2i;
typedef vec2<uint32_t> vec2u;
typedef vec2<float> vec2f;
typedef vec2<double> vec2d;
typedef vec3<int8_t> byte3;
typedef vec3<uint8_t> ubyte3;
typedef vec3<int16_t> short3;
typedef vec3<uint16_t> ushort3;
typedef vec3<int32_t> int3;
typedef vec3<uint32_t> uint3;
typedef vec3<float> float3;
typedef vec3<double> double3;
typedef vec3<int8_t> vec3b;
typedef vec3<uint8_t> vec3ub;
typedef vec3<int16_t> vec3s;
typedef vec3<uint16_t> vec3us;
typedef vec3<int32_t> vec3i;
typedef vec3<uint32_t> vec3u;
typedef vec3<float> vec3f;
typedef vec3<double> vec3d;
typedef vec4<int8_t> byte4;
typedef vec4<uint8_t> ubyte4;
typedef vec4<int16_t> short4;
typedef vec4<uint16_t> ushort4;
typedef vec4<int32_t> int4;
typedef vec4<uint32_t> uint4;
typedef vec4<float> float4;
typedef vec4<double> double4;
typedef vec4<int8_t> vec4b;
typedef vec4<uint8_t> vec4ub;
typedef vec4<int16_t> vec4s;
typedef vec4<uint16_t> vec4us;
typedef vec4<int32_t> vec4i;
typedef vec4<uint32_t> vec4u;
typedef vec4<float> vec4f;
typedef vec4<double> vec4d;
typedef quat<float> quatf;
typedef quat<double> quatd;
typedef mat2<float> mat2f;
typedef mat2<double> mat2d;
typedef mat3<float> mat3f;
typedef mat3<double> mat3d;
typedef mat4<float> mat4f;
typedef mat4<double> mat4d;
typedef trans2<float> trans2f;
typedef trans2<double> trans2d;
typedef trans3<float> trans3f;
typedef trans3<double> trans3d;
typedef rigid2<float> rigid2f;
typedef rigid2<double> rigid2d;
typedef rigid3<float> rigid3f;
typedef rigid3<double> rigid3d;
typedef line2<float> line2f;
typedef line2<double> line2d;
typedef line3<float> line3f;
typedef line3<double> line3d;
typedef ray2<float> ray2f;
typedef ray2<double> ray2d;
typedef ray3<float> ray3f;
typedef ray3<double> ray3d;
typedef segment2<float> segment2f;
typedef segment2<double> segment2d;
typedef segment3<float> segment3f;
typedef segment3<double> segment3d;
typedef rect<int32_t> recti;
typedef rect<uint32_t> rectu;
typedef rect<float> rectf;
typedef rect<double> rectd;
typedef aabb2<float> aabb2f;
typedef aabb2<double> aabb2d;
typedef aabb3<float> aabb3f;
typedef aabb3<double> aabb3d;
typedef triangle3<float> triangle3f;
typedef triangle3<double> triangle3d;
typedef circle2<float> circle2f;
typedef circle2<double> circle2d;
typedef plane<float> planef;
typedef plane<double> planed;
typedef range<float> rangef;
typedef range<vec2f> range2f;
typedef range<vec3f> range3f;
typedef range<vec4f> range4f;
typedef range<double> ranged;
typedef range<vec2d> range2d;
typedef range<vec3d> range3d;
typedef range<vec4d> range4d;
typedef range<int32_t> rangei;
typedef range<vec2i> range2i;
typedef range<vec3i> range3i;
typedef range<vec4i> range4i;
namespace detail
{
template<typename T>
struct UValue_Traits
{
static constexpr T max = tl::numeric_limits<T>::max();
static constexpr T min = T(0);
};
template<typename T>
struct Mu_Traits
{
static constexpr T min = T(0);
static constexpr T max = T(1);
};
template<typename T>
struct Smu_Traits
{
static constexpr T min = T(-1);
static constexpr T max = T(1);
};
}
typedef clamped_value<float, detail::UValue_Traits<float>> ufloat;
typedef clamped_value<double, detail::UValue_Traits<double>> udouble;
typedef clamped_value<float, detail::Mu_Traits<float>> muf;
typedef clamped_value<double, detail::Mu_Traits<double>> mud;
typedef clamped_value<float, detail::Smu_Traits<float>> smuf;
typedef clamped_value<double, detail::Smu_Traits<double>> smud;
}//namespace math
#include "VMath/func_test.h"
#include "VMath/func_common.h"
#include "VMath/func_range.h"
#include "VMath/func_trig.h"
#include "VMath/func_interp.h"
#include "VMath/func_projection.h"
#include "VMath/func_transform.h"
#include "VMath/func_binary.h"
#include "VMath/func_string.h"
#include "VMath/func_cast.h"
#include "VMath/func_interpolation.h"
#include "VMath/func_intersect.h"
#include "VMath/angle.inl"
#include "VMath/circle2.inl"
#include "VMath/vec2.inl"
#include "VMath/vec3.inl"
#include "VMath/vec4.inl"
#include "VMath/rect.inl"
#include "VMath/mat2.inl"
#include "VMath/mat3.inl"
#include "VMath/mat4.inl"
#include "VMath/trans2.inl"
#include "VMath/trans3.inl"
#include "VMath/rigid2.inl"
#include "VMath/rigid3.inl"
#include "VMath/quat.inl"
#include "VMath/plane.inl"
#include "VMath/line2.inl"
#include "VMath/line3.inl"
#include "VMath/ray2.inl"
#include "VMath/ray3.inl"
#include "VMath/segment2.inl"
#include "VMath/segment3.inl"
#include "VMath/triangle3.inl"
#include "VMath/aabb3.inl"
#include "VMath/aabb2.inl"
#include "VMath/range.inl"
#include "VMath/clamped_value.inl"
#include "VMath/func_cast.inl"
#include "VMath/func_range.inl"
#include "VMath/func_test.inl"
#include "VMath/func_common.inl"
#include "VMath/func_trig.inl"
#include "VMath/func_interp.inl"
#include "VMath/func_projection.inl"
#include "VMath/func_transform.inl"
#include "VMath/func_binary.inl"
#include "VMath/func_interpolation.inl"
#include "VMath/func_intersect.inl"
#undef MATH_RESTRICT
+49
View File
@@ -0,0 +1,49 @@
#pragma once
#include <compare>
#include <tl/numeric_limits.h>
#include <tl/span.h>
namespace math
{
template<typename T>
struct aabb2
{
typedef T value_t;
typedef aabb2<T> this_t;
constexpr aabb2() noexcept = default;
constexpr aabb2(const vec2<T>& min, const vec2<T>& max) noexcept;
constexpr explicit aabb2(const vec2<T>& init) noexcept;
constexpr vec2<T> get_center() const noexcept;
constexpr vec2<T> get_extent() const noexcept;
constexpr vec2<T> get_half_extent() const noexcept;
constexpr bool is_valid() const noexcept;
constexpr bool is_empty() const noexcept;
constexpr T get_area() const noexcept;
///@param corners: an array of 4 corners.
/* Edges are stored in this way (assuming Y up):
1---------2 +Y
| | ^
| | |
| | +-----> +X
0---------3
*/
constexpr void get_corners(tl::span<vec2<T>> corners) const noexcept;
constexpr void add(const vec2<T>& p) noexcept;
constexpr void add(const this_t& b) noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
vec2<T> min = vec2<T>(tl::numeric_limits<T>::max());
vec2<T> max = vec2<T>(tl::numeric_limits<T>::lowest());
};
}
+119
View File
@@ -0,0 +1,119 @@
#include <tl/assert.h>
namespace math
{
template<typename T>
inline constexpr aabb2<T>::aabb2(const vec2<T>& minp, const vec2<T>& maxp) noexcept
: min(minp)
, max(maxp)
{
TL_PLAIN_ASSERT(is_lequal(minp, maxp));
}
template<typename T>
inline constexpr aabb2<T>::aabb2(const vec2<T>& p) noexcept
: min(p)
, max(p)
{
}
template<typename T>
inline constexpr vec2<T> aabb2<T>::get_center() const noexcept
{
if constexpr (std::is_floating_point_v<T>)
return (min + max) * T(0.5);
else
return (min + max) / T(2);
}
template<typename T>
inline constexpr vec2<T> aabb2<T>::get_extent() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
return max - min;
}
template<typename T>
inline constexpr vec2<T> aabb2<T>::get_half_extent() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
if constexpr (std::is_floating_point_v<T>)
return (max - min) * T(0.5);
else
return (max - min) / T(2);
}
template<typename T>
inline constexpr bool aabb2<T>::is_valid() const noexcept
{
return max.x >= min.x;
}
template<typename T>
inline constexpr bool aabb2<T>::is_empty() const noexcept
{
return !is_valid() || min == max;
}
template<typename T>
inline constexpr T aabb2<T>::get_area() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
vec2<T> e = get_extent();
return e.x * e.y;
}
template<typename T>
inline constexpr void aabb2<T>::get_corners(tl::span<vec2<T>> corners) const noexcept
{
TL_PLAIN_ASSERT(is_valid());
/*
Edges are stored in this way (assuming Y up):
Hey, am I an ascii artist, or what? :) niko.
1---------2 +Y
| | ^
| | |
| | +-----> +X
0---------3
*/
const vec2<T> middle = get_center();
const vec2<T> diag = get_half_extent();
corners[0] = vec2<T>(middle.x - diag.x, middle.y - diag.y);
corners[1] = vec2<T>(middle.x - diag.x, middle.y + diag.y);
corners[2] = vec2<T>(middle.x + diag.x, middle.y + diag.y);
corners[3] = vec2<T>(middle.x + diag.x, middle.y - diag.y);
}
template<typename T>
inline constexpr void aabb2<T>::add(const vec2<T>& p) noexcept
{
this->min = math::min(this->min, p);
this->max = math::max(this->max, p);
}
template<typename T>
inline constexpr void aabb2<T>::add(const this_t& b) noexcept
{
add(b.min);
add(b.max);
}
}//namespace math
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::aabb2<T>>
{
std::size_t operator()(const math::aabb2<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.min);
tl::hash_and_combine(seed, p.max);
return seed;
}
};
+53
View File
@@ -0,0 +1,53 @@
#pragma once
#include <compare>
#include <tl/numeric_limits.h>
#include <tl/span.h>
namespace math
{
template<typename T>
struct aabb3
{
using value_t = T;
using this_t = aabb3<T>;
constexpr aabb3() = default;
constexpr aabb3(const vec3<T>& min, const vec3<T>& max) noexcept;
constexpr explicit aabb3(const vec3<T>& init) noexcept;
constexpr vec3<T> get_center() const noexcept;
constexpr vec3<T> get_extent() const noexcept;
constexpr vec3<T> get_half_extent() const noexcept;
constexpr bool is_valid() const noexcept;
constexpr bool is_empty() const noexcept;
constexpr T get_volume() const noexcept;
constexpr T get_area() const noexcept;
/*! Returns box corners into corners[]
/3--------/7
/ | / | +Y
/ | / | ^
1---------5 | |
| 2- - -| -6 +-------> +X
| / | / /
|/ | / /
0---------4/ +Z
*/
constexpr void get_corners(tl::span<vec3<T>> corners) const noexcept;
constexpr void add(const vec3<T>& p) noexcept;
constexpr void add(const this_t& b) noexcept;
constexpr void add_checked(const this_t& b) noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
vec3<T> min = vec3<T>(tl::numeric_limits<T>::max());
vec3<T> max = vec3<T>(tl::numeric_limits<T>::lowest());
};
}
+141
View File
@@ -0,0 +1,141 @@
namespace math
{
template<typename T>
inline constexpr aabb3<T>::aabb3(const vec3<T>& minp, const vec3<T>& maxp) noexcept
: min(minp)
, max(maxp)
{
TL_PLAIN_ASSERT(is_lequal(minp, maxp));
}
template<typename T>
inline constexpr aabb3<T>::aabb3(const vec3<T>& init) noexcept
: min(init)
, max(init)
{
}
template<typename T>
inline constexpr vec3<T> aabb3<T>::get_center() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
if constexpr (std::is_floating_point_v<T>)
return (min + max) * T(0.5);
else
return (min + max) / T(2);
}
template<typename T>
inline constexpr vec3<T> aabb3<T>::get_extent() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
return max - min;
}
template<typename T>
inline constexpr vec3<T> aabb3<T>::get_half_extent() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
if constexpr (std::is_floating_point_v<T>)
return (max - min) * T(0.5);
else
return (max - min) / T(2);
}
template<typename T>
inline constexpr bool aabb3<T>::is_valid() const noexcept
{
return is_lequal(min, max);
}
template<typename T>
inline constexpr bool aabb3<T>::is_empty() const noexcept
{
return !is_valid() || min == max;
}
template<typename T>
inline constexpr T aabb3<T>::get_volume() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
vec3<T> e = get_extent();
return e.x * e.y * e.z;
}
template<typename T>
inline constexpr T aabb3<T>::get_area() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
vec3<T> e = get_extent();
return T(2) * (e.x*e.y + e.x*e.z + e.y*e.z);
}
template<typename T>
inline constexpr void aabb3<T>::get_corners(tl::span<vec3<T>> corners) const noexcept
{
TL_PLAIN_ASSERT(is_valid());
/*
Edges are stored in this way(assuming Y up):
Hey, am I an ascii artist, or what? :) niko.
/3--------/7
/ | / | +Y
/ | / | ^
1---------5 | |
| 2- - -| -6 +-------> +X
| / | / /
|/ | / /
0---------4/ +Z
*/
const vec3<T>& middle = get_center();
const vec3<T>& half_diag = get_half_extent();
corners[0] = vec3<T>(middle.x - half_diag.x, middle.y - half_diag.y, middle.z + half_diag.z);
corners[1] = vec3<T>(middle.x - half_diag.x, middle.y + half_diag.y, middle.z + half_diag.z);
corners[2] = vec3<T>(middle.x - half_diag.x, middle.y - half_diag.y, middle.z - half_diag.z);
corners[3] = vec3<T>(middle.x - half_diag.x, middle.y + half_diag.y, middle.z - half_diag.z);
corners[4] = vec3<T>(middle.x + half_diag.x, middle.y - half_diag.y, middle.z + half_diag.z);
corners[5] = vec3<T>(middle.x + half_diag.x, middle.y + half_diag.y, middle.z + half_diag.z);
corners[6] = vec3<T>(middle.x + half_diag.x, middle.y - half_diag.y, middle.z - half_diag.z);
corners[7] = vec3<T>(middle.x + half_diag.x, middle.y + half_diag.y, middle.z - half_diag.z);
}
template<typename T>
inline constexpr void aabb3<T>::add(const vec3<T>& p) noexcept
{
this->min = math::min(this->min, p);
this->max = math::max(this->max, p);
}
template<typename T>
inline constexpr void aabb3<T>::add(const aabb3<T>& b) noexcept
{
TL_PLAIN_ASSERT(b.is_valid());
add(b.min);
add(b.max);
}
template<typename T>
inline constexpr void aabb3<T>::add_checked(const aabb3<T>& b) noexcept
{
if (b.is_valid())
{
add(b.min);
add(b.max);
}
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::aabb3<T>>
{
std::size_t operator()(const math::aabb3<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.min);
tl::hash_and_combine(seed, p.max);
return seed;
}
};
+61
View File
@@ -0,0 +1,61 @@
#pragma once
#include <compare>
namespace math
{
template<typename T>
struct angle
{
typedef T value_t;
using this_t = angle<T>;
static inline T const pi = T(3.1415926535897932384626433832795028841971);
static inline T const pi2 = T(3.1415926535897932384626433832795028841971) / T(2);
static inline T const _2pi = T(3.1415926535897932384626433832795028841971) * T(2);
static inline T const _3pi2 = T(3.1415926535897932384626433832795028841971) * T(3) / T(2);
constexpr angle() noexcept = default;
constexpr explicit angle(T radians) noexcept;
constexpr angle(angle<T> const& a) = default;
constexpr explicit operator T() const { return radians; }
// normalizes an angle to -pi .. pi
constexpr angle<T>& normalize() noexcept;
// normalizes an angle to 0 .. 2pi
constexpr angle<T>& normalize_from_0_to_2pi() noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
constexpr angle<T> operator-() const noexcept;
constexpr angle<T> operator+(angle<T> const& v) const noexcept;
constexpr angle<T> operator-(angle<T> const& v) const noexcept;
constexpr angle<T> operator*(angle<T> const& v) const noexcept;
constexpr angle<T> operator/(angle<T> const& v) const noexcept;
constexpr angle<T>& operator=(angle<T> const& v) noexcept;
constexpr angle<T>& operator+=(angle<T> const& v) noexcept;
constexpr angle<T>& operator-=(angle<T> const& v) noexcept;
constexpr angle<T>& operator*=(angle<T> const& v) noexcept;
constexpr angle<T>& operator/=(angle<T> const& v) noexcept;
constexpr angle<T> operator+(T v) const noexcept;
constexpr angle<T> operator-(T v) const noexcept;
constexpr angle<T> operator*(T v) const noexcept;
constexpr angle<T> operator/(T v) const noexcept;
constexpr angle<T>& operator=(T v) noexcept;
constexpr angle<T>& operator+=(T v) noexcept;
constexpr angle<T>& operator-=(T v) noexcept;
constexpr angle<T>& operator*=(T v) noexcept;
constexpr angle<T>& operator/=(T v) noexcept;
T radians = T{};
};
}
+173
View File
@@ -0,0 +1,173 @@
#pragma once
namespace math
{
//////////////////////////////////////////////////////////////////////////
template<typename T>
constexpr inline angle<T>::angle(T radians) noexcept : radians(radians) { normalize(); }
template<typename T>
constexpr inline angle<T>& angle<T>::normalize() noexcept
{
T a = radians;
while (a > pi) a -= _2pi;
while (a < -pi) a += _2pi;
TL_PLAIN_ASSERT(-pi <= a && a <= pi);
radians = a;
return *this;
}
template<typename T>
constexpr inline angle<T>& angle<T>::normalize_from_0_to_2pi() noexcept
{
T a = radians;
while (a > _2pi) a -= _2pi;
while (a < 0) a += _2pi;
TL_PLAIN_ASSERT(0 <= a && a <= _2pi);
radians = a;
return *this;
}
template<typename T>
constexpr inline angle<T> angle<T>::operator-() const noexcept
{
T rad = (radians != -pi) ? -radians : pi;
TL_PLAIN_ASSERT(-pi < rad&& rad <= pi);
return angle<T>(rad);
}
template<typename T>
constexpr inline angle<T> angle<T>::operator+(angle<T> const& v) const noexcept
{
return *this + v.radians;
}
template<typename T>
constexpr inline angle<T> angle<T>::operator-(angle<T> const& v) const noexcept
{
return *this - v.radians;
}
template<typename T>
constexpr inline angle<T> angle<T>::operator*(angle<T> const& v) const noexcept
{
return *this * v.radians;
}
template<typename T>
constexpr inline angle<T> angle<T>::operator/(angle<T> const& v) const noexcept
{
TL_PLAIN_ASSERT(!is_zero(v.radians));
return *this / v.radians;
}
template<typename T>
constexpr inline angle<T>& angle<T>::operator=(angle<T> const& v) noexcept
{
TL_PLAIN_ASSERT(-pi <= T(v) && T(v) <= pi);
radians = v.radians;
return *this;
}
template<typename T>
constexpr inline angle<T>& angle<T>::operator+=(angle<T> const& v) noexcept
{
*this += v.radians;
return *this;
}
template<typename T>
constexpr inline angle<T>& angle<T>::operator-=(angle<T> const& v) noexcept
{
*this -= v.radians;
return *this;
}
template<typename T>
constexpr inline angle<T>& angle<T>::operator*=(angle<T> const& v) noexcept
{
*this *= v.radians;
return *this;
}
template<typename T>
constexpr inline angle<T>& angle<T>::operator/=(angle<T> const& v) noexcept
{
TL_PLAIN_ASSERT(!is_zero(v.radians));
*this /= v.radians;
return *this;
}
//////////////////////////////////////////////////////////////////////////
template<typename T>
constexpr inline angle<T> angle<T>::operator+(T v) const noexcept
{
const T sum = radians + v;
return angle<T>(sum);
}
template<typename T>
constexpr inline angle<T> angle<T>::operator-(T v) const noexcept
{
const T diff = radians - v;
return angle<T>(diff);
}
template<typename T>
constexpr inline angle<T> angle<T>::operator*(T v) const noexcept
{
const T a = radians * v;
return angle<T>(a);
}
template<typename T>
constexpr inline angle<T> angle<T>::operator/(T v) const noexcept
{
TL_PLAIN_ASSERT(!is_zero(v));
const T a = radians / v;
return angle<T>(a);
}
template<typename T>
constexpr inline angle<T>& angle<T>::operator=(T v) noexcept
{
radians = v;
normalize();
return *this;
}
template<typename T>
constexpr inline angle<T>& angle<T>::operator+=(T v) noexcept
{
radians += v;
normalize();
return *this;
}
template<typename T>
constexpr inline angle<T>& angle<T>::operator-=(T v) noexcept
{
radians -= v;
normalize();
return *this;
}
template<typename T>
constexpr inline angle<T>& angle<T>::operator*=(T v) noexcept
{
radians *= v;
normalize();
return *this;
}
template<typename T>
constexpr inline angle<T>& angle<T>::operator/=(T v) noexcept
{
TL_PLAIN_ASSERT(!is_zero(v));
radians /= v;
normalize();
return *this;
}
//////////////////////////////////////////////////////////////////////////
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::angle<T>>
{
std::size_t operator()(const math::angle<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.radians);
return seed;
}
};
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include <compare>
namespace math
{
template<typename T>
struct circle2
{
typedef T value_t;
typedef circle2<T> this_t;
constexpr circle2() noexcept = default;
constexpr circle2(const vec2<T>& center, T radius) noexcept;
constexpr circle2(const circle2&) noexcept = default;
constexpr circle2& operator=(const circle2&) noexcept = default;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
constexpr bool is_valid() const noexcept;
constexpr bool is_empty() const noexcept;
vec2<T> center;
T radius = T(-1);
};
}
+39
View File
@@ -0,0 +1,39 @@
namespace math
{
template<typename T>
inline constexpr circle2<T>::circle2(const vec2<T>& center, T radius) noexcept
: center(center)
, radius(radius)
{
TL_PLAIN_ASSERT(radius >= 0);
}
template<typename T>
inline constexpr bool circle2<T>::is_valid() const noexcept
{
return !is_negative(radius);
}
template<typename T>
inline constexpr bool circle2<T>::is_empty() const noexcept
{
return is_zero(radius);
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::circle2<T>>
{
std::size_t operator()(const math::circle2<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.center);
tl::hash_and_combine(seed, p.radius);
return seed;
}
};
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <compare>
namespace math
{
template<typename T, typename Traits>
struct clamped_value
{
using this_t = clamped_value<T, Traits>;
constexpr clamped_value() noexcept = default;
constexpr clamped_value(T value) noexcept;
constexpr clamped_value(const this_t& other) noexcept;
constexpr this_t& operator=(T value) noexcept;
constexpr this_t& operator=(const this_t& other) noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
constexpr bool operator!=(const this_t&) const noexcept = default;
constexpr this_t operator+(T value) const noexcept;
constexpr this_t operator-(T value) const noexcept;
constexpr this_t operator*(T value) const noexcept;
constexpr this_t operator/(T value) const noexcept;
constexpr this_t& operator+=(T value) noexcept;
constexpr this_t& operator-=(T value) noexcept;
constexpr this_t& operator*=(T value) noexcept;
constexpr this_t& operator/=(T value) noexcept;
constexpr this_t& operator+=(const this_t& value) noexcept;
constexpr this_t& operator-=(const this_t& value) noexcept;
constexpr this_t& operator*=(const this_t& value) noexcept;
constexpr this_t& operator/=(const this_t& value) noexcept;
constexpr operator T() const noexcept;
constexpr T value() const noexcept;
private:
T m_value;
};
}
+95
View File
@@ -0,0 +1,95 @@
#include <tl/numeric_limits.h>
namespace math
{
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>::clamped_value(T value) noexcept : m_value(math::clamp(value, Traits::min, Traits::max)) {}
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>::clamped_value(const this_t& other) noexcept : m_value(other.m_value) {}
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>& clamped_value<T, Traits>::operator=(T value) noexcept
{
m_value = math::clamp(value, Traits::min, Traits::max);
return *this;
}
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>& clamped_value<T, Traits>::operator=(const this_t& other) noexcept
{
m_value = other.m_value;
return *this;
}
template<typename T, typename Traits>
constexpr clamped_value<T, Traits> clamped_value<T, Traits>::operator+(T value) const noexcept { return this_t(m_value + value); }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits> clamped_value<T, Traits>::operator-(T value) const noexcept { return this_t(m_value - value); }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits> clamped_value<T, Traits>::operator*(T value) const noexcept { return this_t(m_value * value); }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits> clamped_value<T, Traits>::operator/(T value) const noexcept { return this_t(m_value / value); }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>& clamped_value<T, Traits>::operator+=(T value) noexcept { m_value = math::clamp(m_value + value, Traits::min, Traits::max); return *this; }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>& clamped_value<T, Traits>::operator-=(T value) noexcept { m_value = math::clamp(m_value - value, Traits::min, Traits::max); return *this; }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>& clamped_value<T, Traits>::operator*=(T value) noexcept { m_value = math::clamp(m_value * value, Traits::min, Traits::max); return *this; }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>& clamped_value<T, Traits>::operator/=(T value) noexcept { m_value = math::clamp(m_value / value, Traits::min, Traits::max); return *this; }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>& clamped_value<T, Traits>::operator+=(const this_t& value) noexcept { m_value = math::clamp(m_value + value.m_value, Traits::min, Traits::max); return *this; }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>& clamped_value<T, Traits>::operator-=(const this_t& value) noexcept { m_value = math::clamp(m_value - value.m_value, Traits::min, Traits::max); return *this; }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>& clamped_value<T, Traits>::operator*=(const this_t& value) noexcept { m_value = math::clamp(m_value * value.m_value, Traits::min, Traits::max); return *this; }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>& clamped_value<T, Traits>::operator/=(const this_t& value) noexcept { m_value = math::clamp(m_value / value.m_value, Traits::min, Traits::max); return *this; }
template<typename T, typename Traits>
constexpr clamped_value<T, Traits>::operator T() const noexcept { return m_value; }
template<typename T, typename Traits>
constexpr T clamped_value<T, Traits>::value() const noexcept { return m_value; }
}
template<typename T, typename Traits>
class eastl::numeric_limits<math:: clamped_value<T, Traits>>
{
public:
typedef math::clamped_value<T, Traits> value_type;
static EA_CONSTEXPR_OR_CONST bool is_specialized = true;
static EA_CONSTEXPR_OR_CONST int digits = tl::numeric_limits<T>::digits;
static EA_CONSTEXPR_OR_CONST int digits10 = tl::numeric_limits<T>::digits10;
static EA_CONSTEXPR_OR_CONST int max_digits10 = tl::numeric_limits<T>::max_digits10;
static EA_CONSTEXPR_OR_CONST bool is_signed = Traits::min < 0;
static EA_CONSTEXPR_OR_CONST bool is_integer = tl::numeric_limits<T>::is_integer;
static EA_CONSTEXPR_OR_CONST bool is_exact = tl::numeric_limits<T>::is_exact;
static EA_CONSTEXPR_OR_CONST int radix = tl::numeric_limits<T>::radix;
static EA_CONSTEXPR_OR_CONST int min_exponent = tl::numeric_limits<T>::min_exponent;
static EA_CONSTEXPR_OR_CONST int min_exponent10 = tl::numeric_limits<T>::min_exponent10;
static EA_CONSTEXPR_OR_CONST int max_exponent = tl::numeric_limits<T>::max_exponent;
static EA_CONSTEXPR_OR_CONST int max_exponent10 = tl::numeric_limits<T>::max_exponent10;
static EA_CONSTEXPR_OR_CONST bool is_bounded = tl::numeric_limits<T>::is_bounded;
static EA_CONSTEXPR_OR_CONST bool is_modulo = tl::numeric_limits<T>::is_modulo;
static EA_CONSTEXPR_OR_CONST bool traps = tl::numeric_limits<T>::traps;
static EA_CONSTEXPR_OR_CONST bool tinyness_before = tl::numeric_limits<T>::tinyness_before;
static EA_CONSTEXPR_OR_CONST float_round_style round_style = tl::numeric_limits<T>::round_style;
static EA_CONSTEXPR_OR_CONST bool has_infinity = tl::numeric_limits<T>::has_infinity;
static EA_CONSTEXPR_OR_CONST bool has_quiet_NaN = tl::numeric_limits<T>::has_quiet_NaN;
static EA_CONSTEXPR_OR_CONST bool has_signaling_NaN = tl::numeric_limits<T>::has_signaling_NaN;
static EA_CONSTEXPR_OR_CONST float_denorm_style has_denorm = tl::numeric_limits<T>::has_denorm;
static EA_CONSTEXPR_OR_CONST bool has_denorm_loss = tl::numeric_limits<T>::has_denorm_loss;
static EA_CONSTEXPR_OR_CONST bool is_iec559 = tl::numeric_limits<T>::is_iec559;
static value_type min() { return value_type(tl::numeric_limits<T>::min()); }
static value_type max() { return value_type(Traits::max); }
static value_type lowest() { return value_type(T(Traits::min)); }
static value_type epsilon() { return value_type(tl::numeric_limits<T>::epsilon()); }
static value_type round_error() { return value_type(tl::numeric_limits<T>::round_error()); }
static value_type infinity() { return value_type(tl::numeric_limits<T>::infinity()); }
static value_type quiet_NaN() { return value_type(tl::numeric_limits<T>::quiet_NaN()); }
static value_type signaling_NaN() { return value_type(tl::numeric_limits<T>::signaling_NaN()); }
static value_type denorm_min() { return value_type(tl::numeric_limits<T>::denorm_min()); }
};
+37
View File
@@ -0,0 +1,37 @@
#pragma once
namespace math
{
//returns true if the argument is a power of 2.
// isPow2(2) == true
// isPow2(3) == false
// isPow2(16) == true
template<typename T> constexpr bool is_pot(T v) noexcept;
//returns the smallest power of 2 that is greater or equal than the argument
// getSmallestPow2(127) == 128
// getSmallestPow2(128) == 128
// getSmallestPow2(129) == 256
template<typename T> constexpr T get_min_pot(T v) noexcept;
//returns the biggest power of 2 that is smaller or equal than the argument
// getSmallestPow2(127) == 64
// getSmallestPow2(128) == 128
// getSmallestPow2(129) == 128
template<typename T> constexpr T get_max_pot(T v) noexcept;
//returns the log2 of the argument
// getPow2(4) == 2
// getPow2(5) == 2
// getPow2(7) == 2
// getPow2(8) == 3
// getPow2(0) == undefined
template<typename T> constexpr int8_t get_pot(T v) noexcept;
//returns the number of 1 bits in the argument
// getOnBitsCount(4) == 1
// getOnBitsCount(5) == 2
// getOnBitsCount(7) == 3
template<typename T> constexpr int8_t get_on_bits_count(T v) noexcept;
}
+75
View File
@@ -0,0 +1,75 @@
namespace math
{
//////////////////////////////////////////////////////////////////////////
template<typename T>
constexpr inline bool is_pot(T v) noexcept
{
return (!is_zero(v)) && ((v & (v - 1)) == 0);
}
template<typename T>
constexpr inline T get_min_pot(T v) noexcept
{
TL_PLAIN_ASSERT(v < ~0u);
T result = 1;
while (result < v)
result <<= 1;
return result;
}
template<typename T>
constexpr inline T get_max_pot(T v) noexcept
{
TL_PLAIN_ASSERT(v > 0);
T result = 1;
T crt = result;
while (crt <= v)
{
result = crt;
crt <<= 1;
}
return result;
}
template<typename T>
constexpr inline int8_t get_pot(T v) noexcept
{
TL_PLAIN_ASSERT(v > 0);
int8_t shift = -1;
while (v)
{
shift++;
v >>= 1;
}
return shift;
}
template<>
constexpr inline int8_t get_on_bits_count(uint32_t v) noexcept
{
// From Hacker's Delight (http://books.google.com/books?id=iBNKMspIlqEC)
v = v - ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
v = (v + (v >> 4)) & 0x0F0F0F0F;
v = v + (v >> 8);
v = v + (v >> 16);
return static_cast<int8_t>(v & 0x0000003F);
}
template<typename T>
constexpr inline int8_t get_on_bits_count(T v) noexcept
{
uint8_t count = 0;
const uint8_t size = sizeof(T) * 8;
for (uint8_t i = 0; i < size && v; i++)
{
count += (v & 0x1);
v >>= 1;
}
return count;
}
}
+194
View File
@@ -0,0 +1,194 @@
#pragma once
namespace math
{
template<typename T, typename U>
constexpr vec2<T> to_vec2(const vec2<U>& v) noexcept;
template<typename T>
constexpr vec2<T> to_vec2(const vec3<T>& v) noexcept;
template<typename T, typename U>
constexpr vec2<T> to_vec2(const vec3<U>& v) noexcept;
template<typename T>
constexpr vec2<T> to_vec2(const vec4<T>& v) noexcept;
template<typename T, typename U>
constexpr vec2<T> to_vec2(const vec4<U>& v) noexcept;
template<typename T, typename U>
constexpr vec3<T> to_vec3(const vec3<U>& v) noexcept;
template<typename T>
constexpr vec3<T> to_vec3(const vec2<T>& v) noexcept;
template<typename T, typename U>
constexpr vec3<T> to_vec3(const vec2<U>& v) noexcept;
template<typename T>
constexpr vec3<T> to_vec3(const vec2<T>& v, T z) noexcept;
template<typename T, typename U>
constexpr vec3<T> to_vec3(const vec2<U>& v, T z) noexcept;
template<typename T>
constexpr vec3<T> to_vec3(const vec4<T>& v) noexcept;
template<typename T, typename U>
constexpr vec3<T> to_vec3(const vec4<U>& v) noexcept;
template<typename T, typename U>
constexpr vec4<T> to_vec4(const vec4<U>& v) noexcept;
template<typename T>
constexpr vec4<T> to_vec4(const vec2<T>& v) noexcept;
template<typename T, typename U>
constexpr vec4<T> to_vec4(const vec2<U>& v) noexcept;
template<typename T>
constexpr vec4<T> to_vec4(const vec2<T>& v, T z, T w) noexcept;
template<typename T, typename U>
constexpr vec4<T> to_vec4(const vec2<U>& v, T z, T w) noexcept;
template<typename T>
constexpr vec4<T> to_vec4(const vec3<T>& v) noexcept;
template<typename T, typename U>
constexpr vec4<T> to_vec4(const vec3<U>& v) noexcept;
template<typename T>
constexpr vec4<T> to_vec4(const vec3<T>& v, T w) noexcept;
template<typename T, typename U>
constexpr vec4<T> to_vec4(const vec3<U>& v, T w) noexcept;
template<typename T, typename U>
constexpr mat2<T> to_mat2(const mat2<U>& v) noexcept;
template<typename T>
constexpr mat2<T> to_mat2(const mat3<T>& v) noexcept;
template<typename T, typename U>
constexpr mat2<T> to_mat2(const mat3<U>& v) noexcept;
template<typename T>
constexpr mat2<T> to_mat2(const mat4<T>& v) noexcept;
template<typename T, typename U>
constexpr mat2<T> to_mat2(const mat4<U>& v) noexcept;
template<typename T, typename U>
constexpr mat3<T> to_mat3(const mat3<U>& v) noexcept;
template<typename T>
constexpr mat3<T> to_mat3(const mat4<T>& v) noexcept;
template<typename T, typename U>
constexpr mat3<T> to_mat3(const mat4<U>& v) noexcept;
template<typename T>
constexpr mat3<T> to_mat3(const mat2<T>& v) noexcept;
template<typename T, typename U>
constexpr mat3<T> to_mat3(const mat2<U>& v) noexcept;
template<typename T>
constexpr mat3<T> to_mat3(const trans2<T>& v) noexcept;
template<typename T, typename U>
constexpr mat3<T> to_mat3(const trans2<U>& v) noexcept;
template<typename T>
constexpr mat3<T> to_mat3(const quat<T>& v) noexcept;
template<typename T, typename U>
constexpr mat3<T> to_mat3(const quat<U>& v) noexcept;
template<typename T, typename U>
constexpr mat4<T> to_mat4(const mat4<U>& v) noexcept;
template<typename T>
constexpr mat4<T> to_mat4(const mat2<T>& v) noexcept;
template<typename T, typename U>
constexpr mat4<T> to_mat4(const mat2<U>& v) noexcept;
template<typename T>
constexpr mat4<T> to_mat4(const mat3<T>& v) noexcept;
template<typename T, typename U>
constexpr mat4<T> to_mat4(const mat3<U>& v) noexcept;
template<typename T>
constexpr mat4<T> to_mat4(const trans3<T>& v) noexcept;
template<typename T, typename U>
constexpr mat4<T> to_mat4(const trans3<U>& v) noexcept;
template<typename T, class Policy = standard>
constexpr quat<T> to_quat(const mat3<T>& v) noexcept;
template<typename T, typename U, class Policy = standard>
constexpr quat<T> to_quat(const mat3<U>& v) noexcept;
template<typename T>
constexpr trans2<T> to_trans2(const mat3<T>& v) noexcept;
template<typename T, typename U>
constexpr trans2<T> to_trans2(const mat3<U>& v) noexcept;
template<typename T>
constexpr trans2<T> to_trans2(const trans3<T>& v) noexcept;
template<typename T, typename U>
constexpr trans2<T> to_trans2(const trans3<U>& v) noexcept;
template<typename T>
constexpr trans2<T> to_trans2(const rigid2<T>& v) noexcept;
template<typename T>
constexpr trans2<T> to_trans2(const rigid2<T>& v, const math::vec2<T>& scale) noexcept;
template<typename T, typename U>
constexpr trans2<T> to_trans2(const rigid2<U>& v) noexcept;
template<typename T, typename U>
constexpr trans2<T> to_trans2(const rigid2<U>& v, const math::vec2<U>& scale) noexcept;
template<typename T>
constexpr trans3<T> to_trans3(const mat4<T>& v) noexcept;
template<typename T, typename U>
constexpr trans3<T> to_trans3(const mat4<U>& v) noexcept;
template<typename T>
constexpr trans3<T> to_trans3(const trans2<T>& v) noexcept;
template<typename T, typename U>
constexpr trans3<T> to_trans3(const trans2<U>& v) noexcept;
template<typename T>
constexpr trans3<T> to_trans3(const rigid3<T>& v) noexcept;
template<typename T>
constexpr trans3<T> to_trans3(const rigid3<T>& v, const math::vec3<T>& scale) noexcept;
template<typename T, typename U>
constexpr trans3<T> to_trans3(const rigid3<U>& v) noexcept;
template<typename T, typename U>
constexpr trans3<T> to_trans3(const rigid3<U>& v, const math::vec3<U>& scale) noexcept;
template<typename T>
constexpr line3<T> to_line3(const segment3<T>& v) noexcept;
template<typename T, typename U>
constexpr line3<T> to_line3(const segment3<U>& v) noexcept;
//templatic cast function, using the functions above
template<typename To, typename From>
constexpr To cast(const From& v) noexcept;
}
+481
View File
@@ -0,0 +1,481 @@
namespace math
{
template<typename T, typename U> inline constexpr vec2<T> to_vec2(const vec2<U>& v) noexcept { return vec2<T>(T(v.x), T(v.y)); }
template<typename T> inline constexpr vec2<T> to_vec2(const vec3<T>& v) noexcept { return to_vec2<T, T>(v); }
template<typename T, typename U> inline constexpr vec2<T> to_vec2(const vec3<U>& v) noexcept { return vec2<T>(T(v.x), T(v.y)); }
template<typename T> inline constexpr vec2<T> to_vec2(const vec4<T>& v) noexcept { return to_vec2<T, T>(v); }
template<typename T, typename U> inline constexpr vec2<T> to_vec2(const vec4<U>& v) noexcept { return vec2<T>(T(v.x), T(v.y)); }
//////////////////////////////////////////////////////////////////////////
template<typename T, typename U> inline constexpr vec3<T> to_vec3(const vec3<U>& v) noexcept { return vec3<T>(T(v.x), T(v.y), T(v.z)); }
template<typename T> inline constexpr vec3<T> to_vec3(const vec2<T>& v) noexcept { return to_vec3<T, T>(v); }
template<typename T, typename U> inline constexpr vec3<T> to_vec3(const vec2<U>& v) noexcept { return vec3<T>(T(v.x), T(v.y), 0); }
template<typename T> inline constexpr vec3<T> to_vec3(const vec2<T>& v, T z) noexcept { return to_vec3<T, T>(v, z); }
template<typename T, typename U> inline constexpr vec3<T> to_vec3(const vec2<U>& v, T z) noexcept { return vec3<T>(T(v.x), T(v.y), T(z)); }
template<typename T> inline constexpr vec3<T> to_vec3(const vec4<T>& v) noexcept { return to_vec3<T, T>(v); }
template<typename T, typename U> inline constexpr vec3<T> to_vec3(const vec4<U>& v) noexcept { return vec3<T>(T(v.x), T(v.y), T(v.z)); }
//////////////////////////////////////////////////////////////////////////
template<typename T, typename U> inline constexpr vec4<T> to_vec4(const vec4<U>& v) noexcept { return vec4<T>(T(v.x), T(v.y), T(v.z), T(v.w)); }
template<typename T> inline constexpr vec4<T> to_vec4(const vec2<T>& v) noexcept { return to_vec4<T, T>(v); }
template<typename T, typename U> inline constexpr vec4<T> to_vec4(const vec2<U>& v) noexcept { return vec4<T>(T(v.x), T(v.y), T(0), T(0)); }
template<typename T> inline constexpr vec4<T> to_vec4(const vec2<T>& v, T z, T w) noexcept { return to_vec4<T, T>(v, z, w); }
template<typename T, typename U> inline constexpr vec4<T> to_vec4(const vec2<U>& v, T z, T w) noexcept { return vec4<T>(T(v.x), T(v.y), z, w); }
template<typename T> inline constexpr vec4<T> to_vec4(const vec3<T>& v) noexcept { return to_vec4<T, T>(v); }
template<typename T, typename U> inline constexpr vec4<T> to_vec4(const vec3<U>& v) noexcept { return vec4<T>(T(v.x), T(v.y), T(v.z), T(0)); }
template<typename T> inline constexpr vec4<T> to_vec4(const vec3<T>& v, T w) noexcept { return to_vec4<T, T>(v, w); }
template<typename T, typename U> inline constexpr vec4<T> to_vec4(const vec3<U>& v, T w) noexcept { return vec4<T>(T(v.x), T(v.y), T(v.z), w); }
//////////////////////////////////////////////////////////////////////////
template<typename T, typename U>
inline constexpr mat2<T> to_mat2(const mat2<U>& v) noexcept
{
return mat2<T>(to_vec2<T>(v.column0),
to_vec2<T>(v.column1));
}
template<typename T, typename U>
inline constexpr mat2<T> to_mat2(const mat3<U>& v) noexcept
{
const T* m = v.data();
return
{
T(m[0]), T(m[1]),
T(m[3]), T(m[4]),
};
}
template<typename T> inline constexpr mat2<T> to_mat2(const mat3<T>& v) noexcept { return to_mat2<T, T>(v); }
template<typename T, typename U>
inline constexpr mat2<T> to_mat2(const mat4<U>& v) noexcept
{
return to_mat2(to_mat3(v));
}
template<typename T> inline constexpr mat2<T> to_mat2(const mat4<T>& v) noexcept { return to_mat2<T, T>(v); }
//////////////////////////////////////////////////////////////////////////
template<typename T, typename U>
inline constexpr mat3<T> to_mat3(const mat3<U>& v) noexcept
{
return mat3<T>(to_vec3<T>(v.column0),
to_vec3<T>(v.column1),
to_vec3<T>(v.column2));
}
template<typename T, typename U>
inline constexpr mat3<T> to_mat3(const mat4<U>& v) noexcept
{
const T* m = v.data();
return
{
T(m[0]), T(m[1]), T(m[2]),
T(m[4]), T(m[5]), T(m[6]),
T(m[8]), T(m[9]), T(m[10])
};
}
template<typename T> inline constexpr mat3<T> to_mat3(const mat4<T>& v) noexcept { return to_mat3<T, T>(v); }
template<typename T, typename U>
inline constexpr mat3<T> to_mat3(const mat2<U>& v) noexcept
{
const U* m = v.data();
return
{
T(m[2]), T(m[3]), T(0),
T(m[0]), T(m[1]), T(0),
T(0), T(0), T(1),
};
}
template<typename T> inline constexpr mat3<T> to_mat3(const mat2<T>& v) noexcept { return to_mat3<T, T>(v); }
template<typename T, typename U>
inline constexpr mat3<T> to_mat3(const trans2<U>& trans) noexcept
{
const U* m = trans.rotation_scale.data();
return
{
T(m[0]), T(m[1]), T(0),
T(m[2]), T(m[3]), T(0),
T(trans.translation.x), T(trans.translation.y), T(1)
};
}
template<typename T> inline constexpr mat3<T> to_mat3(const trans2<T>& trans) noexcept { return to_mat3<T, T>(trans); }
template<typename T, typename U>
inline constexpr mat3<T> to_mat3(const quat<U>& rotation) noexcept
{
T x = T(rotation.x);
T y = T(rotation.y);
T z = T(rotation.z);
T w = T(rotation.w);
T const x2 = x * T(2);
T const y2 = y * T(2);
T const z2 = z * T(2);
T const xx2 = x2 * x;
T const yy2 = y2 * y;
T const zz2 = z2 * z;
T const x2y = x2 * y;
T const x2z = x2 * z;
T const x2w = x2 * w;
T const y2z = y2 * z;
T const y2w = y2 * w;
T const z2w = z2 * w;
return
{
1 - yy2 - zz2, x2y + z2w, x2z - y2w,
x2y - z2w, 1 - xx2 - zz2, y2z + x2w,
x2z + y2w, y2z - x2w, 1 - yy2 - xx2,
};
}
template<typename T> inline constexpr mat3<T> to_mat3(const quat<T>& rotation) noexcept { return to_mat3<T, T>(rotation); }
template<typename T, typename U>
inline constexpr trans2<T> to_trans2(const mat3<U>& mat) noexcept
{
trans2<T> result(uninitialized);
T* tr = result.rotation_scale.data();
const U* m = mat.data();
tr[0] = T(m[0]);
tr[1] = T(m[1]);
TL_PLAIN_ASSERT(is_zero(m[2], U(0.00001)));
tr[2] = T(m[3]);
tr[3] = T(m[4]);
TL_PLAIN_ASSERT(is_zero(m[5], U(0.00001)));
result.translation = { T(m[6]), T(m[7]) };
TL_PLAIN_ASSERT(is_one(m[8], U(0.00001)));
return result;
}
template<typename T> inline constexpr trans2<T> to_trans2(const mat3<T>& mat) noexcept { return to_trans2<T, T>(mat); }
template<typename T, typename U>
inline constexpr trans2<T> to_trans2(const trans3<U>& v) noexcept
{
trans2<T> result(uninitialized);
T* tr = result.rotation_scale.data();
const U* m = v.rotation_scale.data();
tr[0] = T(m[0]);
tr[1] = T(m[1]);
TL_PLAIN_ASSERT(is_zero(m[2], U(0.00001)));
tr[2] = T(m[3]);
tr[3] = T(m[4]);
TL_PLAIN_ASSERT(is_zero(m[5], U(0.00001)));
TL_PLAIN_ASSERT(is_zero(m[6], U(0.00001)));
TL_PLAIN_ASSERT(is_zero(m[7], U(0.00001)));
TL_PLAIN_ASSERT(is_one(m[8], U(0.00001)));
result.translation = { T(v.translation.x), T(v.translation.y) };
TL_PLAIN_ASSERT(is_zero(v.translation.z, U(0.00001)));
return result;
}
template<typename T> inline constexpr trans2<T> to_trans2(const trans3<T>& v) noexcept { return to_trans2<T, T>(v); }
template<typename T, typename U>
constexpr trans2<T> to_trans2(const rigid2<U>& v) noexcept
{
return trans2<T>(to_vec2<T, U>(v.translation), static_cast<T>(v.rotation));
}
template<typename T, typename U>
constexpr trans2<T> to_trans2(const rigid2<U>& v, const math::vec2<U>& scale) noexcept
{
return trans2<T>(to_vec2<T, U>(v.translation), static_cast<T>(v.rotation), to_vec2<T, U>(scale));
}
template<typename T> constexpr trans2<T> to_trans2(const rigid2<T>& v) noexcept
{
return trans2<T>(v.translation, v.rotation);
}
template<typename T> constexpr trans2<T> to_trans2(const rigid2<T>& v, const math::vec2<T>& scale) noexcept
{
return trans2<T>(v.translation, v.rotation, scale);
}
//////////////////////////////////////////////////////////////////////////
template<typename T, typename U>
inline constexpr mat4<T> to_mat4(const mat4<U>& v) noexcept
{
return mat4<T>(to_vec4<T>(v.column0),
to_vec4<T>(v.column1),
to_vec4<T>(v.column2),
to_vec4<T>(v.column3));
}
template<typename T, typename U>
inline constexpr mat4<T> to_mat4(const mat3<U>& v) noexcept
{
const U* m = v.data();
return
{
T(m[0]), T(m[1]), T(m[2]), T(0),
T(m[3]), T(m[4]), T(m[5]), T(0),
T(m[6]), T(m[7]), T(m[8]), T(0),
T(0), T(0), T(0), T(1),
};
}
template<typename T> inline constexpr mat4<T> to_mat4(const mat3<T>& v) noexcept { return to_mat4<T, T>(v); }
template<typename T, typename U>
inline constexpr mat4<T> to_mat4(const mat2<U>& v) noexcept
{
return to_mat4(to_mat3(v));
}
template<typename T> inline constexpr mat4<T> to_mat4(const mat2<T>& v) noexcept { return to_mat4<T, T>(v); }
template<typename T, typename U, class Policy>
constexpr inline quat<T> to_quat(mat3<U> const& mat) noexcept
{
//from: https://en.wikipedia.org/wiki/Rotation_matrix
// "an M with negative determinant has no uniquely defined closest rotation matrix."
TL_PLAIN_ASSERT(mat.determinant() >= 0);
T x = 0;
T y = 0;
T z = 0;
T w = 0;
T trace = T(mat.element(0, 0) + mat.element(1, 1) + mat.element(2, 2));
if (trace > 0)
{
// |w| > 1/2, may as well choose w > 1/2
T fRoot = sqrt<T, Policy>(trace + 1); // 2w
w = T(0.5) * fRoot;
fRoot = T(0.5) / fRoot; // 1/(4w)
x = T(mat.element(1, 2) - mat.element(2, 1)) * fRoot;
y = T(mat.element(2, 0) - mat.element(0, 2)) * fRoot;
z = T(mat.element(0, 1) - mat.element(1, 0)) * fRoot;
}
else
{
// |w| <= 1/2
int i = 0;
if (mat.element(2, 2) > mat.element(i, i))
i = 2;
else if (mat.element(1, 1) > mat.element(0, 0))
i = 1;
int j = (i + 1) % 3;
int k = (j + 1) % 3;
T fRoot = sqrt<T, Policy>(T(mat.element(i, i) - mat.element(j, j) - mat.element(k, k) + T(1)));
T* apfQuat[3] = { &x, &y, &z };
*apfQuat[i] = T(0.5) * fRoot;
fRoot = T(0.5) / fRoot;
w = T(mat.element(j, k) - mat.element(k, j)) * fRoot;
*apfQuat[j] = T(mat.element(i, j) + mat.element(j, i)) * fRoot;
*apfQuat[k] = T(mat.element(i, k) + mat.element(k, i)) * fRoot;
}
return { x, y, z, w };
}
template<typename T, class Policy> constexpr inline quat<T> to_quat(mat3<T> const& mat) noexcept { return to_quat<T, T, Policy>(mat); }
template<typename T, typename U>
inline constexpr mat4<T> to_mat4(const trans3<U>& trans) noexcept
{
const U* m = trans.rotation_scale.data();
return
{
T(m[0]), T(m[1]), T(m[2]), T(0),
T(m[3]), T(m[4]), T(m[5]), T(0),
T(m[6]), T(m[7]), T(m[8]), T(0),
trans.translation.x, trans.translation.y, trans.translation.z, T(1),
};
}
template<typename T> inline constexpr mat4<T> to_mat4(const trans3<T>& trans) noexcept { return to_mat4<T, T>(trans); }
template<typename T, typename U>
inline constexpr trans3<T> to_trans3(const mat4<U>& mat) noexcept
{
trans3<T> result(uninitialized);
T* tr = result.rotation_scale.data();
const U* m = mat.data();
tr[0] = T(m[0]);
tr[1] = T(m[1]);
tr[2] = T(m[2]);
TL_PLAIN_ASSERT(is_zero(m[3], U(0.00001)));
tr[3] = T(m[4]);
tr[4] = T(m[5]);
tr[5] = T(m[6]);
TL_PLAIN_ASSERT(is_zero(m[7], U(0.00001)));
tr[6] = T(m[8]);
tr[7] = T(m[9]);
tr[8] = T(m[10]);
TL_PLAIN_ASSERT(is_zero(m[11], U(0.00001)));
result.translation = { T(m[12]), T(m[13]), T(m[14]) };
TL_PLAIN_ASSERT(is_one(m[15], U(0.00001)));
return result;
}
template<typename T> inline constexpr trans3<T> to_trans3(const mat4<T>& mat) noexcept { return to_trans3<T, T>(mat); }
template<typename T, typename U>
inline constexpr trans3<T> to_trans3(const trans2<U>& v) noexcept
{
trans3<T> result(uninitialized);
T* tr = result.rotation_scale.data();
const U* m = v.rotation_scale.data();
tr[0] = T(m[0]);
tr[1] = T(m[1]);
tr[2] = T(0);
tr[3] = T(m[2]);
tr[4] = T(m[3]);
tr[5] = T(0);
tr[6] = T(0);
tr[7] = T(0);
tr[8] = T(1);
result.translation = { T(v.translation.x), T(v.translation.y), 0 };
return result;
}
template<typename T> inline constexpr trans3<T> to_trans3(const trans2<T>& v) noexcept { return to_trans3<T, T>(v); }
template<typename T, typename U>
constexpr trans3<T> to_trans3(const rigid3<U>& v) noexcept
{
return trans3<T>(to_vec3<T, U>(v.translation), static_cast<T>(v.rotation));
}
template<typename T, typename U>
constexpr trans3<T> to_trans3(const rigid3<U>& v, const math::vec3<U>& scale) noexcept
{
return trans3<T>(to_vec3<T, U>(v.translation), static_cast<T>(v.rotation), to_vec3<T, U>(scale));
}
template<typename T> constexpr trans3<T> to_trans3(const rigid3<T>& v) noexcept
{
return trans3<T>(v.translation, v.rotation);
}
template<typename T> constexpr trans3<T> to_trans3(const rigid3<T>& v, const math::vec3<T>& scale) noexcept
{
return trans3<T>(v.translation, v.rotation, scale);
}
//////////////////////////////////////////////////////////////////////////
template<typename T, typename U>
inline constexpr line3<T> to_line3(const segment3<U>& v) noexcept
{
return { to_vec3<T>(v.start), to_vec3<T>(v.get_direction()) };
}
template<typename T> inline constexpr line3<T> to_line3(const segment3<T>& v) noexcept { return to_line3<T, T>(v); }
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
namespace detail
{
template<typename To, typename From>
struct caster
{
To operator()(const From& v) const { return static_cast<To>(v); }
};
template<typename T>
struct caster<T, vec2<T>>
{
T operator()(const vec2<T>& v) const { return v[0]; }
};
template<typename T>
struct caster<T, vec3<T>>
{
T operator()(const vec3<T>& v) const { return v[0]; }
};
template<typename T>
struct caster<T, vec4<T>>
{
T operator()(const vec4<T>& v) const { return v[0]; }
};
template<typename T, typename From>
struct caster<vec2<T>, From>
{
vec2<T> operator()(const From& v) const { return to_vec2<T>(v); }
};
template<typename T, typename From>
struct caster<vec3<T>, From>
{
vec3<T> operator()(const From& v) const { return to_vec3<T>(v); }
};
template<typename T, typename From>
struct caster<vec4<T>, From>
{
vec4<T> operator()(const From& v) const { return to_vec4<T>(v); }
};
template<typename T, typename From>
struct caster<quat<T>, From>
{
quat<T> operator()(const From& v) const { return to_quat<T>(v); }
};
template<typename T, typename From>
struct caster<mat2<T>, From>
{
mat2<T> operator()(const From& v) const { return to_mat2<T>(v); }
};
template<typename T, typename From>
struct caster<mat3<T>, From>
{
mat3<T> operator()(const From& v) const { return to_mat3<T>(v); }
};
template<typename T, typename From>
struct caster<mat4<T>, From>
{
mat4<T> operator()(const From& v) const { return to_mat4<T>(v); }
};
template<typename T, typename From>
struct caster<trans2<T>, From>
{
trans2<T> operator()(const From& v) const { return to_trans2<T>(v); }
};
template<typename T, typename From>
struct caster<trans3<T>, From>
{
trans3<T> operator()(const From& v) const { return to_trans3<T>(v); }
};
template<typename T, typename From>
struct caster<line3<T>, From>
{
line3<T> operator()(const From& v) const { return to_line3<T>(v); }
};
}
template<typename To, typename From> inline constexpr To cast(const From& v) noexcept
{
return detail::caster<To, From>()(v);
}
//template<typename T> inline constexpr T cast(const T& v) noexcept { return v; }
}
+167
View File
@@ -0,0 +1,167 @@
#pragma once
#include <tl/numeric_limits.h>
namespace math
{
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr T epsilon() noexcept;
template<typename T> inline T abs(T v) noexcept;
template<> inline uint8_t abs(uint8_t v) noexcept;
template<> inline uint16_t abs(uint16_t v) noexcept;
template<> inline uint32_t abs(uint32_t v) noexcept;
template<> inline uint64_t abs(uint64_t v) noexcept;
template<> inline int64_t abs(int64_t a) noexcept;
template<> inline float abs(float v) noexcept;
template<typename T> angle<T> abs(angle<T> const& v) noexcept;
template<typename T> vec2<T> abs(vec2<T> const& v) noexcept;
template<typename T> vec3<T> abs(vec3<T> const& v) noexcept;
template<typename T> vec4<T> abs(vec4<T> const& v) noexcept;
template<typename T> constexpr T sgn(T const& v) noexcept;
template<typename T> constexpr T sgn(angle<T> const& v) noexcept;
template<typename T> constexpr vec2<T> sgn(vec2<T> const& v) noexcept;
template<typename T> constexpr vec3<T> sgn(vec3<T> const& v) noexcept;
template<typename T> constexpr vec4<T> sgn(vec4<T> const& v) noexcept;
template<typename T, class Policy = standard> inline T sqrt(T const& v) noexcept;
template<> inline float sqrt<float, standard>(float const& v) noexcept;
template<> inline float sqrt<float, safe>(float const& v) noexcept;
template<> inline float sqrt<float, fast>(float const& v) noexcept;
template<> inline double sqrt<double, standard>(double const& v) noexcept;
template<> inline double sqrt<double, fast>(double const& v) noexcept;
template<> inline double sqrt<double, safe>(double const& v) noexcept;
template<typename T, class Policy = standard> inline vec2<T> sqrt(vec2<T> const& v) noexcept;
template<typename T, class Policy = standard> inline vec3<T> sqrt(vec3<T> const& v) noexcept;
template<typename T, class Policy = standard> inline vec4<T> sqrt(vec4<T> const& v) noexcept;
template<typename T, class Policy = standard> T inv_sqrt(T const& v) noexcept;
template<> inline float inv_sqrt<float, fast>(float const& v) noexcept;
template<> inline float inv_sqrt<float, safe>(float const& v) noexcept;
template<> inline double inv_sqrt<double, safe>(double const& v) noexcept;
template<typename T, class Policy = standard> vec2<T> inv_sqrt(vec2<T> const& v) noexcept;
template<typename T, class Policy = standard> vec3<T> inv_sqrt(vec3<T> const& v) noexcept;
template<typename T, class Policy = standard> vec4<T> inv_sqrt(vec4<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr bool inverse(T const& v, T& res) noexcept;
template<typename T, class Policy = standard> constexpr rigid2<T> inverse(const rigid2<T>& v) noexcept; //cannot fail
template<typename T, class Policy = standard> constexpr rigid3<T> inverse(const rigid3<T>& v) noexcept; //cannot fail
template<typename T, class Policy = standard> constexpr quat<T> inverse(const quat<T>& v) noexcept; //cannot fail
template<typename T, class Policy = standard> constexpr bool invert(T& v) noexcept;
template<typename T, class Policy = standard> constexpr bool invert(mat2<T>& v) noexcept;
template<typename T, class Policy = standard> constexpr bool invert(mat3<T>& v) noexcept;
template<typename T, class Policy = standard> constexpr bool invert32(mat3<T>& v) noexcept; //suitable for when the last row is 0 0 1
template<typename T, class Policy = standard> constexpr bool invert(mat4<T>& v) noexcept;
template<typename T, class Policy = standard> constexpr bool invert43(mat4<T>& v) noexcept; //suitable for when the last row is 0 0 0 1
template<typename T, class Policy = standard> constexpr bool invert(trans2<T>& v) noexcept;
template<typename T, class Policy = standard> constexpr bool invert(trans3<T>& v) noexcept;
template<typename T, class Policy = standard> constexpr bool invert(rigid2<T>& v) noexcept;
template<typename T, class Policy = standard> constexpr bool invert(rigid3<T>& v) noexcept;
template<typename T, class Policy = standard> constexpr bool invert(quat<T>& v) noexcept;
template<typename T> constexpr T transposed(T const& v) noexcept;
template<typename T> constexpr void transpose(mat2<T>& v) noexcept;
template<typename T> constexpr void transpose(mat3<T>& v) noexcept;
template<typename T> constexpr void transpose(mat4<T>& v) noexcept;
template<typename T, class Policy = standard> inline T pow(T const& a, T const& b) noexcept;
template<> inline float pow<float, standard>(float const& a, float const& b) noexcept;
template<> inline float pow<float, fast>(float const& a, float const& b) noexcept;
template<> inline float pow<float, safe>(float const& a, float const& b) noexcept;
template<> inline double pow<double, standard>(double const& a, double const& b) noexcept;
template<> inline double pow<double, fast>(double const& a, double const& b) noexcept;
template<> inline double pow<double, safe>(double const& a, double const& b) noexcept;
template<typename T, class Policy = standard> inline vec2<T> pow(vec2<T> const& a, vec2<T> const& b) noexcept;
template<typename T, class Policy = standard> inline vec3<T> pow(vec3<T> const& a, vec3<T> const& b) noexcept;
template<typename T, class Policy = standard> inline vec4<T> pow(vec4<T> const& a, vec4<T> const& b) noexcept;
template<typename T> constexpr T positive_zero(T const& v) noexcept;
template<> constexpr float positive_zero(float const& v) noexcept;
template<typename T> constexpr angle<T> positive_zero(angle<T> const& v) noexcept;
template<typename T> constexpr vec2<T> positive_zero(vec2<T> const& v) noexcept;
template<typename T> constexpr vec3<T> positive_zero(vec3<T> const& v) noexcept;
template<typename T> constexpr vec4<T> positive_zero(vec4<T> const& v) noexcept;
template<typename T> constexpr quat<T> positive_zero(quat<T> const& v) noexcept;
template<typename T> constexpr T dot(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T> constexpr T dot(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T> constexpr T dot(vec4<T> const& v1, vec4<T> const& v2) noexcept;
template<typename T> constexpr T dot(quat<T> const& v1, quat<T> const& v2) noexcept;
template<typename T> constexpr T cross(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T> constexpr vec3<T> cross(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T> vec4<T> cross(vec4<T> const& x1, vec4<T> const& x2, vec4<T> const& x3) noexcept;
template<typename T> constexpr T length_sq(vec2<T> const& v) noexcept;
template<typename T> constexpr T length_sq(vec3<T> const& v) noexcept;
template<typename T> constexpr T length_sq(vec4<T> const& v) noexcept;
template<typename T> constexpr T length_sq(quat<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr T length(vec2<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr T length(vec3<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr T length(vec4<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr T length(quat<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr void set_length(vec2<T>& v, T length) noexcept;
template<typename T, class Policy = standard> constexpr void set_length(vec3<T>& v, T length) noexcept;
template<typename T, class Policy = standard> constexpr void set_length(vec4<T>& v, T length) noexcept;
template<typename T, class Policy = standard> constexpr angle<T> normalized(angle<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr vec2<T> normalized(vec2<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr vec3<T> normalized(vec3<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr vec4<T> normalized(vec4<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr quat<T> normalized(quat<T> const& v) noexcept;
template<typename T> constexpr T square(T const& v) noexcept;
template<typename T, class Policy = standard> constexpr T distance(T const& v1, T const& v2) noexcept;
template<typename T, class Policy = standard> constexpr angle<T> distance(angle<T> const& v1, angle<T> const& v2) noexcept;
template<typename T, class Policy = standard> constexpr T distance(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T, class Policy = standard> constexpr T distance(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T, class Policy = standard> constexpr T distance(vec4<T> const& v1, vec4<T> const& v2) noexcept;
template<typename T, class Policy = standard> constexpr T distance(line3<T> const& l1, line3<T> const& l2) noexcept;
template<typename T, class Policy = standard> constexpr T signed_distance(T const& v1, T const& v2) noexcept;
template<typename T, class Policy = standard> constexpr angle<T> signed_distance(angle<T> const& v1, angle<T> const& v2) noexcept;
template<typename T, class Policy = standard> constexpr T signed_distance(plane<T> const& p, vec3<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr T signed_distance(vec3<T> const& v, plane<T> const& p) noexcept;
template<typename T> constexpr T distance_sq(T const& v1, T const& v2) noexcept;
template<typename T> constexpr T distance_sq(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T> constexpr T distance_sq(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T> constexpr T distance_sq(vec4<T> const& v1, vec4<T> const& v2) noexcept;
template<typename T> constexpr T distance_sq(line3<T> const& l1, line3<T> const& l2) noexcept;
namespace cwise
{
template<typename T> constexpr T min_component(vec2<T> const& v) noexcept;
template<typename T> constexpr T min_component(vec3<T> const& v) noexcept;
template<typename T> constexpr T min_component(vec4<T> const& v) noexcept;
template<typename T> constexpr size_t min_component_index(vec2<T> const& v) noexcept;
template<typename T> constexpr size_t min_component_index(vec3<T> const& v) noexcept;
template<typename T> constexpr size_t min_component_index(vec4<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr T max_component(vec2<T> const& v) noexcept;
template<typename T> constexpr T max_component(vec3<T> const& v) noexcept;
template<typename T> constexpr T max_component(vec4<T> const& v) noexcept;
template<typename T> constexpr size_t max_component_index(vec2<T> const& v) noexcept;
template<typename T> constexpr size_t max_component_index(vec3<T> const& v) noexcept;
template<typename T> constexpr size_t max_component_index(vec4<T> const& v) noexcept;
}
namespace batch
{
template<typename T> void dot(T* dst, size_t dstStride, vec3<T> const* src1, size_t src1Stride, vec3<T> const* src2, size_t src2Stride, size_t count) noexcept;
template<typename T> void dot(T* dst, size_t dstStride, vec4<T> const* src1, size_t src1Stride, vec4<T> const* src2, size_t src2Stride, size_t count) noexcept;
}
}
//#include "func_common.hpp"
File diff suppressed because it is too large Load Diff
+30
View File
@@ -0,0 +1,30 @@
#pragma once
namespace math
{
template<class Policy = standard>
constexpr float lerp(float a, float b, float t) noexcept;
template<class T, class Policy = standard>
constexpr T lerp(T const& a, T const& b, float t) noexcept;
template<typename T, class Policy = standard>
constexpr angle<T> lerp(angle<T> const& a, angle<T> const& b, float t) noexcept;
template<class T, class Policy = standard>
constexpr vec2<T> lerp(vec2<T> const& a, vec2<T> const& b, float t) noexcept;
template<class T, class Policy = standard>
constexpr vec3<T> lerp(vec3<T> const& a, vec3<T> const& b, float t) noexcept;
template<class T, class Policy = standard>
constexpr vec4<T> lerp(vec4<T> const& a, vec4<T> const& b, float t) noexcept;
template<typename T, class Policy = standard>
constexpr quat<T> nlerp(quat<T> const& a, quat<T> const& b, float t) noexcept;
template<typename T, class Policy = standard>
constexpr quat<T> slerp(quat<T> const& a, quat<T> const& b, float t) noexcept;
}
+123
View File
@@ -0,0 +1,123 @@
namespace math
{
namespace detail
{
template<class Policy>
constexpr float lerp_check_mu(float t) noexcept
{
//TL_PLAIN_ASSERT(is_finite(t));
TL_PLAIN_ASSERT(t >= 0 && t <= 1);
return t;
}
template<>
constexpr float lerp_check_mu<safe>(float t) noexcept
{
//TL_PLAIN_ASSERT(is_finite(t));
return clamp(t, 0.f, 1.f);
}
}
template<class Policy>
constexpr float lerp(float a, float b, float t) noexcept
{
TL_PLAIN_ASSERT(is_finite(a) && is_finite(b)/* && is_finite(t)*/);
t = detail::lerp_check_mu<Policy>(t);
const float x = b - a;
return a + x*t;
}
template<class T, class Policy>
constexpr T lerp(T const& a, T const& b, float t) noexcept
{
TL_PLAIN_ASSERT(is_finite(a) && is_finite(b)/* && is_finite(t)*/);
t = detail::lerp_check_mu<Policy>(t);
return (T)(a*(1.f - t) + b*t);
}
template<typename T, class Policy>
constexpr angle<T> lerp(angle<T> const& a, angle<T> const& b, float t) noexcept
{
t = detail::lerp_check_mu<Policy>(t);
T start = a.radians;
T end = b.radians;
T difference = abs(end - start);
if (difference > angle<T>::pi) // We need to add on to one of the values.
{
if (end > start) // We'll add it on to start...
start += angle<T>::_2pi;
else // Add it on to end.
end += angle<T>::_2pi;
}
return angle<T>(start + ((end - start) * t));
}
template<class T, class Policy>
constexpr vec2<T> lerp(vec2<T> const& a, vec2<T> const& b, float t) noexcept
{
t = detail::lerp_check_mu<Policy>(t);
vec2<T> x = b - a;
return vec2<T>(a.x + x.x*T(t), a.y + x.y*T(t));
}
template<class T, class Policy>
constexpr vec3<T> lerp(vec3<T> const& a, vec3<T> const& b, float t) noexcept
{
t = detail::lerp_check_mu<Policy>(t);
vec3<T> x = b - a;
return vec3<T>(a.x + x.x*T(t), a.y + x.y*T(t), a.z + x.z*T(t));
}
template<class T, class Policy>
constexpr vec4<T> lerp(vec4<T> const& a, vec4<T> const& b, float t) noexcept
{
t = detail::lerp_check_mu<Policy>(t);
vec4<T> x = b - a;
return vec4<T>(a.x + x.x*T(t), a.y + x.y*T(t), a.z + x.z*T(t), a.w + x.w*T(t));
}
template<typename T, class Policy>
constexpr quat<T> nlerp(quat<T> const& a, quat<T> const& b, float t) noexcept
{
t = detail::lerp_check_mu<Policy>(t);
T angle = dot(a, b);
if (angle >= 0)
return normalized(a + (b - a) * t);
else if (angle <= -0.9999)
return normalized(t < T(0.5) ? a : b);
else
return normalized(a + (-b - a) * t);
}
template<typename T, class Policy>
constexpr quat<T> slerp(quat<T> const& a, quat<T> const& b, float t) noexcept
{
t = detail::lerp_check_mu<Policy>(t);
const T one = T(1) - tl::numeric_limits<T>::epsilon() * T(2);
T d = dot(a, b);
T absD = math::abs(d);
T scale0;
T scale1;
if (absD >= one)
{
scale0 = T(1) - t;
scale1 = t;
}
else
{
// theta is the angle between the 2 quaternions
T theta = acos(absD);
T sinTheta = sin(theta);
scale0 = sin((T(1) - t) * theta) / sinTheta;
scale1 = sin((t * theta)) / sinTheta;
}
if (d < T(0))
scale1 = -scale1;
TL_PLAIN_ASSERT(!is_nan(scale0) && !is_nan(scale1));
return normalized(quat<T>(a * scale0 + b * scale1));
}
}
+67
View File
@@ -0,0 +1,67 @@
#pragma once
namespace math
{
// Spherical linear interpolation No-Invert.
// Knowing that dot(q1,q2) = cos(theta) where theta is the angle between q1 and q2.
// This version of slerp, used by squad, does not check for theta > 90.
template<typename T> constexpr quat<T> slerp_no_invert(quat<T> const& a, quat<T> const& b, float mu) noexcept;
//! Spherical Quadrangle Interpolation
// It constructs a spherical cubic interpolation as a series of three spherical
// linear interpolations of a quadrangle of unit quaternions.
// qspline() uses this method to perform a spline interpolation.
template<typename T> constexpr quat<T> squad(quat<T> const& q1, quat<T> const& qa, quat<T> const& qb, quat<T> const& q2, float mu) noexcept;
namespace tween
{
// Linear interpolation LinearStep(t) = t
template<typename T> constexpr T linear(T t) noexcept;
// Cubic Hermite interpolation; between [0 and 1]; see http://en.wikipedia.org/wiki/Smoothstep
// SmoothStep(t) = 3t^2 - 2t^3
template<typename T> constexpr T smooth(T t) noexcept;
// Variation of Smooth Step; between [0 and 1]; see http://en.wikipedia.org/wiki/Smoothstep
// SmootherStep(t) = 6t^5 - 15t^4 + 10t^3
template<typename T> constexpr T smoother(T t) noexcept;
// quadratic transition out [0 to 1]
template<typename T> constexpr T quadratic_ease_out(T t) noexcept;
// quadratic transition in [0 to 1]
template<typename T> constexpr T quadratic_ease_in(T t) noexcept;
// quadratic smooth transition [0 to 1]
template<typename T> constexpr T quadratic_ease_inout(T t) noexcept;
// quartic transition out [0 to 1]
template<typename T> constexpr T quartic_ease_out(T t) noexcept;
// quartic transition in [0 to 1]
template<typename T> constexpr T quartic_ease_in(T t) noexcept;
// quartic smooth transition [0 to 1]
template<typename T> constexpr T quartic_ease_inout(T t) noexcept;
// octic transition out [0 to 1]
template<typename T> constexpr T octic_ease_out(T t) noexcept;
// octic transition in [0 to 1]
template<typename T> constexpr T octic_ease_in(T t) noexcept;
// octic smooth transition inout [0 to 1]
template<typename T>constexpr T octic_ease_inout(T t) noexcept;
// circular transition out [0 to 1]
template<typename T> constexpr T circular_ease_out(T t) noexcept;
// circular transition in [0 to 1]
template<typename T> constexpr T circular_ease_in(T t) noexcept;
// circular transition inout [0 to 1]
template<typename T> constexpr T circular_ease_inout(T t) noexcept;
}
}
+164
View File
@@ -0,0 +1,164 @@
namespace math
{
template<typename T> constexpr quat<T> slerp_no_invert(quat<T> const& a, quat<T> const& b, float t) noexcept
{
const T one = T(1);
T angle = dot(a, b);
T scale;
T invscale;
if (angle > T(0.999) || angle < T(-0.999))
{
scale = one - t;
invscale = t;
return math::normalized(quat<T>((a * scale) + (b * invscale)));
}
else
{
T const theta = acos(angle);
T const invsintheta = one / sin(theta);
scale = sin(theta * (one - t)) * invsintheta;
invscale = sin(theta * t) * invsintheta;
return quat<T>((a * scale) + (b * invscale));
}
}
template<typename T> constexpr quat<T> squad(quat<T> const& q1, quat<T> const& q_tangent_a, quat<T> const& q_tangent_b, quat<T> const& q2, float t) noexcept
{
const math::quat<T> r1 = slerp_no_invert(q1, q2, t);
const math::quat<T> r2 = slerp_no_invert(q_tangent_a, q_tangent_b, t);
return slerp_no_invert(r1, r2, 2 * t * (1 - t));
}
namespace tween
{
template<typename T> constexpr T linear(T t) noexcept
{
return t;
}
template<typename T> constexpr T smooth(T t) noexcept
{
return clamp(t * t * (T(3) - T(2) * t), T(0), T(1));
}
template<typename T> constexpr T smoother(T t) noexcept
{
return clamp(t * t * t * (t * (t * T(6) - T(15)) + T(10)), T(0), T(1));
}
template<typename T> constexpr T quadratic_ease_out(T t) noexcept
{
T invT = T(1) - t;
return clamp(T(1) - (invT * invT), T(0), T(1));
}
template<typename T> constexpr T quadratic_ease_in(T t) noexcept
{
return clamp(t * t, T(0), T(1));
}
template<typename T> constexpr T quadratic_ease_inout(T t) noexcept
{
t *= T(2);
if (t < T(1))
return clamp(T(0.5) * t * t, T(0), T(1));
else
{
t -= T(2);
return clamp(T(-0.5) * (t * t - T(2)), T(0), T(1));
}
}
template<typename T> constexpr T quartic_ease_out(T t) noexcept
{
T invT = T(1) - t;
invT *= invT;
return clamp(T(1) - (invT * invT), T(0), T(1));
}
template<typename T> constexpr T quartic_ease_in(T t) noexcept
{
T t2 = t * t;
return t2 * t2;
}
template<typename T> constexpr T quartic_ease_inout(T t) noexcept
{
t *= T(2);
if (t < T(1))
{
T t2 = t * t;
return T(0.5) * t2 * t2;
}
else
{
t -= T(2);
T t2 = t * t;
return clamp(T(-0.5) * (t2 * t2 - T(2)), T(0), T(1));
}
}
template<typename T> constexpr T octic_ease_out(T t) noexcept
{
T invT = T(1) - t;
invT *= invT;
invT *= invT;
invT *= invT;
return clamp(T(1) - invT, T(0), T(1));
}
template<typename T> constexpr T octic_ease_in(T t) noexcept
{
T t2 = t * t;
t2 *= t2;
return t2 * t2;
}
template<typename T> constexpr T octic_ease_inout(T t) noexcept
{
t *= T(2);
if (t < T(1))
{
T t2 = t * t;
t2 *= t2;
return T(0.5) * t2 * t2;
}
else
{
t -= T(2);
T t2 = t * t;
t2 *= t2;
return clamp(T(-0.5) * (t2 * t2 - T(2)), T(0), T(1));
}
}
template<typename T> constexpr T circular_ease_out(T t) noexcept
{
T t1 = t - 1;
return math::sqrt(T(1) - t1 * t1);
}
template<typename T> constexpr T circular_ease_in(T t) noexcept
{
return clamp(T(-1) * (math::sqrt(T(1) - t * t) - T(1)), T(0), T(1));
}
template<typename T> constexpr T circular_ease_inout(T t) noexcept
{
t *= T(2);
if (t < T(1))
return clamp(T(-0.5) * (math::sqrt(T(1) - t * t) - T(1)), T(0), T(1));
else
{
t -= T(2);
return clamp(T(0.5) * (math::sqrt(T(1) - t * t) + T(1)), T(0), T(1));
}
}
}
}
+53
View File
@@ -0,0 +1,53 @@
#pragma once
namespace math
{
/*
* d_near and d_far specifies the distance from the origin where the primitive enter and exits the aabb
*
*/
template<typename T>
constexpr bool intersect_line_plane(const line3<T>& line, const plane<T>& plane, float& d) noexcept;
template<typename T>
constexpr bool intersect_line_aabb(const line3<T>& line, const aabb3<T>& aabb, float& d_near, float& d_far) noexcept;
template<typename T>
constexpr bool intersect_line_aabb(const line2<T>& line, const aabb2<T>& aabb, float& d_near, float& d_far) noexcept;
template<typename T>
constexpr bool intersect_ray_plane(const ray3<T>& line, const plane<T>& plane, float& d) noexcept;
template<typename T>
constexpr bool intersect_ray_aabb(const ray2<T>& ray, const aabb2<T>& aabb, float& d_near, float& d_far) noexcept;
template<typename T>
constexpr bool intersect_ray_aabb(const ray3<T>& ray, const aabb3<T>& aabb, float& d_near, float& d_far) noexcept;
template<typename T>
constexpr bool intersect_segment_aabb(const segment2<T>& segment, const aabb2<T>& aabb, float& d_near, float& d_far) noexcept;
template<typename T>
constexpr bool intersect_segment_aabb(const segment3<T>& segment, const aabb3<T>& aabb, float& d_near, float& d_far) noexcept;
template<typename T>
constexpr bool intersect_point_segment(const math::vec3<T>& point, const segment3<T>& segment) noexcept;
template<typename T>
constexpr bool intersect_point_segment(const math::vec3<T>& point, const segment3<T>& segment, float& d) noexcept;
template<typename T>
constexpr bool intersect_line_triangle(const line3<T>& line, const triangle3<T>& triangle, float& line_d, vec2<T>& bari_coords) noexcept;
template<typename T>
constexpr bool intersect_ray_triangle(const ray3<T>& ray, const triangle3<T>& triangle, float& ray_d, vec2<T>& bari_coords) noexcept;
template<typename T>
constexpr bool intersect_segment_triangle(const segment3<T>& segment, const triangle3<T>& triangle, float& segment_d, vec2<T>& bari_coords) noexcept;
template<typename T>
constexpr math::segment3<T> closest_segment_between_lines(const math::line3<T>& a, const math::line3<T>& b) noexcept;
template<typename T>
constexpr math::vec3<T> closest_point_to_line(const vec3<T>& point, const line3<T>& line) noexcept;
template<typename T>
constexpr math::vec3<T> closest_point_to_segment(const vec3<T>& point, const segment3<T>& segment) noexcept;
template<typename T>
constexpr math::vec3<T> closest_point_to_ray(const vec3<T>& point, const ray3<T>& ray) noexcept;
}
+380
View File
@@ -0,0 +1,380 @@
#pragma once
namespace math
{
/*
* Reference
* https://github.com/juj/MathGeoLib/blob/master/src/Geometry/Line.cpp
*/
namespace detail
{
template<typename T>
constexpr bool do_intersect_line_aabb(const vec3<T>& line_pos, const vec3<T>& line_dir, const aabb3<T>& aabb, float& d_near, float& d_far) noexcept
{
// The user should have inputted values for d_near and d_far to specify the desired subrange [d_near, d_far] of the line
// for this intersection test.
// For a Line-AABB test, pass in
// d_near = -FLOAT_INF;
// d_far = FLOAT_INF;
// For a Ray-AABB test, pass in
// d_near = 0.f;
// d_far = FLOAT_INF;
// For a LineSegment-AABB test, pass in
// d_near = 0.f;
// d_far = LineSegment.Length();
// Test each cardinal plane (X, Y and Z) in turn.
if (!is_zero(line_dir.x))
{
const float rcp_dir = T(1) / line_dir.x;
const float t1 = (aabb.min.x - line_pos.x) * rcp_dir;
const float t2 = (aabb.max.x - line_pos.x) * rcp_dir;
// d_near tracks distance to intersect (enter) the AABB.
// d_far tracks the distance to exit the AABB.
if (t1 < t2)
d_near = math::max(t1, d_near), d_far = math::min(t2, d_far);
else // Swap t1 and t2.
d_near = math::max(t2, d_near), d_far = math::min(t1, d_far);
if (d_near > d_far)
return false; // Box is missed since we "exit" before entering it.
}
else if (line_pos.x < aabb.min.x || line_pos.x > aabb.max.x)
return false; // The ray can't possibly enter the box, abort.
if (!is_zero(line_dir.y))
{
const float rcp_dir = T(1) / line_dir.y;
const float t1 = (aabb.min.y - line_pos.y) * rcp_dir;
const float t2 = (aabb.max.y - line_pos.y) * rcp_dir;
if (t1 < t2)
d_near = math::max(t1, d_near), d_far = math::min(t2, d_far);
else // Swap t1 and t2.
d_near = math::max(t2, d_near), d_far = math::min(t1, d_far);
if (d_near > d_far)
return false; // Box is missed since we "exit" before entering it.
}
else if (line_pos.y < aabb.min.y || line_pos.y > aabb.max.y)
return false; // The ray can't possibly enter the box, abort.
if (!is_zero(line_dir.z)) // ray is parallel to plane in question
{
const float rcp_dir = T(1) / line_dir.z;
const float t1 = (aabb.min.z - line_pos.z) * rcp_dir;
const float t2 = (aabb.max.z - line_pos.z) * rcp_dir;
if (t1 < t2)
d_near = math::max(t1, d_near), d_far = math::min(t2, d_far);
else // Swap t1 and t2.
d_near = math::max(t2, d_near), d_far = math::min(t1, d_far);
}
else if (line_pos.z < aabb.min.z || line_pos.z > aabb.max.z)
return false; // The ray can't possibly enter the box, abort.
return d_near <= d_far;
}
template<typename T>
constexpr bool do_intersect_line_aabb(const vec3<T>& line_pos, const vec3<T>& line_dir, const aabb2<T>& aabb, float& d_near, float& d_far) noexcept
{
// The user should have inputted values for d_near and d_far to specify the desired subrange [d_near, d_far] of the line
// for this intersection test.
// For a Line-AABB test, pass in
// d_near = -FLOAT_INF;
// d_far = FLOAT_INF;
// For a Ray-AABB test, pass in
// d_near = 0.f;
// d_far = FLOAT_INF;
// For a LineSegment-AABB test, pass in
// d_near = 0.f;
// d_far = LineSegment.Length();
// Test each cardinal plane (X, Y and Z) in turn.
if (!is_zero(line_dir.x))
{
const float rcp_dir = T(1) / line_dir.x;
const float t1 = (aabb.min.x - line_pos.x) * rcp_dir;
const float t2 = (aabb.max.x - line_pos.x) * rcp_dir;
// d_near tracks distance to intersect (enter) the AABB.
// d_far tracks the distance to exit the AABB.
if (t1 < t2)
d_near = math::max(t1, d_near), d_far = math::min(t2, d_far);
else // Swap t1 and t2.
d_near = math::max(t2, d_near), d_far = math::min(t1, d_far);
if (d_near > d_far)
return false; // Box is missed since we "exit" before entering it.
}
else if (line_pos.x < aabb.min.x || line_pos.x > aabb.max.x)
return false; // The ray can't possibly enter the box, abort.
if (!is_zero(line_dir.y))
{
const float rcp_dir = T(1) / line_dir.y;
const float t1 = (aabb.min.y - line_pos.y) * rcp_dir;
const float t2 = (aabb.max.y - line_pos.y) * rcp_dir;
if (t1 < t2)
d_near = math::max(t1, d_near), d_far = math::min(t2, d_far);
else // Swap t1 and t2.
d_near = math::max(t2, d_near), d_far = math::min(t1, d_far);
if (d_near > d_far)
return false; // Box is missed since we "exit" before entering it.
}
else if (line_pos.y < aabb.min.y || line_pos.y > aabb.max.y)
return false; // The ray can't possibly enter the box, abort.
return d_near <= d_far;
}
/// Computes the closest point pair on two lines.
/** The first line is specified by two points start0 and end0. The second line is specified by
two points start1 and end1.
The implementation of this function follows http://paulbourke.net/geometry/lineline3d/ .
@param v0 The starting point of the first line.
@param v10 The direction vector of the first line. This can be unnormalized.
@param v2 The starting point of the second line.
@param v32 The direction vector of the second line. This can be unnormalized.
@param d [out] Receives the normalized distance of the closest point along the first line.
@param d2 [out] Receives the normalized distance of the closest point along the second line.
@return Returns the closest point on line start0<->end0 to the second line.
@note This is a low-level utility function. You probably want to use ClosestPoint() or Distance() instead.
@see ClosestPoint(), Distance(). */
template<typename T>
constexpr void closest_point_line_line(const vec3<T>& a_pos, const vec3<T>& a_dir, const vec3<T>& b_pos, const vec3<T>& b_dir, float& a_d, float& b_d) noexcept
{
TL_PLAIN_ASSERT(!is_zero(a_dir));
TL_PLAIN_ASSERT(!is_zero(b_dir));
const vec3<T> v02 = a_pos - b_pos;
const T d0232 = dot(v02, b_dir);
const T d3210 = dot(b_dir, a_dir);
const T d3232 = dot(b_dir, b_dir);
TL_PLAIN_ASSERT(!is_zero(d3232)); // Don't call with a zero direction vector.
const T d0210 = dot(v02, a_dir);
const T d1010 = dot(a_dir, a_dir);
const T denom = d1010 * d3232 - d3210 * d3210;
if (denom != T(0))
a_d = (d0232 * d3210 - d0210 * d3232) / denom;
else
a_d = T(0);
b_d = (d0232 + a_d * d3210) / d3232;
}
/** Calculates the intersection between a line and a triangle. The facing is not accounted for, so
rays are reported to intersect triangles that are both front and backfacing.
According to "T. M&ouml;ller, B. Trumbore. Fast, Minimum Storage Ray/Triangle Intersection. 2005."
http://jgt.akpeters.com/papers/MollerTrumbore97/
@param linePos The starting point of the line.
@param lineDir The direction vector of the line. This does not need to be normalized.
@param v0 Vertex 0 of the triangle.
@param v1 Vertex 1 of the triangle.
@param v2 Vertex 2 of the triangle.
@param u [out] The barycentric u coordinate is returned here if an intersection occurred.
@param v [out] The barycentric v coordinate is returned here if an intersection occurred.
@return The distance along the ray to the point of intersection, or +inf if no intersection occurred.
If no intersection, then u and v and t will contain undefined values. If lineDir was not normalized, then to get the
real world-space distance, one must scale the returned value with lineDir.Length(). If the returned value is negative,
then the intersection occurs 'behind' the line starting position, with respect to the direction vector lineDir. */
template<typename T>
constexpr bool do_intersect_line_tri(const vec3<T>& line_pos, const vec3<T>& line_dir,
const vec3<T>& v0, const vec3<T>& v1, const vec3<T>& v2,
T& line_d, T& tri_u, T& tri_v) noexcept
{
const T epsilon = tl::numeric_limits<T>::epsilon();
// Edge vectors
const vec3<T> vE1 = v1 - v0;
const vec3<T> vE2 = v2 - v0;
// begin calculating determinant - also used to calculate U parameter
const vec3<T> vP = cross(line_dir, vE2);
// If det < 0, intersecting backfacing, tri > 0, intersecting frontfacing, tri == 0, parallel to plane.
const T det = dot(vE1, vP);
// If determinant is near zero, ray lies in plane of triangle.
if (abs(det) <= epsilon) [[unlikely]]
return false;
const T inv_det = T(1) / det;
// Calculate distance from v0 to ray origin
const vec3<T> vT = line_pos - v0;
// Output barycentric tri_u
tri_u = dot(vT, vP) * inv_det;
if (tri_u < -epsilon || tri_u > T(1) + epsilon)
return false; // Barycentric U is outside the triangle - early out.
// Prepare to test V parameter
const vec3<T> vQ = cross(vT, vE1);
// Output barycentric v
tri_v = dot(line_dir, vQ) * inv_det;
if (tri_v < -epsilon || tri_u + tri_v > T(1) + epsilon) // Barycentric V or the combination of U and V are outside the triangle - no intersection.
return false;
// Barycentric u and v are in limits, the ray intersects the triangle.
// Output signed distance from ray to triangle.
line_d = dot(vE2, vQ) * inv_det;
return true;
}
}
template<typename T>
constexpr bool intersect_line_plane(const line3<T>& line, const plane<T>& plane, float& d) noexcept
{
const T b = math::dot(plane.normal, line.direction);
if (math::is_zero(b))
return false;
const math::vec3<T> v = line.origin - plane.get_member_point();
const T a = -math::dot(plane.normal, v);
d = a / b;
return true;
}
template<typename T>
constexpr bool intersect_line_aabb(const line2<T>& line, const aabb2<T>& aabb, float& d_near, float& d_far) noexcept
{
d_near = tl::numeric_limits<T>::lowest();
d_far = tl::numeric_limits<T>::max();
return detail::do_intersect_line_aabb(line.origin, line.direction, aabb, d_near, d_far);
}
template<typename T>
constexpr bool intersect_line_aabb(const line3<T>& line, const aabb3<T>& aabb, float& d_near, float& d_far) noexcept
{
d_near = tl::numeric_limits<T>::lowest();
d_far = tl::numeric_limits<T>::max();
return detail::do_intersect_line_aabb(line.origin, line.direction, aabb, d_near, d_far);
}
template<typename T>
constexpr bool intersect_ray_plane(const ray3<T>& line, const plane<T>& plane, float& d) noexcept
{
const T b = math::dot(plane.normal, line.direction);
if (math::is_zero(b))
return false;
const math::vec3<T> v = line.origin - plane.get_member_point();
const T a = -math::dot(plane.normal, v);
d = a / b;
return d >= T(0);
}
template<typename T>
constexpr bool intersect_ray_aabb(const ray2<T>& ray, const aabb2<T>& aabb, float& d_near, float& d_far) noexcept
{
d_near = 0;
d_far = tl::numeric_limits<T>::max();
return detail::do_intersect_line_aabb(ray.origin, ray.direction, aabb, d_near, d_far);
}
template<typename T>
constexpr bool intersect_ray_aabb(const ray3<T>& ray, const aabb3<T>& aabb, float& d_near, float& d_far) noexcept
{
d_near = 0;
d_far = tl::numeric_limits<T>::max();
return detail::do_intersect_line_aabb(ray.origin, ray.direction, aabb, d_near, d_far);
}
template<typename T>
constexpr bool intersect_segment_aabb(const segment2<T>& segment, const aabb2<T>& aabb, float& d_near, float& d_far) noexcept
{
d_near = 0;
d_far = segment.length();
const vec2<T> dir = (segment.end - segment.start) / d_far;
return detail::do_intersect_line_aabb(segment.start, dir, aabb, d_near, d_far);
}
template<typename T>
constexpr bool intersect_segment_aabb(const segment3<T>& segment, const aabb3<T>& aabb, float& d_near, float& d_far) noexcept
{
d_near = 0;
d_far = segment.length();
const vec3<T> dir = (segment.end - segment.start) / d_far;
return detail::do_intersect_line_aabb(segment.start, dir, aabb, d_near, d_far);
}
template<typename T>
constexpr bool intersect_point_segment(const math::vec3<T>& point, const segment3<T>& segment) noexcept
{
T d;
return intersect_point_segment(point, segment, d);
}
template<typename T>
constexpr bool intersect_point_segment(const math::vec3<T>& point, const segment3<T>& segment, float& d) noexcept
{
const T length = segment.length();
const vec3<T> dir = (segment.end - segment.start) / length;
d = dot(point - segment.start, dir);
return d >= 0 && d < length;
}
template<typename T>
constexpr bool intersect_line_triangle(const line3<T>& line, const triangle3<T>& triangle, float& line_d, vec2<T>& bari_coords) noexcept
{
return detail::do_intersect_line_tri(line.origin, line.direction, triangle.a, triangle.b, triangle.c, line_d, bari_coords.x, bari_coords.y);
}
template<typename T>
constexpr bool intersect_ray_triangle(const ray3<T>& ray, const triangle3<T>& triangle, float& ray_d, vec2<T>& bari_coords) noexcept
{
if (!detail::do_intersect_line_tri(ray.origin, ray.direction, triangle.a, triangle.b, triangle.c, ray_d, bari_coords.x, bari_coords.y))
return false;
if (ray_d < T(0))
return false;
return true;
}
template<typename T>
constexpr bool intersect_segment_triangle(const segment3<T>& segment, const triangle3<T>& triangle, float& segment_d, vec2<T>& bari_coords) noexcept
{
const T length = segment.length();
const vec3<T> dir = (segment.end - segment.start) / length;
if (!detail::do_intersect_line_tri(segment.start, dir, triangle.a, triangle.b, triangle.c, segment_d, bari_coords.x, bari_coords.y))
return false;
if (segment_d < T(0) || segment_d > length)
return false;
return true;
}
template<typename T>
constexpr math::segment3<T> closest_segment_between_lines(const math::line3<T>& a, const math::line3<T>& b) noexcept
{
T ad, bd;
detail::closest_point_line_line(a.origin, a.direction, b.origin, b.direction, ad, bd);
return { a.origin + a.direction * ad, b.origin + b.direction * bd };
}
template<typename T>
constexpr math::vec3<T> closest_point_to_line(const vec3<T>& point, const line3<T>& line) noexcept
{
const T d = dot(point - line.origin.start, line.direction);
return line.start + line.direction * d;
}
template<typename T>
constexpr math::vec3<T> closest_point_to_segment(const vec3<T>& point, const segment3<T>& segment) noexcept
{
const T length = segment.length();
const vec3<T> dir = (segment.end - segment.start) / length;
T d = dot(point - segment.start, dir);
d = clamp(d, T(0), length);
return segment.start + dir * d;
}
template<typename T>
constexpr math::vec3<T> closest_point_to_ray(const vec3<T>& point, const ray3<T>& ray) noexcept
{
T d = dot(point - ray.origin, ray.direction);
d = max(d, T(0));
return ray.origin + ray.direction * d;
}
}
+14
View File
@@ -0,0 +1,14 @@
#pragma once
namespace math
{
///! Creates a RH offseted orthographic projection matrix
template<typename T> constexpr mat4<T> ortho(T left, T right, T bottom, T top, T z_near, T z_far) noexcept;
///! Creates a RH perspective projection matrix
template<typename T> constexpr mat4<T> perspective(T fov, T aspect_ratio, T z_near, T z_far) noexcept;
///! Creates a RH asymmetric frustum projection matrix
template<typename T> constexpr mat4<T> perspective(T left, T right, T bottom, T top, T z_near, T z_far) noexcept;
}//namespace math
+105
View File
@@ -0,0 +1,105 @@
namespace math
{
///! Creates a RH orthographic projection matrix
template<typename T>
constexpr mat4<T> ortho(T left, T right, T bottom, T top, T z_near, T z_far) noexcept
{
mat4<T> mat;
T* M = mat.data();
M[0] = 2 / (right - left);
M[1] = 0;
M[2] = 0;
M[3] = 0;
M[4] = 0;
M[5] = 2 / (top - bottom);
M[6] = 0;
M[7] = 0;
M[8] = 0;
M[9] = 0;
M[10] = (T)(-2) / (z_far - z_near);
M[11] = 0;
M[12] = - (right + left) / (right - left);
M[13] = - (top + bottom) / (top - bottom);
M[14] = - (z_far + z_near) / (z_far - z_near);
M[15] = 1;
return mat;
}
///! Creates a RH perspective projection matrix
template<typename T>
constexpr mat4<T> perspective(T fov, T aspect_ratio, T z_near, T z_far) noexcept
{
T const y_fac = tan(fov / 2);
T const x_fac = y_fac*aspect_ratio;
mat4<T> mat;
T* M = mat.data();
M[0] = 1/x_fac;
M[1] = 0;
M[2] = 0;
M[3] = 0;
M[4] = 0;
M[5] = 1/y_fac;
M[6] = 0;
M[7] = 0;
M[8] = 0;
M[9] = 0;
M[10] = -(z_far+z_near)/(z_far-z_near);
M[11] = -1;
M[12] = 0;
M[13] = 0;
M[14] = -(2*z_far*z_near)/(z_far-z_near);
M[15] = 0;
return mat;
}
///! Creates a RH asymmetric frustum projection matrix
template<typename T>
constexpr mat4<T> perspective(T left, T right, T bottom, T top, T z_near, T z_far) noexcept
{
// glFrustum call (column order)
//
// | 2n/(r-l) 0 (r+l)/(r-l) 0 |
// | 0 2n/(t-b) (t+b)/(t-b) 0 |
// | 0 0 (n+f)/(n-f) (2nf)/(n-f) |
// | 0 0 -1 0 |
//
T diff_x = 1/(right-left);
T diff_y = 1/(top-bottom);
T diff_z = 1/(z_near-z_far);
mat4<T> mat;
T* m = mat.data();
m[ 0] = 2*z_near*diff_x;
m[ 1] = 0;
m[ 2] = 0;
m[ 3] = 0;
m[ 4] = 0;
m[ 5] = 2*z_near*diff_y;
m[ 6] = 0;
m[ 7] = 0;
m[ 8] = (right+left)*diff_x;
m[ 9] = (top+bottom)*diff_y;
m[10] = (z_far+z_near)*diff_z;
m[11] = -1;
m[12] = 0;
m[13] = 0;
m[14] = 2*z_near*z_far*diff_z;
m[15] = 0;
return mat;
}
}
+56
View File
@@ -0,0 +1,56 @@
#pragma once
namespace math
{
//min
template<typename T> constexpr vec2<T> min(vec2<T> const& a, vec2<T> const& b) noexcept;
template<typename T> constexpr vec3<T> min(vec3<T> const& a, vec3<T> const& b) noexcept;
template<typename T> constexpr vec4<T> min(vec4<T> const& a, vec4<T> const& b) noexcept;
template<typename T, typename Traits> constexpr clamped_value<T, Traits> min(clamped_value<T, Traits> const& a, clamped_value<T, Traits> const& b) noexcept;
template<typename T> constexpr T min(T a, T b) noexcept;
//max
template<typename T> constexpr vec2<T> max(vec2<T> const& a, vec2<T> const& b) noexcept;
template<typename T> constexpr vec3<T> max(vec3<T> const& a, vec3<T> const& b) noexcept;
template<typename T> constexpr vec4<T> max(vec4<T> const& a, vec4<T> const& b) noexcept;
template<typename T, typename Traits> constexpr clamped_value<T, Traits> max(clamped_value<T, Traits> const& a, clamped_value<T, Traits> const& b) noexcept;
template<typename T> constexpr T max(T a, T b) noexcept;
//clamping
template<typename T> constexpr vec2<T> clamp(vec2<T> const& x, vec2<T> const& min, vec2<T> const& max) noexcept;
template<typename T> constexpr vec3<T> clamp(vec3<T> const& x, vec3<T> const& min, vec3<T> const& max) noexcept;
template<typename T> constexpr vec4<T> clamp(vec4<T> const& x, vec4<T> const& min, vec4<T> const& max) noexcept;
template<typename T, typename Traits> constexpr clamped_value<T, Traits> clamp(clamped_value<T, Traits> const& x, clamped_value<T, Traits> const& min, clamped_value<T, Traits> const& max) noexcept;
template<typename T> constexpr T clamp(T x, T min, T max) noexcept;
//horizontal tests
namespace horiz
{
template<typename T> constexpr T min(vec2<T> const& a) noexcept;
template<typename T> constexpr T max(vec2<T> const& a) noexcept;
template<typename T> constexpr T min(vec3<T> const& a) noexcept;
template<typename T> constexpr T max(vec3<T> const& a) noexcept;
template<typename T> constexpr T min(vec4<T> const& a) noexcept;
template<typename T> constexpr T max(vec4<T> const& a) noexcept;
template<typename T> constexpr T min(quat<T> const& a) noexcept;
template<typename T> constexpr T max(quat<T> const& a) noexcept;
template<typename T> constexpr T min(mat2<T> const& a) noexcept;
template<typename T> constexpr T max(mat2<T> const& a) noexcept;
template<typename T> constexpr T min(mat3<T> const& a) noexcept;
template<typename T> constexpr T max(mat3<T> const& a) noexcept;
template<typename T> constexpr T min(mat4<T> const& a) noexcept;
template<typename T> constexpr T max(mat4<T> const& a) noexcept;
}
//rounding
template<typename T> T floor(T x) noexcept;
template<typename T> T ceil(T x) noexcept;
template<typename T> T fract(T x) noexcept;
//rounds to the closest integer
template<typename T> T round(T x) noexcept;
//round to decimal
template<typename T> T round(T x, uint8_t decimals) noexcept;
}
//#include "func_range.hpp"
+345
View File
@@ -0,0 +1,345 @@
#pragma once
namespace math
{
//////////////////////////////////////////////////////////////////////////
// scalars
namespace detail //unchecked min/max to use in clamp to avoid double checking
{
template<typename T> constexpr inline T min(T a, T b) noexcept
{
return a <= b ? a : b;
}
template<typename T> constexpr inline T max(T a, T b) noexcept
{
return a >= b ? a : b;
}
}
template<typename T> constexpr inline T min(T a, T b) noexcept
{
/*TL_PLAIN_ASSERT(is_finite(a) && is_finite(b));*/
return a <= b ? a : b;
}
template<typename T> constexpr inline T max(T a, T b) noexcept
{
/*TL_PLAIN_ASSERT(is_finite(a) && is_finite(b));*/
return a >= b ? a : b;
}
template<typename T> constexpr inline vec2<T> min(vec2<T> const& a, vec2<T> const& b) noexcept
{
/*TL_PLAIN_ASSERT(is_finite(a) && is_finite(b));*/
return vec2<T>(detail::min(a.x, b.x), detail::min(a.y, b.y));
}
template<typename T> constexpr inline vec3<T> min(vec3<T> const& a, vec3<T> const& b) noexcept
{
/*TL_PLAIN_ASSERT(is_finite(a) && is_finite(b));*/
return vec3<T>(detail::min(a.x, b.x), detail::min(a.y, b.y), detail::min(a.z, b.z));
}
template<typename T> constexpr inline vec4<T> min(vec4<T> const& a, vec4<T> const& b) noexcept
{
/*TL_PLAIN_ASSERT(is_finite(a) && is_finite(b));*/
return vec4<T>(detail::min(a.x, b.x), detail::min(a.y, b.y), detail::min(a.z, b.z), min(a.w, b.w));
}
template<typename T, typename Traits> constexpr inline clamped_value<T, Traits> min(clamped_value<T, Traits> const& a, clamped_value<T, Traits> const& b) noexcept
{
/*TL_PLAIN_ASSERT(is_finite(a) && is_finite(b));*/
return clamped_value<T, Traits>(detail::min(a.value(), b.value()));
}
template<typename T> constexpr inline vec2<T> max(vec2<T> const& a, vec2<T> const& b) noexcept
{
/*TL_PLAIN_ASSERT(is_finite(a) && is_finite(b));*/
return vec2<T>(detail::max(a.x, b.x), detail::max(a.y, b.y));
}
template<typename T> constexpr inline vec3<T> max(vec3<T> const& a, vec3<T> const& b) noexcept
{
/*TL_PLAIN_ASSERT(is_finite(a) && is_finite(b));*/
return vec3<T>(detail::max(a.x, b.x), detail::max(a.y, b.y), detail::max(a.z, b.z));
}
template<typename T> constexpr inline vec4<T> max(vec4<T> const& a, vec4<T> const& b) noexcept
{
/*TL_PLAIN_ASSERT(is_finite(a) && is_finite(b));*/
return vec4<T>(detail::max(a.x, b.x), detail::max(a.y, b.y), detail::max(a.z, b.z), detail::max(a.w, b.w));
}
template<typename T, typename Traits> constexpr inline clamped_value<T, Traits> max(clamped_value<T, Traits> const& a, clamped_value<T, Traits> const& b) noexcept
{
/*TL_PLAIN_ASSERT(is_finite(a) && is_finite(b));*/
return clamped_value<T, Traits>(detail::max(a.value(), b.value()));
}
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr inline T clamp(T x, T min, T max) noexcept
{
TL_PLAIN_ASSERT(is_finite(x)/* && is_finite(min) && is_finite(max)*/);
return detail::min(detail::max(x, min), max);
}
template<typename T> constexpr inline vec2<T> clamp(vec2<T> const& x, vec2<T> const& min, vec2<T> const& max) noexcept
{
return vec2<T>(clamp(x.x, min.x, max.x), clamp(x.y, min.y, max.y));
}
template<typename T> constexpr inline vec3<T> clamp(vec3<T> const& x, vec3<T> const& min, vec3<T> const& max) noexcept
{
return vec3<T>(clamp(x.x, min.x, max.x), clamp(x.y, min.y, max.y), clamp(x.z, min.z, max.z));
}
template<typename T> constexpr inline vec4<T> clamp(vec4<T> const& x, vec4<T> const& min, vec4<T> const& max) noexcept
{
return vec4<T>(clamp(x.x, min.x, max.x), clamp(x.y, min.y, max.y), clamp(x.z, min.z, max.z), clamp(x.w, min.w, max.w));
}
template<typename T, typename Traits> constexpr inline clamped_value<T, Traits> clamp(clamped_value<T, Traits> const& x, clamped_value<T, Traits> const& min, clamped_value<T, Traits> const& max) noexcept
{
return clamped_value<T, Traits>(clamp(x.value(), min.value(), max.value()));
}
//////////////////////////////////////////////////////////////////////////
namespace horiz
{
template<typename T> constexpr inline T min(vec2<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
return detail::min(a.x, a.y);
}
template<typename T> constexpr inline T max(vec2<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
return detail::max(a.x, a.y);
}
template<typename T> constexpr inline T min(vec3<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
return detail::min(detail::min(a.x, a.y), a.z);
}
template<typename T> constexpr inline T max(vec3<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
return detail::max(detail::max(a.x, a.y), a.z);
}
template<typename T> constexpr inline T min(vec4<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
return detail::min(detail::min(detail::min(a.x, a.y), a.z), a.w);
}
template<typename T> constexpr inline T max(vec4<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
return detail::max(detail::max(detail::max(a.x, a.y), a.z), a.w);
}
template<typename T> constexpr inline T min(quat<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
return detail::min(detail::min(detail::min(a.x, a.y), a.z), a.w);
}
template<typename T> constexpr inline T max(quat<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
return detail::max(detail::max(detail::max(a.x, a.y), a.z), a.w);
}
template<typename T> constexpr inline T min(mat2<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
T x = detail::min(a.m[0], a.m[1]);
x = detail::min(x, a.m[2]);
x = detail::min(x, a.m[3]);
return x;
}
template<typename T> constexpr inline T max(mat2<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
T x = detail::max(a.m[0], a.m[1]);
x = detail::max(x, a.m[2]);
x = detail::max(x, a.m[3]);
return x;
}
template<typename T> constexpr inline T min(mat3<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
T x = detail::min(a.m[0], a.m[1]);
for (size_t i = 2; i < a.element_count; i++)
x = detail::min(x, a.m[i]);
return x;
}
template<typename T> constexpr inline T max(mat3<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
T x = detail::max(a.m[0], a.m[1]);
for (size_t i = 2; i < a.element_count; i++)
x = detail::max(x, a.m[i]);
return x;
}
template<typename T> constexpr inline T min(mat4<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
T x = detail::min(a.m[0], a.m[1]);
for (size_t i = 2; i < a.element_count; i++)
x = detail::min(x, a.m[i]);
return x;
}
template<typename T> constexpr inline T max(mat4<T> const& a) noexcept
{
//TL_PLAIN_ASSERT(is_finite(a));
T x = detail::max(a.m[0], a.m[1]);
for (size_t i = 2; i < a.element_count; i++)
x = detail::max(x, a.m[i]);
return x;
}
}
//////////////////////////////////////////////////////////////////////////
template<typename T> inline T floor(T x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x));
return std::floor(x);
}
template<> inline float floor(float x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x));
return ::floorf(x);
}
template<typename T> constexpr inline vec2<T> floor(vec2<T> const& x) noexcept
{
return vec2<T>(floor(x.x), floor(x.y));
}
template<typename T> constexpr inline vec3<T> floor(vec3<T> const& x) noexcept
{
return vec3<T>(floor(x.x), floor(x.y), floor(x.z));
}
template<typename T> constexpr inline vec4<T> floor(vec4<T> const& x) noexcept
{
return vec4<T>(floor(x.x), floor(x.y), floor(x.z), floor(x.w));
}
template<typename T, typename Traits> constexpr inline clamped_value<T, Traits> floor(clamped_value<T, Traits> const& x) noexcept
{
return clamped_value<T, Traits>(floor(x.value()));
}
template<typename T> inline T ceil(T x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x));
return std::ceil(x);
}
template<> inline float ceil(float x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x));
return ceilf(x);
}
template<typename T> constexpr inline vec2<T> ceil(vec2<T> const& x) noexcept
{
return vec2<T>(ceil(x.x), ceil(x.y));
}
template<typename T> constexpr inline vec3<T> ceil(vec3<T> const& x) noexcept
{
return vec3<T>(ceil(x.x), ceil(x.y), ceil(x.z));
}
template<typename T> constexpr inline vec4<T> ceil(vec4<T> const& x) noexcept
{
return vec4<T>(ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w));
}
template<typename T, typename Traits> constexpr inline clamped_value<T, Traits> ceil(clamped_value<T, Traits> const& x) noexcept
{
return clamped_value<T, Traits>(ceil(x.value()));
}
template<typename T> inline T fract(T x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x));
return x - floor(x);
}
template<typename T> constexpr inline vec2<T> fract(vec2<T> const& x) noexcept
{
return vec2<T>(fract(x.x), fract(x.y));
}
template<typename T> constexpr inline vec3<T> fract(vec3<T> const& x) noexcept
{
return vec3<T>(fract(x.x), fract(x.y), fract(x.z));
}
template<typename T> constexpr inline vec4<T> fract(vec4<T> const& x) noexcept
{
return vec4<T>(fract(x.x), fract(x.y), fract(x.z), fract(x.w));
}
template<typename T, typename Traits> constexpr inline clamped_value<T, Traits> fract(clamped_value<T, Traits> const& x) noexcept
{
return clamped_value<T, Traits>(fract(x.value));
}
//rounds to the closest integer
template<typename T> inline T round(T x) noexcept; //no implementation
//rounds to the closest integer
template<> inline float round(float x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x));
return floor(x + 0.5f);
}
template<> inline double round(double x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x));
return floor(x + 0.5);
}
template<typename T> constexpr inline vec2<T> round(vec2<T> const& x) noexcept
{
return vec2<T>(round(x.x), round(x.y));
}
template<typename T> constexpr inline vec3<T> round(vec3<T> const& x) noexcept
{
return vec3<T>(round(x.x), round(x.y), round(x.z));
}
template<typename T> constexpr inline vec4<T> round(vec4<T> const& x) noexcept
{
return vec4<T>(round(x.x), round(x.y), round(x.z), round(x.w));
}
template<typename T, typename Traits> constexpr inline clamped_value<T, Traits> round(clamped_value<T, Traits> const& x) noexcept
{
return clamped_value<T, Traits>(round(x.value()));
}
//rounds to the closest integer
template<typename T> inline T round(T x, uint8_t decimals) noexcept; //no implementation
//rounds to the closest integer
template<> inline float round(float x, uint8_t decimals) noexcept
{
TL_PLAIN_ASSERT(is_finite(x));
const float ix = floor(x);
const float frac = x - ix;
const float p = ::powf(10.f, (float)decimals);
float f = floor(round(frac * p));
f /= p;
return ix + f;
}
template<> inline double round(double x, uint8_t decimals) noexcept
{
TL_PLAIN_ASSERT(is_finite(x));
const double ix = floor(x);
const double frac = x - ix;
const double p = ::pow(10.0, (double)decimals);
double f = floor(round(frac * p));
f /= p;
return ix + f;
}
template<typename T> constexpr inline vec2<T> round(vec2<T> const& x, uint8_t decimals) noexcept
{
return vec2<T>(round(x.x, decimals), round(x.y, decimals));
}
template<typename T> constexpr inline vec3<T> round(vec3<T> const& x, uint8_t decimals) noexcept
{
return vec3<T>(round(x.x, decimals), round(x.y, decimals), round(x.z, decimals));
}
template<typename T> constexpr inline vec4<T> round(vec4<T> const& x, uint8_t decimals) noexcept
{
return vec4<T>(round(x.x, decimals), round(x.y, decimals), round(x.z, decimals), round(x.w, decimals));
}
template<typename T, typename Traits> constexpr inline clamped_value<T, Traits> round(clamped_value<T, Traits> const& x, uint8_t decimals) noexcept
{
return clamped_value<T, Traits>(round(x.value(), decimals));
}
}
+85
View File
@@ -0,0 +1,85 @@
#pragma once
#include "tl/format.h"
template<typename T>
struct std::formatter<math::vec2<T>>
{
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
auto format(const math::vec2<T>& v, std::format_context& ctx) const noexcept
{
return format_to(ctx.out(), "{},{}", v.x, v.y);
}
};
template<typename T>
struct std::formatter<math::vec3<T>>
{
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
auto format(const math::vec3<T>& v, std::format_context& ctx) const noexcept
{
return format_to(ctx.out(), "{},{},{}", v.x, v.y, v.z);
}
};
template<typename T>
struct std::formatter<math::vec4<T>>
{
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
auto format(const math::vec4<T>& v, std::format_context& ctx) const noexcept
{
return format_to(ctx.out(), "{},{},{},{}", v.x, v.y, v.z, v.w);
}
};
template<typename T>
struct std::formatter<math::quat<T>>
{
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
auto format(const math::quat<T>& v, std::format_context& ctx) const noexcept
{
return format_to(ctx.out(), "{},{},{},{}", v.x, v.y, v.z, v.w);
}
};
template<typename T>
struct std::formatter<math::mat2<T>>
{
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
auto format(const math::mat2<T>& v, std::format_context& ctx) const noexcept
{
return format_to(ctx.out(), "[{}][{}]", v.get_column(0), v.get_column(1));
}
};
template<typename T>
struct std::formatter<math::mat3<T>>
{
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
auto format(const math::mat3<T>& v, std::format_context& ctx) const noexcept
{
return format_to(ctx.out(), "[{}][{}][{}]", v.get_column(0), v.get_column(1), v.get_column(2));
}
};
template<typename T>
struct std::formatter<math::mat4<T>>
{
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
auto format(const math::mat4<T>& v, std::format_context& ctx) const noexcept
{
return format_to(ctx.out(), "[{}][{}][{}][{}]", v.get_column(0), v.get_column(1), v.get_column(2), v.get_column(3));
}
};
template<typename T>
struct std::formatter<math::trans2<T>>
{
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
auto format(const math::trans2<T>& v, std::format_context& ctx) const noexcept
{
return format_to(ctx.out(), "[{}][{}][{}]", v.get_axis_x(), v.get_axis_y(), v.get_translation());
}
};
template<typename T>
struct std::formatter<math::trans3<T>>
{
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
auto format(const math::trans3<T>& v, std::format_context& ctx) const noexcept
{
return format_to(ctx.out(), "[{}][{}][{}][{}]", v.get_axis_x(), v.get_axis_y(), v.get_axis_z(), v.get_translation());
}
};
+322
View File
@@ -0,0 +1,322 @@
#pragma once
#include <tl/numeric_limits.h>
namespace math
{
template<typename T> inline bool is_equal(T v1, T v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<> inline bool is_equal(float v1, float v2, float tolerance) noexcept;
template<typename T> inline bool is_equal(angle<T> const& v1, angle<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline bool is_equal(vec2<T> const& v1, vec2<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline bool is_equal(vec3<T> const& v1, vec3<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline bool is_equal(vec4<T> const& v1, vec4<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline bool is_equal(quat<T> const& v1, quat<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline bool is_equal(mat2<T> const& v1, mat2<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline bool is_equal(mat3<T> const& v1, mat3<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline bool is_equal(mat4<T> const& v1, mat4<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline bool is_equal(trans3<T> const& v1, trans3<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline bool is_equal(trans2<T> const& v1, trans2<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline bool is_equal(rigid3<T> const& v1, rigid3<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline bool is_equal(rigid2<T> const& v1, rigid2<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr bool is_less(T v1, T v2) noexcept;
template<typename T> constexpr bool is_less(angle<T> const& v1, angle<T> const& v2) noexcept;
template<typename T> constexpr bool is_less(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T> constexpr bool is_less(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T> constexpr bool is_less(vec4<T> const& v1, vec4<T> const& v2) noexcept;
template<typename T> constexpr bool is_less(quat<T> const& v1, quat<T> const& v2) noexcept;
template<typename T> constexpr bool is_less(mat2<T> const& v1, mat2<T> const& v2) noexcept;
template<typename T> constexpr bool is_less(mat3<T> const& v1, mat3<T> const& v2) noexcept;
template<typename T> constexpr bool is_less(mat4<T> const& v1, mat4<T> const& v2) noexcept;
template<typename T> constexpr bool is_less(trans3<T> const& v1, trans3<T> const& v2) noexcept;
template<typename T> constexpr bool is_less(trans2<T> const& v1, trans2<T> const& v2) noexcept;
template<typename T> constexpr bool is_less(rigid3<T> const& v1, rigid3<T> const& v2) noexcept;
template<typename T> constexpr bool is_less(rigid2<T> const& v1, rigid2<T> const& v2) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr bool is_lequal(T v1, T v2) noexcept;
template<typename T> constexpr bool is_lequal(angle<T> const& v1, angle<T> const& v2) noexcept;
template<typename T> constexpr bool is_lequal(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T> constexpr bool is_lequal(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T> constexpr bool is_lequal(vec4<T> const& v1, vec4<T> const& v2) noexcept;
template<typename T> constexpr bool is_lequal(quat<T> const& v1, quat<T> const& v2) noexcept;
template<typename T> constexpr bool is_lequal(mat2<T> const& v1, mat2<T> const& v2) noexcept;
template<typename T> constexpr bool is_lequal(mat3<T> const& v1, mat3<T> const& v2) noexcept;
template<typename T> constexpr bool is_lequal(mat4<T> const& v1, mat4<T> const& v2) noexcept;
template<typename T> constexpr bool is_lequal(trans3<T> const& v1, trans3<T> const& v2) noexcept;
template<typename T> constexpr bool is_lequal(trans2<T> const& v1, trans2<T> const& v2) noexcept;
template<typename T> constexpr bool is_lequal(rigid3<T> const& v1, rigid3<T> const& v2) noexcept;
template<typename T> constexpr bool is_lequal(rigid2<T> const& v1, rigid2<T> const& v2) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr bool is_greater(T v1, T v2) noexcept;
template<typename T> constexpr bool is_greater(angle<T> const& v1, angle<T> const& v2) noexcept;
template<typename T> constexpr bool is_greater(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T> constexpr bool is_greater(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T> constexpr bool is_greater(vec4<T> const& v1, vec4<T> const& v2) noexcept;
template<typename T> constexpr bool is_greater(quat<T> const& v1, quat<T> const& v2) noexcept;
template<typename T> constexpr bool is_greater(mat2<T> const& v1, mat2<T> const& v2) noexcept;
template<typename T> constexpr bool is_greater(mat3<T> const& v1, mat3<T> const& v2) noexcept;
template<typename T> constexpr bool is_greater(mat4<T> const& v1, mat4<T> const& v2) noexcept;
template<typename T> constexpr bool is_greater(trans3<T> const& v1, trans3<T> const& v2) noexcept;
template<typename T> constexpr bool is_greater(trans2<T> const& v1, trans2<T> const& v2) noexcept;
template<typename T> constexpr bool is_greater(rigid3<T> const& v1, rigid3<T> const& v2) noexcept;
template<typename T> constexpr bool is_greater(rigid2<T> const& v1, rigid2<T> const& v2) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr bool is_gequal(T v1, T v2) noexcept;
template<typename T> constexpr bool is_gequal(angle<T> const& v1, angle<T> const& v2) noexcept;
template<typename T> constexpr bool is_gequal(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T> constexpr bool is_gequal(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T> constexpr bool is_gequal(vec4<T> const& v1, vec4<T> const& v2) noexcept;
template<typename T> constexpr bool is_gequal(quat<T> const& v1, quat<T> const& v2) noexcept;
template<typename T> constexpr bool is_gequal(mat2<T> const& v1, mat2<T> const& v2) noexcept;
template<typename T> constexpr bool is_gequal(mat3<T> const& v1, mat3<T> const& v2) noexcept;
template<typename T> constexpr bool is_gequal(mat4<T> const& v1, mat4<T> const& v2) noexcept;
template<typename T> constexpr bool is_gequal(trans3<T> const& v1, trans3<T> const& v2) noexcept;
template<typename T> constexpr bool is_gequal(trans2<T> const& v1, trans2<T> const& v2) noexcept;
template<typename T> constexpr bool is_gequal(rigid3<T> const& v1, rigid3<T> const& v2) noexcept;
template<typename T> constexpr bool is_gequal(rigid2<T> const& v1, rigid2<T> const& v2) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr bool is_zero(T v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(angle<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(vec2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(vec3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(vec4<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(quat<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(mat2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(mat3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(mat4<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(trans3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(trans2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(rigid3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_zero(rigid2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr bool is_one(T v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_one(vec2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_one(vec3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_one(vec4<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_one(quat<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_one(mat2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_one(mat3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_one(mat4<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_one(trans3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_one(trans2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_one(rigid3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_one(rigid2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> inline bool is_positive(T v) noexcept;
template<> inline bool is_positive(float v) noexcept;
template<> inline bool is_positive(uint8_t v) noexcept;
template<> inline bool is_positive(uint16_t v) noexcept;
template<> inline bool is_positive(uint32_t v) noexcept;
template<> inline bool is_positive(uint64_t v) noexcept;
template<typename T> inline bool is_positive(angle<T> const& v) noexcept;
template<typename T> inline bool is_positive(vec2<T> const& v) noexcept;
template<typename T> inline bool is_positive(vec3<T> const& v) noexcept;
template<typename T> inline bool is_positive(vec4<T> const& v) noexcept;
template<typename T> inline bool is_positive(quat<T> const& v) noexcept;
template<typename T> inline bool is_positive(mat2<T> const& v) noexcept;
template<typename T> inline bool is_positive(mat3<T> const& v) noexcept;
template<typename T> inline bool is_positive(mat4<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> inline bool is_negative(T v) noexcept;
template<> inline bool is_negative(float v) noexcept;
template<> inline bool is_negative(float v) noexcept;
template<> inline bool is_negative(uint8_t v) noexcept;
template<> inline bool is_negative(uint16_t v) noexcept;
template<> inline bool is_negative(uint32_t v) noexcept;
template<> inline bool is_negative(uint64_t v) noexcept;
template<typename T> inline bool is_negative(angle<T> const& v) noexcept;
template<typename T> inline bool is_negative(vec2<T> const& v) noexcept;
template<typename T> inline bool is_negative(vec3<T> const& v) noexcept;
template<typename T> inline bool is_negative(vec4<T> const& v) noexcept;
template<typename T> inline bool is_negative(quat<T> const& v) noexcept;
template<typename T> inline bool is_negative(mat2<T> const& v) noexcept;
template<typename T> inline bool is_negative(mat3<T> const& v) noexcept;
template<typename T> inline bool is_negative(mat4<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
constexpr bool is_nan(float f) noexcept;
constexpr bool is_nan(double d) noexcept;
template<typename T> constexpr bool is_nan(T) noexcept;
template<typename T> constexpr bool is_nan(angle<T> const& v) noexcept;
template<typename T> constexpr bool is_nan(vec2<T> const& v) noexcept;
template<typename T> constexpr bool is_nan(vec3<T> const& v) noexcept;
template<typename T> constexpr bool is_nan(vec4<T> const& v) noexcept;
template<typename T> constexpr bool is_nan(quat<T> const& v) noexcept;
template<typename T> constexpr bool is_nan(mat2<T> const& v) noexcept;
template<typename T> constexpr bool is_nan(mat3<T> const& v) noexcept;
template<typename T> constexpr bool is_nan(mat4<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
constexpr bool is_infinite(float f) noexcept;
constexpr bool is_infinite(double d) noexcept;
template<typename T> constexpr bool is_infinite(T) noexcept;
template<typename T> constexpr bool is_infinite(angle<T> const& v) noexcept;
template<typename T> constexpr bool is_infinite(vec2<T> const& v) noexcept;
template<typename T> constexpr bool is_infinite(vec3<T> const& v) noexcept;
template<typename T> constexpr bool is_infinite(vec4<T> const& v) noexcept;
template<typename T> constexpr bool is_infinite(quat<T> const& v) noexcept;
template<typename T> constexpr bool is_infinite(mat2<T> const& v) noexcept;
template<typename T> constexpr bool is_infinite(mat3<T> const& v) noexcept;
template<typename T> constexpr bool is_infinite(mat4<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
constexpr bool is_finite(float f) noexcept;
constexpr bool is_finite(double d) noexcept;
template<typename T> constexpr bool is_finite(T) noexcept;
template<typename T> constexpr bool is_finite(angle<T> const& v) noexcept;
template<typename T> constexpr bool is_finite(vec2<T> const& v) noexcept;
template<typename T> constexpr bool is_finite(vec3<T> const& v) noexcept;
template<typename T> constexpr bool is_finite(vec4<T> const& v) noexcept;
template<typename T> constexpr bool is_finite(quat<T> const& v) noexcept;
template<typename T> constexpr bool is_finite(mat2<T> const& v) noexcept;
template<typename T> constexpr bool is_finite(mat3<T> const& v) noexcept;
template<typename T> constexpr bool is_finite(mat4<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr bool is_identity(mat2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_identity(mat3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_identity(mat4<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_identity(quat<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_identity(trans3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_identity(trans2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_identity(rigid3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_identity(rigid2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr bool is_normalized(vec2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_normalized(vec3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_normalized(vec4<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr bool is_normalized(quat<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
//////////////////////////////////////////////////////////////////////////
namespace cwise
{
template<typename T> inline vec2<bool> is_equal(vec2<T> const& v1, vec2<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline vec3<bool> is_equal(vec3<T> const& v1, vec3<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline vec4<bool> is_equal(vec4<T> const& v1, vec4<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> inline vec4<bool> is_equal(quat<T> const& v1, quat<T> const& v2, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<> inline vec2<bool> is_equal(vec2<float> const& v1, vec2<float> const& v2, float tolerance) noexcept;
template<> inline vec3<bool> is_equal(vec3<float> const& v1, vec3<float> const& v2, float tolerance) noexcept;
template<> inline vec4<bool> is_equal(vec4<float> const& v1, vec4<float> const& v2, float tolerance) noexcept;
template<> inline vec4<bool> is_equal(quat<float> const& v1, quat<float> const& v2, float tolerance) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<bool> is_less(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T> constexpr vec3<bool> is_less(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T> constexpr vec4<bool> is_less(vec4<T> const& v1, vec4<T> const& v2) noexcept;
template<typename T> constexpr vec4<bool> is_less(quat<T> const& v1, quat<T> const& v2) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<bool> is_lequal(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T> constexpr vec3<bool> is_lequal(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T> constexpr vec4<bool> is_lequal(vec4<T> const& v1, vec4<T> const& v2) noexcept;
template<typename T> constexpr vec4<bool> is_lequal(quat<T> const& v1, quat<T> const& v2) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<bool> is_greater(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T> constexpr vec3<bool> is_greater(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T> constexpr vec4<bool> is_greater(vec4<T> const& v1, vec4<T> const& v2) noexcept;
template<typename T> constexpr vec4<bool> is_greater(quat<T> const& v1, quat<T> const& v2) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<bool> is_gequal(vec2<T> const& v1, vec2<T> const& v2) noexcept;
template<typename T> constexpr vec3<bool> is_gequal(vec3<T> const& v1, vec3<T> const& v2) noexcept;
template<typename T> constexpr vec4<bool> is_gequal(vec4<T> const& v1, vec4<T> const& v2) noexcept;
template<typename T> constexpr vec4<bool> is_gequal(quat<T> const& v1, quat<T> const& v2) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<bool> is_zero(vec2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr vec3<bool> is_zero(vec3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr vec4<bool> is_zero(vec4<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr vec4<bool> is_zero(quat<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<bool> is_one(vec2<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr vec3<bool> is_one(vec3<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr vec4<bool> is_one(vec4<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
template<typename T> constexpr vec4<bool> is_one(quat<T> const& v, T tolerance = tl::numeric_limits<T>::epsilon()) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<bool> is_positive(vec2<T> const& v) noexcept;
template<typename T> constexpr vec3<bool> is_positive(vec3<T> const& v) noexcept;
template<typename T> constexpr vec4<bool> is_positive(vec4<T> const& v) noexcept;
template<typename T> constexpr vec4<bool> is_positive(quat<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<bool> is_negative(vec2<T> const& v) noexcept;
template<typename T> constexpr vec3<bool> is_negative(vec3<T> const& v) noexcept;
template<typename T> constexpr vec4<bool> is_negative(vec4<T> const& v) noexcept;
template<typename T> constexpr vec4<bool> is_negative(quat<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<bool> is_nan(vec2<T> const& v) noexcept;
template<typename T> constexpr vec3<bool> is_nan(vec3<T> const& v) noexcept;
template<typename T> constexpr vec4<bool> is_nan(vec4<T> const& v) noexcept;
template<typename T> constexpr vec4<bool> is_nan(quat<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<bool> is_infinite(vec2<T> const& v) noexcept;
template<typename T> constexpr vec3<bool> is_infinite(vec3<T> const& v) noexcept;
template<typename T> constexpr vec4<bool> is_infinite(vec4<T> const& v) noexcept;
template<typename T> constexpr vec4<bool> is_infinite(quat<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<bool> is_finite(vec2<T> const& v) noexcept;
template<typename T> constexpr vec3<bool> is_finite(vec3<T> const& v) noexcept;
template<typename T> constexpr vec4<bool> is_finite(vec4<T> const& v) noexcept;
template<typename T> constexpr vec4<bool> is_finite(quat<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
constexpr bool all(vec2<bool> const& v) noexcept;
constexpr bool all(vec3<bool> const& v) noexcept;
constexpr bool all(vec4<bool> const& v) noexcept;
constexpr bool any(vec2<bool> const& v) noexcept;
constexpr bool any(vec3<bool> const& v) noexcept;
constexpr bool any(vec4<bool> const& v) noexcept;
constexpr bool none(vec2<bool> const& v) noexcept;
constexpr bool none(vec3<bool> const& v) noexcept;
constexpr bool none(vec4<bool> const& v) noexcept;
} //cwise
}
File diff suppressed because it is too large Load Diff
+173
View File
@@ -0,0 +1,173 @@
namespace math
{
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr mat2<T>& multiply(mat2<T>& result, mat2<T> const& a, mat2<T> const& b) noexcept;
template<typename T> constexpr mat3<T>& multiply(mat3<T>& result, mat3<T> const& a, mat3<T> const& b) noexcept;
template<typename T> constexpr mat4<T>& multiply(mat4<T>& result, mat4<T> const& a, mat4<T> const& b) noexcept;
#if defined(MATH_USE_SIMD)
template<> mat4<float>& multiply(mat4<float>& result, mat4<float> const& a, mat4<float> const& b) noexcept;
#endif
template<typename T> constexpr trans2<T>& multiply(trans2<T>& result, trans2<T> const& a, trans2<T> const& b) noexcept;
template<typename T> constexpr trans3<T>& multiply(trans3<T>& result, trans3<T> const& a, trans3<T> const& b) noexcept;
template<typename T> constexpr rigid2<T>& multiply(rigid2<T>& result, rigid2<T> const& a, rigid2<T> const& b) noexcept;
template<typename T> constexpr rigid3<T>& multiply(rigid3<T>& result, rigid3<T> const& a, rigid3<T> const& b) noexcept;
//////////////////////////////////////////////////////////////////////////
namespace cwise
{
template<typename T> constexpr mat4<T>& multiply(mat4<T>& result, mat4<T> const& a, mat4<T> const& b) noexcept;
template<typename T> constexpr mat4<T>& add(mat4<T>& result, mat4<T> const& a, mat4<T> const& b) noexcept;
template<typename T> constexpr mat4<T>& substract(mat4<T>& result, mat4<T> const& a, mat4<T> const& b) noexcept;
template<typename T> constexpr mat4<T>& multiply(mat4<T>& result, mat4<T> const& a, T b) noexcept;
template<typename T> constexpr mat4<T>& add(mat4<T>& result, mat4<T> const& a, T b) noexcept;
template<typename T> constexpr mat4<T>& substract(mat4<T>& result, mat4<T> const& a, T b) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr mat3<T>& multiply(mat3<T>& result, mat3<T> const& a, mat3<T> const& b) noexcept;
template<typename T> constexpr mat3<T>& add(mat3<T>& result, mat3<T> const& a, mat3<T> const& b) noexcept;
template<typename T> constexpr mat3<T>& substract(mat3<T>& result, mat3<T> const& a, mat3<T> const& b) noexcept;
template<typename T> constexpr mat3<T>& multiply(mat3<T>& result, mat3<T> const& a, T b) noexcept;
template<typename T> constexpr mat3<T>& add(mat3<T>& result, mat3<T> const& a, T b) noexcept;
template<typename T> constexpr mat3<T>& substract(mat3<T>& result, mat3<T> const& a, T b) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr mat2<T>& multiply(mat2<T>& result, mat2<T> const& a, mat2<T> const& b) noexcept;
template<typename T> constexpr mat2<T>& add(mat2<T>& result, mat2<T> const& a, mat2<T> const& b) noexcept;
template<typename T> constexpr mat2<T>& substract(mat2<T>& result, mat2<T> const& a, mat2<T> const& b) noexcept;
template<typename T> constexpr mat2<T>& multiply(mat2<T>& result, mat2<T> const& a, T b) noexcept;
template<typename T> constexpr mat2<T>& add(mat2<T>& result, mat2<T> const& a, T b) noexcept;
template<typename T> constexpr mat2<T>& substract(mat2<T>& result, mat2<T> const& a, T b) noexcept;
} //cwise
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec2<T> transform(mat2<T> const& mat, vec2<T> const& v) noexcept;
template<typename T> constexpr vec2<T> transform(mat3<T> const& mat, vec2<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr vec2<T> transform(rigid2<T> const& trans, vec2<T> const& v) noexcept;
template<typename T> constexpr vec2<T> transform(trans2<T> const& t, vec2<T> const& v) noexcept;
template<typename T> constexpr vec2<T> rotate(mat2<T> const& mat, vec2<T> const& v) noexcept;
template<typename T> constexpr vec2<T> rotate(mat3<T> const& mat, vec2<T> const& v) noexcept;
template<typename T> constexpr vec2<T> rotate(rigid2<T> const& trans, vec2<T> const& v) noexcept;
template<typename T, class Policy = standard> constexpr vec2<T> rotate(T rotation, vec2<T> const& v) noexcept;
template<typename T> constexpr vec2<T> rotate(trans2<T> const& t, vec2<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec3<T> transform(mat3<T> const& mat, vec3<T> const& v) noexcept;
#if defined(MATH_USE_SIMD)
template<> vec3<float> transform(const mat4<float>& mat, const vec3<float>& vect) noexcept;
#endif
template<typename T> constexpr vec3<T> transform(mat4<T> const& mat, vec3<T> const& v) noexcept;
template<typename T> constexpr vec3<T> transform(rigid3<T> const& trans, vec3<T> const& v) noexcept;
template<typename T> constexpr vec3<T> transform(trans3<T> const& trans, vec3<T> const& v) noexcept;
template<typename T> constexpr vec3<T> rotate(mat3<T> const& mat, vec3<T> const& v) noexcept;
template<typename T> constexpr vec3<T> rotate(mat4<T> const& mat, vec3<T> const& v) noexcept;
template<typename T> constexpr vec3<T> rotate(rigid3<T> const& trans, vec3<T> const& v) noexcept;
template<typename T> constexpr vec3<T> rotate(trans3<T> const& m, vec3<T> const& v) noexcept;
template<typename T> constexpr vec3<T> rotate(quat<T> const& q, vec3<T> const& v) noexcept;
template<typename T> constexpr vec3<T> project(mat4<T> const& m, vec3<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr vec4<T> transform(mat4<T> const& mat, vec4<T> const& v) noexcept;
#if defined(MATH_USE_SIMD)
template<> vec4<float> transform(const mat4<float>& mat, const vec4<float>& vect) noexcept;
#endif
template<typename T> constexpr vec4<T> project(mat4<T> const& m, vec4<T> const& v) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr ray2<T> transform(mat2<T> const& mat, ray2<T> const& ray) noexcept;
template<typename T> constexpr ray2<T> transform(mat3<T> const& mat, ray2<T> const& ray) noexcept;
template<typename T> constexpr ray2<T> transform(rigid2<T> const& trans, ray2<T> const& ray) noexcept;
template<typename T> constexpr ray2<T> transform(trans2<T> const& trans, ray2<T> const& ray) noexcept;
template<typename T> constexpr segment2<T> transform(mat2<T> const& mat, segment2<T> const& segment) noexcept;
template<typename T> constexpr segment2<T> transform(mat3<T> const& mat, segment2<T> const& segment) noexcept;
template<typename T> constexpr segment2<T> transform(rigid2<T> const& trans, segment2<T> const& segment) noexcept;
template<typename T> constexpr segment2<T> transform(trans2<T> const& trans, segment2<T> const& segment) noexcept;
template<typename T> constexpr ray2<T> rotate(mat2<T> const& mat, ray2<T> const& ray) noexcept;
template<typename T> constexpr ray2<T> rotate(mat3<T> const& mat, ray2<T> const& ray) noexcept;
template<typename T> constexpr ray2<T> rotate(rigid2<T> const& trans, ray2<T> const& ray) noexcept;
template<typename T> constexpr ray2<T> rotate(trans2<T> const& trans, ray2<T> const& ray) noexcept;
template<typename T> constexpr ray3<T> transform(mat3<T> const& mat, ray3<T> const& ray) noexcept;
template<typename T> constexpr ray3<T> transform(mat4<T> const& mat, ray3<T> const& ray) noexcept;
template<typename T> constexpr ray3<T> transform(rigid3<T> const& trans, ray3<T> const& ray) noexcept;
template<typename T> constexpr ray3<T> transform(trans3<T> const& trans, ray3<T> const& ray) noexcept;
template<typename T> constexpr segment3<T> transform(mat3<T> const& mat, segment3<T> const& segment) noexcept;
template<typename T> constexpr segment3<T> transform(mat4<T> const& mat, segment3<T> const& segment) noexcept;
template<typename T> constexpr segment3<T> transform(rigid3<T> const& trans, segment3<T> const& segment) noexcept;
template<typename T> constexpr segment3<T> transform(trans3<T> const& trans, segment3<T> const& segment) noexcept;
template<typename T> constexpr ray3<T> rotate(mat3<T> const& mat, ray3<T> const& ray) noexcept;
template<typename T> constexpr ray3<T> rotate(mat4<T> const& mat, ray3<T> const& ray) noexcept;
template<typename T> constexpr ray3<T> rotate(trans3<T> const& trans, ray3<T> const& ray) noexcept;
template<typename T> constexpr ray3<T> rotate(rigid3<T> const& trans, ray3<T> const& ray) noexcept;
//////////////////////////////////////////////////////////////////////////
/// aabbN transforms
//////////////////////////////////////////////////////////////////////////
template<typename T> constexpr aabb2<T> transform(mat3<T> const& trans, aabb2<T> const& box) noexcept;
template<typename T> constexpr aabb2<T> transform(trans2<T> const& trans, aabb2<T> const& box) noexcept;
template<typename T> constexpr aabb2<T> transform(rigid2<T> const& trans, aabb2<T> const& box) noexcept;
template<typename T> constexpr rect<T> transform(mat3<T> const& trans, rect<T> const& rect) noexcept;
template<typename T> constexpr rect<T> transform(trans2<T> const& trans, rect<T> const& rect) noexcept;
template<typename T> constexpr rect<T> transform(rigid2<T> const& trans, rect<T> const& rect) noexcept;
template<typename T> constexpr aabb2<T> rotate(mat2<T> const& m, aabb2<T> const& box) noexcept;
template<typename T> constexpr aabb2<T> rotate(mat3<T> const& m, aabb2<T> const& box) noexcept;
template<typename T> constexpr aabb2<T> rotate(rigid2<T> const& trans, aabb2<T> const& box) noexcept;
template<typename T> constexpr aabb2<T> rotate(trans2<T> const& trans, aabb2<T> const& box) noexcept;
template<typename T> constexpr rect<T> rotate(mat2<T> const& m, rect<T> const& box) noexcept;
template<typename T> constexpr rect<T> rotate(mat3<T> const& m, rect<T> const& box) noexcept;
template<typename T> constexpr rect<T> rotate(rigid2<T> const& trans, rect<T> const& box) noexcept;
template<typename T> constexpr rect<T> rotate(trans2<T> const& trans, rect<T> const& box) noexcept;
template<typename T> constexpr aabb3<T> transform(mat4<T> const& m, aabb3<T> const& box) noexcept;
template<typename T> constexpr aabb3<T> transform(rigid3<T> const& trans, aabb3<T> const& box) noexcept;
template<typename T> constexpr aabb3<T> transform(trans3<T> const& trans, aabb3<T> const& box) noexcept;
template<typename T> constexpr aabb3<T> rotate(mat3<T> const& m, aabb3<T> const& box) noexcept;
template<typename T> constexpr aabb3<T> rotate(mat4<T> const& m, aabb3<T> const& box) noexcept;
template<typename T> constexpr aabb3<T> rotate(rigid3<T> const& trans, aabb3<T> const& box) noexcept;
template<typename T> constexpr aabb3<T> rotate(trans3<T> const& trans, aabb3<T> const& box) noexcept;
namespace batch
{
template<typename T> void transform(trans2<T> const& t, vec2<T>* dst, size_t dst_stride, vec2<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void rotate(trans2<T> const& t, vec2<T>* dst, size_t dst_stride, vec2<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void transform(trans3<T> const& t, vec3<T>* dst, size_t dst_stride, vec3<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void rotate(trans3<T> const& t, vec3<T>* dst, size_t dst_stride, vec3<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void transform(mat3<T> const& m, vec2<T>* dst, size_t dst_stride, vec2<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void rotate(mat3<T> const& m, vec2<T>* dst, size_t dst_stride, vec2<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void transform(mat3<T> const& m, vec3<T>* dst, size_t dst_stride, vec3<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void rotate(mat3<T> const& m, vec3<T>* dst, size_t dst_stride, vec3<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void transform(mat4<T> const& m, vec3<T>* dst, size_t dst_stride, vec3<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void rotate(mat4<T> const& m, vec3<T>* dst, size_t dst_stride, vec3<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void transform(mat4<T> const& m, vec4<T>* dst, size_t dst_stride, vec4<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void rotate(mat4<T> const& m, vec4<T>* dst, size_t dst_stride, vec4<T> const* src, size_t src_stride, size_t count) noexcept;
//////////////////////////////////////////////////////////////////////////
template<typename T> void multiply(mat4<T> const& m, mat4<T>* dst, size_t dst_stride, mat4<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void multiply(trans3<T> const& m, trans3<T>* dst, size_t dst_stride, trans3<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void multiply(mat3<T> const& m, mat3<T>* dst, size_t dst_stride, mat3<T> const* src, size_t src_stride, size_t count) noexcept;
template<typename T> void multiply(trans2<T> const& m, trans2<T>* dst, size_t dst_stride, trans2<T> const* src, size_t src_stride, size_t count) noexcept;
}
//////////////////////////////////////////////////////////////////////////
}
File diff suppressed because it is too large Load Diff
+54
View File
@@ -0,0 +1,54 @@
#pragma once
namespace math
{
template<typename T> constexpr T to_radians(T const& degrees) noexcept;
template<typename T> constexpr T to_degrees(T const& radians) noexcept;
//////////////////////////////////////////////////////////////////////////
//component wise trig for vectors.
//vec3 val = sin(angles) is equivalent to
// val.x = sin(angles.x)
// val.y = sin(angles.y)
// val.z = sin(angles.z)
template<typename T, class Policy = standard> /*constexpr*/ T cos(T const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec2<T> cos(vec2<T> const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec3<T> cos(vec3<T> const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec4<T> cos(vec4<T> const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ T sin(T const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec2<T> sin(vec2<T> const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec3<T> sin(vec3<T> const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec4<T> sin(vec4<T> const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ T tan(T const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec2<T> tan(vec2<T> const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec3<T> tan(vec3<T> const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec4<T> tan(vec4<T> const& angle) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ void sin_cos(T const& angle, T& sin, T& cos) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ void sin_cos(vec2<T> const& angle, vec2<T>& sin, vec2<T>& cos) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ void sin_cos(vec3<T> const& angle, vec3<T>& sin, vec3<T>& cos) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ void sin_cos(vec4<T> const& angle, vec4<T>& sin, vec4<T>& cos) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ T acos(T const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec2<T> acos(vec2<T> const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec3<T> acos(vec3<T> const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec4<T> acos(vec4<T> const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ T asin(T const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec2<T> asin(vec2<T> const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec3<T> asin(vec3<T> const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec4<T> asin(vec4<T> const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ T atan(T const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec2<T> atan(vec2<T> const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec3<T> atan(vec3<T> const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec4<T> atan(vec4<T> const& v) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ T atan2(T const& y, T const& x) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec2<T> atan2(vec2<T> const& y, vec2<T> const& x) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec3<T> atan2(vec3<T> const& y, vec3<T> const& x) noexcept;
template<typename T, class Policy = standard> /*constexpr*/ vec4<T> atan2(vec4<T> const& y, vec4<T> const& x) noexcept;
}
+635
View File
@@ -0,0 +1,635 @@
namespace math
{
//////////////////////////////////////////////////////////////////////////
// scalars
template<typename T>
constexpr T to_radians(T const& degrees) noexcept
{
static_assert(std::is_floating_point_v<T>);
TL_PLAIN_ASSERT(is_finite(degrees));
if constexpr (std::is_floating_point_v<T>)
return degrees * angle<T>::pi * T(0.00555555555555555555555555555556);
else
return degrees * angle<T>::pi / T(180);
}
template<typename T>
constexpr T to_degrees(T const& a) noexcept
{
static_assert(std::is_floating_point_v<T>);
TL_PLAIN_ASSERT(is_finite(a));
return a * T(180) / angle<T>::pi;
}
//////////////////////////////////////////////////////////////////////////
namespace detail
{
//one version of fast_sin - around 1100 cycles on atmega2560
//max_error = 0.001091, avg_error = 0.000505
// constexpr float _fast_sin(float x)
// {
// float res = x * (1.27323954f - 0.405284735f * math::abs(x));
// return res * (.225f * (math::abs(res) - 1.f) + 1.f);
// }
//
// constexpr float fast_sin(float x)
// {
// //always wrap input angle to -PI..PI
// if (is_negative(x) && x < -3.14159266f)
// {
// do { x += 6.28318531f; } while (x < -3.14159266f);
// }
// else if (x > 3.14159266f)
// {
// do { x -= 6.28318531f; } while (x > 3.14159266f);
// }
// return _fast_sin(x);
// }
// constexpr float fast_cos(float x)
// {
// return fast_sin(x + 1.5707963268f);
// }
// constexpr void fast_sin_cos(float x, float& s, float& c)
// {
// //always wrap input angle to -PI..PI
// if (is_negative(x) && x < -3.14159266f)
// {
// do { x += 6.28318531f; } while (x < -3.14159266f);
//
// s = _fast_sin(x);
// c = _fast_sin(x + 1.5707963268f); //no need to check for overflow
// }
// else if (x > 3.14159266f)
// {
// do { x -= 6.28318531f; } while (x > 3.14159266f);
//
// s = _fast_sin(x);
// c = _fast_sin(x + 1.5707963268f); //no need to check for overflow
// }
// else
// {
// s = _fast_sin(x);
// x += 1.5707963268f;
// if (is_positive(x) && x > 3.14159266f)
// {
// x -= 6.28318531f;
// }
// c = _fast_sin(x);
// }
// }
//////////////////////////////////////////////////////////////////////////
// lookup table version: around 600 cycles
//max_error = 0.000538 avg_error = 0.000347
//mantissa of (sin(x = 0 - pi/2) + 1) + 1
//the last element is to allow interpolating without checking for out of bounds
extern const uint32_t k_sin_cos[806];
inline float fast_sin_pi2(float x) noexcept //x = 64 .. 64 + pi/2
{
TL_PLAIN_ASSERT(x >= 64 && x <= 64 + anglef::pi2);
//0 1234567 0 1234567 01234567 01234567
//s eeeeeee e ------t tttttttt iiiiiiii
const uint8_t* __restrict x1_ptr = reinterpret_cast<uint8_t*>(&x);
const uint8_t it = *x1_ptr; //low 8 bits are for interpolating between table entries
const uint16_t fx = *reinterpret_cast<const uint16_t*>(x1_ptr + 1)&0x7FFF; //high 9 bits are for table lookup
//now fx should be between 0 and 804
//compose the float from a precomputed exponent (1.0) by appending the decimals
const uint16_t t1 = k_sin_cos[fx] >> 16;
const uint16_t t2 = k_sin_cos[fx + 1] >> 16;
//v = a + (b - a)*t;
const uint32_t v = (uint32_t(t1) << 7) + ((uint32_t(t2 - t1) * it) >> 1);
const uint32_t f = 0x3F800000 | v;
const float* __restrict ret = reinterpret_cast<const float*>(&f); //1 .. 2
return *ret;
}
inline float fast_sin(float x) noexcept
{
while (is_positive(x) && x >= anglef::_2pi) x -= anglef::_2pi;
while (is_negative(x)) x += anglef::_2pi;
if (x >= anglef::pi)
{
if (x >= 3.f * anglef::pi2) //IV
return 1.f - fast_sin_pi2(64.f + (anglef::_2pi - x));
else //III
return 1.f - fast_sin_pi2(64.f + (x - anglef::pi));
}
else
{
if (x >= anglef::pi2) //II
return fast_sin_pi2(64.f + (anglef::pi - x)) - 1.f;
else //I
return fast_sin_pi2(64.f + x) - 1.f;
}
}
inline float fast_cos(float x) noexcept
{
return fast_sin(x + anglef::pi2);
}
inline void fast_sin_cos_pi2(float x, float& sres, float& cres) noexcept //x = 64 .. 64 + pi/2
{
TL_PLAIN_ASSERT(x >= 64 && x <= 64 + anglef::pi2);
//0 1234567 0 1234567 01234567 01234567
//s eeeeeee e ------t tttttttt iiiiiiii
const uint8_t* __restrict x1_ptr = reinterpret_cast<uint8_t*>(&x);
const uint8_t it = *x1_ptr; //low 8 bits are for interpolating between table entries
const uint16_t fx = *reinterpret_cast<const uint16_t*>(x1_ptr + 1) & 0x7FFF; //high 9 bits are for table lookup
//now fx should be between 0 and 804
//compose the float from a precomputed exponent (1.0) by appending the decimals
const uint32_t sc1 = k_sin_cos[fx];
const uint32_t sc2 = k_sin_cos[fx + 1];
{
const uint16_t v1 = sc1 >> 16;
const uint16_t v2 = sc2 >> 16;
//v = a + (b - a)*t;
const uint32_t v = (uint32_t(v1) << 7) + ((uint32_t(v2 - v1) * it) >> 1);
const uint32_t f = 0x3F800000 | v;
sres = *reinterpret_cast<const float*>(&f); //1 .. 2
}
{
const uint16_t v1 = sc1 & 0xFFFF;
const uint16_t v2 = sc2 & 0xFFFF;
//v = a + (b - a)*t;
const uint32_t v = (uint32_t(v1) << 7) - ((uint32_t(v1 - v2) * it) >> 1);
const uint32_t f = 0x3F800000 | v;
cres = *reinterpret_cast<const float*>(&f); //1 .. 2
}
}
inline void fast_sin_cos(float x, float& s, float& c) noexcept
{
while (is_positive(x) && x >= anglef::_2pi) x -= anglef::_2pi;
while (is_negative(x)) x += anglef::_2pi;
if (x >= anglef::pi)
{
if (x >= 3.f * anglef::pi2)
{
//IV
fast_sin_cos_pi2(64.f + (anglef::_2pi - x), s, c);
s = 1.f - s;
c = c - 1.f;
}
else
{
//III
fast_sin_cos_pi2(64.f + (x - anglef::pi), s, c);
s = 1.f - s;
c = 1.f - c;
}
}
else
{
if (x >= anglef::pi2)
{
//II
fast_sin_cos_pi2(64.f + (anglef::pi - x), s, c);
s = s - 1.f;
c = 1.f - c;
}
else
{
//I
fast_sin_cos_pi2(64.f + x, s, c);
s = s - 1.f;
c = c - 1.f;
}
}
}
}
//////////////////////////////////////////////////////////////////////////
//standard
template<> /*constexpr*/ inline float cos<float, standard>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return ::cosf(s);
}
template<> /*constexpr*/ inline float sin<float, standard>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return ::sinf(s);
}
template<> /*constexpr*/ inline float tan<float, standard>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return ::tanf(s);
}
template<> /*constexpr*/ inline void sin_cos<float, standard>(float const& angle, float& s, float& c) noexcept
{
TL_PLAIN_ASSERT(is_finite(angle));
s = ::sinf(angle);
c = ::cosf(angle);
}
template<> /*constexpr*/ inline double cos<double, standard>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return ::cos(s);
}
template<> /*constexpr*/ inline double sin<double, standard>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return ::sin(s);
}
template<> /*constexpr*/ inline double tan<double, standard>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return ::tan(s);
}
template<> /*constexpr*/ inline void sin_cos<double, standard>(double const& angle, double& s, double& c) noexcept
{
TL_PLAIN_ASSERT(is_finite(angle));
s = ::sin(angle);
c = ::cos(angle);
}
//////////////////////////////////////////////////////////////////////////
//fast
template<> /*constexpr*/ inline float cos<float, fast>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return detail::fast_cos(s);
}
template<> /*constexpr*/ inline float sin<float, fast>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return detail::fast_sin(s);
}
template<> /*constexpr*/ inline float tan<float, fast>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return ::tanf(s);
}
template<> /*constexpr*/ inline void sin_cos<float, fast>(float const& angle, float& s, float& c) noexcept
{
TL_PLAIN_ASSERT(is_finite(angle));
detail::fast_sin_cos(angle, s, c);
}
template<> /*constexpr*/ inline double cos<double, fast>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return ::cos(s);
}
template<> /*constexpr*/ inline double sin<double, fast>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return ::sin(s);
}
template<> /*constexpr*/ inline double tan<double, fast>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return ::tan(s);
}
template<> /*constexpr*/ inline void sin_cos<double, fast>(double const& angle, double& s, double& c) noexcept
{
TL_PLAIN_ASSERT(is_finite(angle));
s = ::sin(angle);
c = ::cos(angle);
}
//////////////////////////////////////////////////////////////////////////
//safe
template<> /*constexpr*/ inline float cos<float, safe>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? 1 : ::cosf(s);
}
template<> /*constexpr*/ inline float sin<float, safe>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? 0 : ::sinf(s);
}
template<> /*constexpr*/ inline float tan<float, safe>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? 0 : ::tanf(s);
}
template<> /*constexpr*/ inline void sin_cos<float, safe>(float const& angle, float& s, float& c) noexcept
{
TL_PLAIN_ASSERT(is_finite(angle));
if (is_finite(angle))
{
s = ::sinf(angle);
c = ::cosf(angle);
}
else
{
s = 0;
c = 1;
}
}
template<> /*constexpr*/ inline double cos<double, safe>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? 1 : ::cos(s);
}
template<> /*constexpr*/ inline double sin<double, safe>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? 0 : ::sin(s);
}
template<> /*constexpr*/ inline double tan<double, safe>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? 0 : ::tan(s);
}
template<> /*constexpr*/ inline void sin_cos<double, safe>(double const& angle, double& s, double& c) noexcept
{
TL_PLAIN_ASSERT(is_finite(angle));
if (!is_finite(angle))
{
s = ::sin(angle);
c = ::cos(angle);
}
else
{
s = 0;
c = 1;
}
}
template<typename T, class Policy> /*constexpr*/ inline void sin_cos(T const& angle, T& s, T& c) noexcept
{
s = sin<T, Policy>(angle);
c = cos<T, Policy>(angle);
}
//////////////////////////////////////////////////////////////////////////
template<typename T, class Policy>
/*constexpr*/ inline T cos(T const& angle) noexcept
{
TL_PLAIN_ASSERT(is_finite(angle));
return std::cos(angle);
}
template<typename T, class Policy>
/*constexpr*/ inline T sin(T const& angle) noexcept
{
TL_PLAIN_ASSERT(is_finite(angle));
return std::sin(angle);
}
template<typename T, class Policy>
/*constexpr*/ inline T tan(T const& angle) noexcept
{
TL_PLAIN_ASSERT(is_finite(angle));
return std::tan(angle);
}
//////////////////////////////////////////////////////////////////////////
template<> /*constexpr*/ inline float acos<float, standard>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return float(::acosf(s));
}
template<> /*constexpr*/ inline float asin<float, standard>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return float(::asinf(s));
}
template<> /*constexpr*/ inline float atan<float, standard>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return float(::atanf(s));
}
template<> /*constexpr*/ inline float atan2<float, standard>(float const& y, float const& x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x) && is_finite(y));
return float(::atan2f(y, x));
}
template<> /*constexpr*/ inline double acos<double, standard>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return double(::acos(s));
}
template<> /*constexpr*/ inline double asin<double, standard>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return double(::asin(s));
}
template<> /*constexpr*/ inline double atan<double, standard>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return double(::atan(s));
}
template<> /*constexpr*/ inline double atan2<double, standard>(double const& y, double const& x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x) && is_finite(y));
return double(::atan2(y, x));
}
template<> /*constexpr*/ inline float acos<float, fast>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return float(::acosf(s));
}
template<> /*constexpr*/ inline float asin<float, fast>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return float(::asinf(s));
}
template<> /*constexpr*/ inline float atan<float, fast>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return float(::atanf(s));
}
template<> /*constexpr*/ inline float atan2<float, fast>(float const& y, float const& x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x) && is_finite(y));
return float(::atan2f(y, x));
}
template<> /*constexpr*/ inline double acos<double, fast>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return double(::acos(s));
}
template<> /*constexpr*/ inline double asin<double, fast>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return double(::asin(s));
}
template<> /*constexpr*/ inline double atan<double, fast>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return double(::atan(s));
}
template<> /*constexpr*/ inline double atan2<double, fast>(double const& y, double const& x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x) && is_finite(y));
return double(::atan2(y, x));
}
template<> /*constexpr*/ inline float acos<float, safe>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? angle<float>::pi2 : float(::acosf(clamp(s, 0.f, 1.f)));
}
template<> /*constexpr*/ inline float asin<float, safe>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? 0 : float(::asinf(s));
}
template<> /*constexpr*/ inline float atan<float, safe>(float const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? 0 : float(::atanf(s));
}
template<> /*constexpr*/ inline float atan2<float, safe>(float const& y, float const& x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x) && is_finite(y) && !is_zero(y));
return !is_finite(x) || !is_finite(y) || is_zero(y) ? 0 : float(::atan2f(y, x));
}
template<> /*constexpr*/ inline double acos<double, safe>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? angle<double>::pi2 : double(::acos(s));
}
template<> /*constexpr*/ inline double asin<double, safe>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? 0 : double(::asin(s));
}
template<> /*constexpr*/ inline double atan<double, safe>(double const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
return !is_finite(s) ? 0 : double(::atan(s));
}
template<> /*constexpr*/ inline double atan2<double, safe>(double const& y, double const& x) noexcept
{
TL_PLAIN_ASSERT(is_finite(x) && is_finite(y) && !is_zero(y));
return !is_finite(x) || !is_finite(y) || is_zero(y) ? 0 : double(::atan2(y, x));
}
//////////////////////////////////////////////////////////////////////////
// vec2
template<typename T>
constexpr vec2<T> to_degrees(vec2<T> const& v) noexcept
{
return vec2<T>(to_degrees(v.x), to_degrees(v.y));
}
template<typename T>
constexpr vec2<T> to_radians(vec2<T> const& v) noexcept
{
return vec2<T>(to_radians(v.x), to_radians(v.y));
}
template<typename T, class Policy>
/*constexpr*/ inline vec2<T> cos(vec2<T> const& v) noexcept
{
return vec2<T>(cos<T, Policy>(v.x), cos<T, Policy>(v.y));
}
template<typename T, class Policy>
/*constexpr*/ inline vec2<T> sin(vec2<T> const& v) noexcept
{
return vec2<T>(sin<T, Policy>(v.x), sin<T, Policy>(v.y));
}
template<typename T, class Policy>
/*constexpr*/ inline vec2<T> tan(vec2<T> const& v) noexcept
{
return vec2<T>(tan<T, Policy>(v.x), tan<T, Policy>(v.y));
}
template<typename T, class Policy>
/*constexpr*/ inline void sin_cos(vec2<T> const& angle, vec2<T>& s, vec2<T>& c) noexcept
{
s = sin<T, Policy>(angle);
c = cos<T, Policy>(angle);
}
//////////////////////////////////////////////////////////////////////////
// vec3
template<typename T>
constexpr vec3<T> to_degrees(vec3<T> const& v) noexcept
{
return vec3<T>(to_degrees(v.x), to_degrees(v.y), to_degrees(v.z));
}
template<typename T>
constexpr vec3<T> to_radians(vec3<T> const& v) noexcept
{
return vec3<T>(to_radians(v.x), to_radians(v.y), to_radians(v.z));
}
template<typename T, class Policy>
/*constexpr*/ inline vec3<T> cos(vec3<T> const& v) noexcept
{
return vec3<T>(cos<T, Policy>(v.x), cos<T, Policy>(v.y), cos<T, Policy>(v.z));
}
template<typename T, class Policy>
/*constexpr*/ inline vec3<T> sin(vec3<T> const& v) noexcept
{
return vec3<T>(sin<T, Policy>(v.x), sin<T, Policy>(v.y), sin<T, Policy>(v.z));
}
template<typename T, class Policy>
/*constexpr*/ inline vec3<T> tan(vec3<T> const& v) noexcept
{
return vec3<T>(tan<T, Policy>(v.x), tan<T, Policy>(v.y), tan<T, Policy>(v.z));
}
template<typename T, class Policy>
/*constexpr*/ inline void sin_cos(vec3<T> const& angle, vec3<T>& s, vec3<T>& c) noexcept
{
s = sin<T, Policy>(angle);
c = cos<T, Policy>(angle);
}
//////////////////////////////////////////////////////////////////////////
// vec4
template<typename T>
constexpr vec4<T> to_degrees(vec4<T> const& v) noexcept
{
return vec4<T>(to_degrees(v.x), to_degrees(v.y), to_degrees(v.z), to_degrees(v.w));
}
template<typename T>
constexpr vec4<T> to_radians(vec4<T> const& v) noexcept
{
return vec4<T>(to_radians(v.x), to_radians(v.y), to_radians(v.z), to_radians(v.w));
}
template<typename T, class Policy>
/*constexpr*/ inline vec4<T> cos(vec4<T> const& v) noexcept
{
return vec4<T>(cos<T, Policy>(v.x), cos<T, Policy>(v.y), cos<T, Policy>(v.z), cos<T, Policy>(v.w));
}
template<typename T, class Policy>
/*constexpr*/ inline vec4<T> sin(vec4<T> const& v) noexcept
{
return vec4<T>(sin<T, Policy>(v.x), sin<T, Policy>(v.y), sin<T, Policy>(v.z), sin<T, Policy>(v.w));
}
template<typename T, class Policy>
/*constexpr*/ inline vec4<T> tan(vec4<T> const& v) noexcept
{
return vec4<T>(tan<T, Policy>(v.x), tan<T, Policy>(v.y), tan<T, Policy>(v.z), tan<T, Policy>(v.w));
}
template<typename T, class Policy>
/*constexpr*/ inline void sin_cos(vec4<T> const& angle, vec4<T>& s, vec4<T>& c) noexcept
{
s = sin<T, Policy>(angle);
c = cos<T, Policy>(angle);
}
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <compare>
namespace math
{
template<typename T>
struct line2
{
typedef T value_t;
typedef line2<T> this_t;
constexpr line2() noexcept = default;
constexpr line2(const vec2<T>& start, const vec2<T>& direction) noexcept;
constexpr line2(const line2<T>&) noexcept = default;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
constexpr line2<T>& operator=(const line2<T>&) noexcept = default;
constexpr bool is_valid() const noexcept;
constexpr vec2<T> get_point(T distance) const noexcept;
constexpr void translate(const vec2<T>& offset) noexcept;
vec2<T> origin;
vec2<T> direction;
};
}
+45
View File
@@ -0,0 +1,45 @@
namespace math
{
template<typename T>
constexpr line2<T>::line2(const vec2<T>& start, const vec2<T>& direction) noexcept
: origin(start)
, direction(direction)
{
}
template<typename T>
constexpr bool line2<T>::is_valid() const noexcept
{
return !is_zero(direction);
}
template<typename T>
constexpr vec2<T> line2<T>::get_point(T distance) const noexcept
{
TL_PLAIN_ASSERT(is_valid());
return origin + direction * distance;
}
template<typename T>
constexpr void line2<T>::translate(const vec2<T>& offset) noexcept
{
TL_PLAIN_ASSERT(is_valid());
origin += offset;
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::line2<T>>
{
std::size_t operator()(const math::line2<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.origin);
tl::hash_and_combine(seed, p.direction);
return seed;
}
};
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <compare>
namespace math
{
template<typename T>
struct line3
{
typedef T value_t;
typedef line3<T> this_t;
constexpr line3() noexcept = default;
constexpr line3(const vec3<T>& start, const vec3<T>& direction) noexcept;
constexpr line3(const line3<T>&) noexcept = default;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
constexpr line3<T>& operator=(const line3<T>&) noexcept = default;
constexpr bool is_valid() const noexcept;
constexpr vec3<T> get_point(T distance) const noexcept;
constexpr void translate(const vec3<T>& offset) noexcept;
vec3<T> origin;
vec3<T> direction;
};
}
+45
View File
@@ -0,0 +1,45 @@
namespace math
{
template<typename T>
constexpr line3<T>::line3(const vec3<T>& start, const vec3<T>& direction) noexcept
: origin(start)
, direction(direction)
{
}
template<typename T>
constexpr bool line3<T>::is_valid() const noexcept
{
return !is_zero(direction);
}
template<typename T>
constexpr vec3<T> line3<T>::get_point(T distance) const noexcept
{
TL_PLAIN_ASSERT(is_valid());
return origin + direction * distance;
}
template<typename T>
constexpr void line3<T>::translate(const vec3<T>& offset) noexcept
{
TL_PLAIN_ASSERT(is_valid());
origin += offset;
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::line3<T>>
{
std::size_t operator()(const math::line3<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.origin);
tl::hash_and_combine(seed, p.direction);
return seed;
}
};
+92
View File
@@ -0,0 +1,92 @@
#pragma once
#include <compare>
namespace math
{
template <typename T>
struct vec2;
//column-major (OpenGL) layout
// .----------- packet0 (column0) - x axis
// | .------- packet1 (column1) - y axis
// 0 2
// 1 3
template <typename T>
struct mat2
{
typedef T value_t;
using this_t = mat2<T>;
static constexpr size_t row_count = 2;
static constexpr size_t column_count = 2;
static constexpr size_t element_count = 4;
template <class Policy = standard>
constexpr static mat2<T> from_rotation(T rotation) noexcept;
// template<class Policy = standard>
// static mat2<T> from_rotation(math::angle<T> angle) noexcept;
constexpr mat2() noexcept;
constexpr explicit mat2(math::ZUninitialized) noexcept;
constexpr explicit mat2(angle<T> const& rotation) noexcept;
constexpr explicit mat2(T value) noexcept;
constexpr mat2(mat2<T> const&) noexcept = default;
//column major - column0 is initialized from v0, v1
constexpr mat2(T v0, T v1,
T v2, T v3) noexcept;
constexpr mat2(vec2<T> const& column0,
vec2<T> const& column1) noexcept;
constexpr mat2<T>& operator=(mat2<T> const&) noexcept = default;
//Rows are NOT linearly in memory. First row is m[0], m[2]
constexpr vec2<T> get_row(size_t row) const noexcept;
constexpr void set_row(size_t row, vec2<T> const& v) noexcept;
//Columns are linearly in memory. First row is m[0], m[1], and is the X axis of the matrix
constexpr vec2<T> const& get_column(size_t column) const noexcept;
constexpr void set_column(size_t column, vec2<T> const& v) noexcept;
constexpr vec2<T> const& get_axis_x() const noexcept;
constexpr void set_axis_x(vec2<T> const& axis) noexcept;
constexpr vec2<T> const& get_axis_y() const noexcept;
constexpr void set_axis_y(vec2<T> const& axis) noexcept;
template <class Policy = standard>
constexpr vec2<T> get_scale() const noexcept;
constexpr void set_scale(vec2<T> const& scale) noexcept;
constexpr T determinant() const noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
constexpr T* data() noexcept;
constexpr T const* data() const noexcept;
constexpr T& element(size_t column, size_t row) noexcept;
constexpr T const& element(size_t column, size_t row) const noexcept;
constexpr mat2<T> operator*(mat2<T> const& other) const noexcept;
constexpr mat2<T> operator+(mat2<T> const& other) const noexcept;
constexpr mat2<T> operator-(mat2<T> const& other) const noexcept;
constexpr mat2<T> operator*(T scalar) const noexcept;
constexpr mat2<T> operator+(T scalar) const noexcept;
constexpr mat2<T> operator-(T scalar) const noexcept;
constexpr mat2<T>& operator*=(mat2<T> const& other) noexcept;
constexpr mat2<T>& operator+=(mat2<T> const& other) noexcept;
constexpr mat2<T>& operator-=(mat2<T> const& other) noexcept;
constexpr mat2<T>& operator*=(T scalar) noexcept;
constexpr mat2<T>& operator+=(T scalar) noexcept;
constexpr mat2<T>& operator-=(T scalar) noexcept;
vec2<T> column0;
vec2<T> column1;
};
}
+285
View File
@@ -0,0 +1,285 @@
namespace math
{
template<typename T>
template<class Policy>
constexpr mat2<T> mat2<T>::from_rotation(T rotation) noexcept
{
if (rotation == T(0))
return {};
else
{
T s, c;
sin_cos<T, Policy>(rotation, s, c);
return { c, s, -s, c };
}
}
// template<typename T>
// template<class Policy>
// constexpr mat2<T> mat2<T>::from_rotation(math::angle<T> angle) noexcept
// {
// return from_rotation<T, Policy>(angle.radians);
// }
template<typename T>
constexpr mat2<T>::mat2() noexcept
: column0(T(1), T(0))
, column1(T(0), T(1))
{
}
template<typename T>
constexpr mat2<T>::mat2(math::ZUninitialized) noexcept
{
}
template<typename T>
constexpr mat2<T>::mat2(angle<T> const& rotation) noexcept
: column0(math::uninitialized)
, column1(math::uninitialized)
{
T s, c;
sin_cos(rotation.radians, s, c);
T* m = data();
m[0] = c;
m[1] = s;
m[2] = -s;
m[3] = c;
}
template<typename T>
constexpr mat2<T>::mat2(T value) noexcept
: column0(value, value)
, column1(value, value)
{
TL_PLAIN_ASSERT(is_finite(value));
}
template<typename T>
constexpr mat2<T>::mat2(T v0, T v1, T v2, T v3) noexcept
: column0(v0, v1)
, column1(v2, v3)
{
TL_PLAIN_ASSERT(is_finite(column0) &&
is_finite(column1));
}
template<typename T>
constexpr mat2<T>::mat2(vec2<T> const& column0, vec2<T> const& column1) noexcept
: column0(column0)
, column1(column1)
{
TL_PLAIN_ASSERT(is_finite(column0) &&
is_finite(column1));
}
///////////////////////////////////////////////////////////////////////////////
//methods
///////////////////////////////////////////////////////////////////////////////
template<typename T>
constexpr vec2<T> mat2<T>::get_row(size_t row) const noexcept
{
TL_PLAIN_ASSERT(row < row_count);
const T* m = data();
return vec2<T>(m[row], m[row + 2]);
}
template<typename T>
constexpr void mat2<T>::set_row(size_t row, vec2<T> const& v) noexcept
{
TL_PLAIN_ASSERT(is_finite(v));
TL_PLAIN_ASSERT(row < row_count);
T* m = data();
m[row] = v.x;
m[row + 2] = v.y;
}
template<typename T>
constexpr vec2<T> const& mat2<T>::get_column(size_t column) const noexcept
{
TL_PLAIN_ASSERT(column < column_count);
const T* m = data();
size_t idx = column * row_count;
return *(vec2<T> const*)(&m[idx]);
}
template<typename T>
constexpr void mat2<T>::set_column(size_t column, vec2<T> const& v) noexcept
{
TL_PLAIN_ASSERT(is_finite(v));
TL_PLAIN_ASSERT(column < column_count);
T* m = data();
size_t idx = column * row_count;
*(vec2<T>*)(&m[idx]) = v;
}
template<typename T>
constexpr vec2<T> const& mat2<T>::get_axis_x() const noexcept
{
return get_column(0);
}
template<typename T>
constexpr vec2<T> const& mat2<T>::get_axis_y() const noexcept
{
return get_column(1);
}
template<typename T>
template<class Policy>
constexpr vec2<T> mat2<T>::get_scale() const noexcept
{
return vec2<T>(get_axis_x().template length<Policy>(), get_axis_y().template length<Policy>());
}
template<typename T>
constexpr void mat2<T>::set_axis_x(vec2<T> const& axis) noexcept
{
set_column(0, axis);
}
template<typename T>
constexpr void mat2<T>::set_axis_y(vec2<T> const& axis) noexcept
{
set_column(1, axis);
}
template<typename T>
constexpr void mat2<T>::set_scale(vec2<T> const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
T* m = data();
m[0] = s.x;
m[3] = s.y;
}
template<typename T>
constexpr T mat2<T>::determinant() const noexcept
{
const T* m = data();
return m[0] * m[3]
- m[1] * m[2];
}
///////////////////////////////////////////////////////////////////////////////
// indexing operators
///////////////////////////////////////////////////////////////////////////////
template<typename T>
constexpr T* mat2<T>::data() noexcept
{
return (T*)&column0;
}
template<typename T>
constexpr T const* mat2<T>::data() const noexcept
{
return (T const*)&column0;
}
template<typename T>
constexpr T& mat2<T>::element(size_t column, size_t row) noexcept
{
TL_PLAIN_ASSERT(column < column_count&& row < row_count);
T* m = data();
return m[column * row_count + row];
}
template<typename T>
constexpr T const& mat2<T>::element(size_t column, size_t row) const noexcept
{
TL_PLAIN_ASSERT(column < column_count&& row < row_count);
const T* m = data();
return m[column * row_count + row];
}
template<typename T>
constexpr mat2<T> mat2<T>::operator*(mat2<T> const& other) const noexcept
{
mat2<T> ret;
return multiply(ret, *this, other);
}
template<typename T>
constexpr mat2<T> mat2<T>::operator+(mat2<T> const& other) const noexcept
{
mat2<T> ret;
return cwise::add(ret, *this, other);
}
template<typename T>
constexpr mat2<T> mat2<T>::operator-(mat2<T> const& other) const noexcept
{
mat2<T> ret;
return cwise::substract(ret, *this, other);
}
template<typename T>
constexpr mat2<T>& mat2<T>::operator*=(mat2<T> const& other) noexcept
{
mat2<T> a(*this);
return multiply(*this, a, other);
}
template<typename T>
constexpr mat2<T>& mat2<T>::operator+=(mat2<T> const& other) noexcept
{
return cwise::add(*this, *this, other);
}
template<typename T>
constexpr mat2<T>& mat2<T>::operator-=(mat2<T> const& other) noexcept
{
return cwise::substract(*this, *this, other);
}
template<typename T>
constexpr mat2<T> mat2<T>::operator*(T scalar) const noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
mat2<T> ret;
return cwise::multiply(ret, *this, scalar);
}
template<typename T>
constexpr mat2<T> mat2<T>::operator+(T scalar) const noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
mat2<T> ret;
return cwise::add(ret, *this, scalar);
}
template<typename T>
constexpr mat2<T> mat2<T>::operator-(T scalar) const noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
mat2<T> ret;
return cwise::substract(ret, *this, scalar);
}
template<typename T>
constexpr mat2<T>& mat2<T>::operator*=(T scalar) noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
return cwise::multiply(*this, *this, scalar);
}
template<typename T>
constexpr mat2<T>& mat2<T>::operator+=(T scalar) noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
return cwise::add(*this, *this, scalar);
}
template<typename T>
constexpr mat2<T>& mat2<T>::operator-=(T scalar) noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
return cwise::substract(*this, *this, scalar);
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::mat2<T>>
{
std::size_t operator()(const math::mat2<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.column0);
tl::hash_and_combine(seed, p.column1);
return seed;
}
};
+101
View File
@@ -0,0 +1,101 @@
#pragma once
#include <compare>
namespace math
{
template <typename T>
struct vec3;
//column-major (OpenGL) layout
// .--------------- column0 - x axis
// | .----------- column1 - y axis
// | | .------- column2 - translation
// 0 3 6
// 1 4 7
// 2 5 8
template <typename T>
struct mat3
{
typedef T value_t;
using this_t = mat3<T>;
static constexpr size_t row_count = 3;
static constexpr size_t column_count = 3;
static constexpr size_t element_count = 9;
///! Creates a world space lookat matrix (front axis is -yaxis, up axis is zaxis)
/// This lookAt method computes a look at matrix in jet coordinate system (3dmax biped).
/// This means that when you send a front of (0,1,0) and an up of (0,0,1) the resulting matrix is identity.
template <class Policy = standard>
constexpr static mat3<T> from_look_at(vec3<T> const& front, vec3<T> const& up) noexcept;
constexpr mat3() noexcept;
constexpr explicit mat3(math::ZUninitialized) noexcept;
constexpr explicit mat3(T value) noexcept;
constexpr mat3(mat3<T> const&) noexcept = default;
//column major (column 0 is initialized from v0, v1, v2)
constexpr mat3(T v0, T v1, T v2,
T v3, T v4, T v5,
T v6, T v7, T v8) noexcept;
constexpr mat3(vec3<T> const& column0,
vec3<T> const& column1,
vec3<T> const& column2) noexcept;
constexpr mat3<T>& operator=(mat3<T> const&) noexcept = default;
//Rows are NOT linearly in memory. First row is m[0], m[3], m[6]
constexpr vec3<T> get_row(size_t row) const noexcept;
constexpr void set_row(size_t row, vec3<T> const& v) noexcept;
//Columns are linearly in memory. First row is m[0], m[1], m[2] and is the X axis of the matrix
constexpr vec3<T> const& get_column(size_t column) const noexcept;
constexpr void set_column(size_t column, vec3<T> const& v) noexcept;
constexpr vec3<T> const& get_axis_x() const noexcept;
constexpr void set_axis_x(vec3<T> const& axis) noexcept;
constexpr vec3<T> const& get_axis_y() const noexcept;
constexpr void set_axis_y(vec3<T> const& axis) noexcept;
constexpr vec3<T> const& get_axis_z() const noexcept;
constexpr void set_axis_z(vec3<T> const& axis) noexcept;
template <class Policy = standard>
constexpr vec3<T> get_scale() const noexcept;
constexpr void set_scale(vec3<T> const& scale) noexcept;
constexpr void post_scale(vec3<T> const& scale) noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
constexpr T determinant() const noexcept;
constexpr T* data() noexcept;
constexpr T const* data() const noexcept;
constexpr T& element(size_t column, size_t row) noexcept;
constexpr T const& element(size_t column, size_t row) const noexcept;
constexpr mat3<T> operator*(mat3<T> const& other) const noexcept;
constexpr mat3<T> operator+(mat3<T> const& other) const noexcept;
constexpr mat3<T> operator-(mat3<T> const& other) const noexcept;
constexpr mat3<T> operator*(T scalar) const noexcept;
constexpr mat3<T> operator+(T scalar) const noexcept;
constexpr mat3<T> operator-(T scalar) const noexcept;
constexpr mat3<T>& operator*=(mat3<T> const& other) noexcept;
constexpr mat3<T>& operator+=(mat3<T> const& other) noexcept;
constexpr mat3<T>& operator-=(mat3<T> const& other) noexcept;
constexpr mat3<T>& operator*=(T scalar) noexcept;
constexpr mat3<T>& operator+=(T scalar) noexcept;
constexpr mat3<T>& operator-=(T scalar) noexcept;
vec3<T> column0;
vec3<T> column1;
vec3<T> column2;
};
}
+289
View File
@@ -0,0 +1,289 @@
namespace math
{
template<typename T>
template<class Policy>
constexpr mat3<T> mat3<T>::from_look_at(vec3<T> const& front, vec3<T> const& up) noexcept
{
vec3<T> axisY = normalized<T, Policy>(front);
vec3<T> axisX = normalized<T, Policy>(cross(axisY, normalized<T, Policy>(up)));//this normalize is mandatory because axisY and up may be unitary but they hardly are orthogonal
vec3<T> axisZ = cross(axisX, axisY);
return mat3<T>(axisX, axisY, axisZ);
}
template<typename T>
constexpr mat3<T>::mat3() noexcept
: column0(T(1), T(0), T(0))
, column1(T(0), T(1), T(0))
, column2(T(0), T(0), T(1))
{
}
template<typename T>
constexpr mat3<T>::mat3(ZUninitialized) noexcept
{
}
template<typename T>
constexpr mat3<T>::mat3(T value) noexcept
: column0(value, value, value)
, column1(value, value, value)
, column2(value, value, value)
{
TL_PLAIN_ASSERT(is_finite(value));
}
template<typename T>
constexpr mat3<T>::mat3(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8) noexcept
: column0(v0, v1, v2)
, column1(v3, v4, v5)
, column2(v6, v7, v8)
{
TL_PLAIN_ASSERT(is_finite(column0) &&
is_finite(column1) &&
is_finite(column2));
}
template<typename T>
constexpr mat3<T>::mat3(vec3<T> const& column0, vec3<T> const& column1, vec3<T> const& column2) noexcept
: column0(column0)
, column1(column1)
, column2(column2)
{
TL_PLAIN_ASSERT(is_finite(column0) &&
is_finite(column1) &&
is_finite(column2));
}
template<typename T>
constexpr vec3<T> mat3<T>::get_row(size_t row) const noexcept
{
TL_PLAIN_ASSERT(row < row_count);
const T* m = data();
return vec3<T>(m[row + 0], m[row + 3], m[row + 6]);
}
template<typename T>
constexpr void mat3<T>::set_row(size_t row, vec3<T> const& v) noexcept
{
TL_PLAIN_ASSERT(is_finite(v));
TL_PLAIN_ASSERT(row < row_count);
T* m = data();
m[row + 0] = v.x;
m[row + 3] = v.y;
m[row + 6] = v.z;
}
template<typename T>
constexpr vec3<T> const& mat3<T>::get_column(size_t column) const noexcept
{
TL_PLAIN_ASSERT(column < column_count);
const T* m = data();
size_t idx = column * row_count;
return *reinterpret_cast<vec3<T> const*>(&m[idx]);
}
template<typename T>
constexpr void mat3<T>::set_column(size_t column, vec3<T> const& v) noexcept
{
TL_PLAIN_ASSERT(is_finite(v));
TL_PLAIN_ASSERT(column < column_count);
T* m = data();
size_t idx = column * row_count;
*reinterpret_cast<vec3<T>*>(&m[idx]) = v;
}
template<typename T>
constexpr vec3<T> const& mat3<T>::get_axis_x() const noexcept
{
return get_column(0);
}
template<typename T>
constexpr vec3<T> const& mat3<T>::get_axis_y() const noexcept
{
return get_column(1);
}
template<typename T>
constexpr vec3<T> const& mat3<T>::get_axis_z() const noexcept
{
return get_column(2);
}
template<typename T>
template<class Policy>
constexpr vec3<T> mat3<T>::get_scale() const noexcept
{
return vec3<T>(get_axis_x().template length<Policy>(), get_axis_y().template length<Policy>(), get_axis_z().template length<Policy>());
}
template<typename T>
constexpr void mat3<T>::set_axis_x(vec3<T> const& axis) noexcept
{
set_column(0, axis);
}
template<typename T>
constexpr void mat3<T>::set_axis_y(vec3<T> const& axis) noexcept
{
set_column(1, axis);
}
template<typename T>
constexpr void mat3<T>::set_axis_z(vec3<T> const& axis) noexcept
{
set_column(2, axis);
}
template<typename T>
constexpr void mat3<T>::set_scale(vec3<T> const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
T* m = data();
m[0] = s.x;
m[4] = s.y;
m[8] = s.z;
}
template<typename T>
constexpr void mat3<T>::post_scale(vec3<T> const& s) noexcept
{
TL_PLAIN_ASSERT(is_finite(s));
T* m = data();
m[0] *= s.x;
m[4] *= s.y;
m[8] *= s.z;
}
template<typename T>
constexpr T mat3<T>::determinant() const noexcept
{
const T* m = data();
return m[0] * (m[4] * m[8] - m[5] * m[7])
- m[1] * (m[3] * m[8] - m[5] * m[6])
+ m[2] * (m[3] * m[7] - m[4] * m[6]);
}
///////////////////////////////////////////////////////////////////////////////
// indexing operators
///////////////////////////////////////////////////////////////////////////////
template<typename T>
constexpr T* mat3<T>::data() noexcept
{
return (T*)&column0;
}
template<typename T>
constexpr T const* mat3<T>::data() const noexcept
{
return (T const*)&column0;
}
template<typename T>
constexpr T& mat3<T>::element(size_t column, size_t row) noexcept
{
TL_PLAIN_ASSERT(column < column_count&& row < row_count);
return data()[column * row_count + row];
}
template<typename T>
constexpr T const& mat3<T>::element(size_t column, size_t row) const noexcept
{
TL_PLAIN_ASSERT(column < column_count&& row < row_count);
return data()[column * row_count + row];
}
template<typename T>
constexpr mat3<T> mat3<T>::operator*(mat3<T> const& other) const noexcept
{
mat3<T> ret(math::uninitialized);
return multiply(ret, *this, other);
}
template<typename T>
constexpr mat3<T> mat3<T>::operator+(mat3<T> const& other) const noexcept
{
mat3<T> ret(math::uninitialized);
return cwise::add(ret, *this, other);
}
template<typename T>
constexpr mat3<T> mat3<T>::operator-(mat3<T> const& other) const noexcept
{
mat3<T> ret(math::uninitialized);
return cwise::substract(ret, *this, other);
}
template<typename T>
constexpr mat3<T>& mat3<T>::operator*=(mat3<T> const& other) noexcept
{
mat3<T> a(*this);
return multiply(*this, a, other);
}
template<typename T>
constexpr mat3<T>& mat3<T>::operator+=(mat3<T> const& other) noexcept
{
return cwise::add(*this, *this, other);
}
template<typename T>
constexpr mat3<T>& mat3<T>::operator-=(mat3<T> const& other) noexcept
{
return cwise::substract(*this, *this, other);
}
template<typename T>
constexpr mat3<T> mat3<T>::operator*(T scalar) const noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
mat3<T> ret(math::uninitialized);
return cwise::multiply(ret, *this, scalar);
}
template<typename T>
constexpr mat3<T> mat3<T>::operator+(T scalar) const noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
mat3<T> ret(math::uninitialized);
return cwise::add(ret, *this, scalar);
}
template<typename T>
constexpr mat3<T> mat3<T>::operator-(T scalar) const noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
mat3<T> ret(math::uninitialized);
return cwise::substract(ret, *this, scalar);
}
template<typename T>
constexpr mat3<T>& mat3<T>::operator*=(T scalar) noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
return cwise::multiply(*this, *this, scalar);
}
template<typename T>
constexpr mat3<T>& mat3<T>::operator+=(T scalar) noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
return cwise::add(*this, *this, scalar);
}
template<typename T>
constexpr mat3<T>& mat3<T>::operator-=(T scalar) noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
return cwise::substract(*this, *this, scalar);
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::mat3<T>>
{
std::size_t operator()(const math::mat3<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.column0);
tl::hash_and_combine(seed, p.column1);
tl::hash_and_combine(seed, p.column2);
return seed;
}
};
+98
View File
@@ -0,0 +1,98 @@
#pragma once
#include <compare>
namespace math
{
template <typename T>
struct vec4;
//column-major (OpenGL) layout
// .--------------- column0 - x axis
// | .----------- column1 - y axis
// | | .------- column2 - z axis
// | | | .--- column3 - w axis
// 0 4 8 12
// 1 5 9 13
// 2 6 10 14
// 3 7 11 15
template <typename T>
struct mat4
{
typedef T value_t;
using this_t = mat4<T>;
static constexpr size_t row_count = 4;
static constexpr size_t column_count = 4;
static constexpr size_t element_count = 16;
constexpr mat4() noexcept;
constexpr explicit mat4(math::ZUninitialized) noexcept;
constexpr explicit mat4(T value) noexcept;
constexpr mat4(mat4<T> const&) noexcept = default;
//column major - column0 is initialized from v0, v1, v2, v3
constexpr mat4(T v0, T v1, T v2, T v3,
T v4, T v5, T v6, T v7,
T v8, T v9, T v10, T v11,
T v12, T v13, T v14, T v15) noexcept;
constexpr mat4(vec4<T> const& column0,
vec4<T> const& column1,
vec4<T> const& column2,
vec4<T> const& column3) noexcept;
constexpr mat4<T>& operator=(mat4<T> const&) noexcept = default;
constexpr mat4<T> operator*(mat4<T> const& other) const noexcept;
constexpr mat4<T> operator+(mat4<T> const& other) const noexcept;
constexpr mat4<T> operator-(mat4<T> const& other) const noexcept;
constexpr mat4<T> operator*(T scalar) const noexcept;
constexpr mat4<T> operator+(T scalar) const noexcept;
constexpr mat4<T> operator-(T scalar) const noexcept;
constexpr mat4<T>& operator*=(mat4<T> const& other) noexcept;
constexpr mat4<T>& operator+=(mat4<T> const& other) noexcept;
constexpr mat4<T>& operator-=(mat4<T> const& other) noexcept;
constexpr mat4<T>& operator*=(T scalar) noexcept;
constexpr mat4<T>& operator+=(T scalar) noexcept;
constexpr mat4<T>& operator-=(T scalar) noexcept;
//Rows are NOT linearly in memory. First row is m[0], m[4], m[8], m[12]
constexpr vec4<T> get_row(size_t row) const noexcept;
constexpr void set_row(size_t row, vec4<T> const& v) noexcept;
//Columns are linearly in memory. First row is m[0], m[1], m[2], m[3] and is the X axis of the matrix
constexpr vec4<T> const& get_column(size_t column) const noexcept;
constexpr void set_column(size_t column, vec4<T> const& v) noexcept;
constexpr vec4<T> const& get_axis_x() const noexcept;
constexpr void set_axis_x(vec4<T> const& axis) noexcept;
constexpr vec4<T> const& get_axis_y() const noexcept;
constexpr void set_axis_y(vec4<T> const& axis) noexcept;
constexpr vec4<T> const& get_axis_z() const noexcept;
constexpr void set_axis_z(vec4<T> const& axis) noexcept;
constexpr vec4<T> const& get_axis_w() const noexcept;
constexpr void set_axis_w(vec4<T> const& axis) noexcept;
constexpr T determinant() const noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
constexpr T* data() noexcept;
constexpr T const* data() const noexcept;
constexpr T& element(size_t column, size_t row) noexcept;
constexpr T const& element(size_t column, size_t row) const noexcept;
vec4<T> column0;
vec4<T> column1;
vec4<T> column2;
vec4<T> column3;
};
}
+293
View File
@@ -0,0 +1,293 @@
namespace math
{
template<typename T>
constexpr mat4<T>::mat4() noexcept
: column0(T(1), T(0), T(0), T(0))
, column1(T(0), T(1), T(0), T(0))
, column2(T(0), T(0), T(1), T(0))
, column3(T(0), T(0), T(0), T(1))
{
}
template<typename T>
constexpr mat4<T>::mat4(math::ZUninitialized) noexcept
{
}
template<typename T>
constexpr mat4<T>::mat4(T value) noexcept
: column0(value, value, value, value)
, column1(value, value, value, value)
, column2(value, value, value, value)
, column3(value, value, value, value)
{
TL_PLAIN_ASSERT(is_finite(value));
}
template<typename T>
constexpr mat4<T>::mat4(T v0, T v1, T v2, T v3,
T v4, T v5, T v6, T v7,
T v8, T v9, T v10, T v11,
T v12, T v13, T v14, T v15) noexcept
: column0(v0, v1, v2, v3)
, column1(v4, v5, v6, v7)
, column2(v8, v9, v10, v11)
, column3(v12, v13, v14, v15)
{
TL_PLAIN_ASSERT(is_finite(column0) &&
is_finite(column1) &&
is_finite(column2) &&
is_finite(column3));
}
template<typename T>
constexpr mat4<T>::mat4(vec4<T> const& column0, vec4<T> const& column1, vec4<T> const& column2, vec4<T> const& column3) noexcept
: column0(column0)
, column1(column1)
, column2(column2)
, column3(column3)
{
TL_PLAIN_ASSERT(is_finite(column0) &&
is_finite(column1) &&
is_finite(column2) &&
is_finite(column3));
}
///////////////////////////////////////////////////////////////////////////////
//methods
///////////////////////////////////////////////////////////////////////////////
template<typename T>
constexpr vec4<T> mat4<T>::get_row(size_t row) const noexcept
{
TL_PLAIN_ASSERT(row < 4);
const T* m = data();
return vec4<T>(m[row + 0], m[row + 4], m[row + 8], m[row + 12]);
}
template<typename T>
constexpr void mat4<T>::set_row(size_t row, vec4<T> const& v) noexcept
{
TL_PLAIN_ASSERT(is_finite(v));
TL_PLAIN_ASSERT(row < 4);
T* m = data();
m[row + 0] = v.x;
m[row + 4] = v.y;
m[row + 8] = v.z;
m[row + 12] = v.w;
}
template<typename T>
constexpr vec4<T> const& mat4<T>::get_column(size_t column) const noexcept
{
TL_PLAIN_ASSERT(column < column_count);
size_t idx = column * row_count;
const T* m = data();
return *reinterpret_cast<vec4<T> const*>(&m[idx]);
}
template<typename T>
constexpr void mat4<T>::set_column(size_t column, vec4<T> const& v) noexcept
{
TL_PLAIN_ASSERT(is_finite(v));
TL_PLAIN_ASSERT(column < column_count);
size_t idx = column * row_count;
T* m = data();
*reinterpret_cast<vec4<T>*>(&m[idx]) = v;
}
template<typename T>
constexpr vec4<T> const& mat4<T>::get_axis_x() const noexcept
{
return get_column(0);
}
template<typename T>
constexpr vec4<T> const& mat4<T>::get_axis_y() const noexcept
{
return get_column(1);
}
template<typename T>
constexpr vec4<T> const& mat4<T>::get_axis_z() const noexcept
{
return get_column(2);
}
template<typename T>
constexpr vec4<T> const& mat4<T>::get_axis_w() const noexcept
{
return get_column(3);
}
template<typename T>
constexpr void mat4<T>::set_axis_x(vec4<T> const& axis) noexcept
{
set_column(0, axis);
}
template<typename T>
constexpr void mat4<T>::set_axis_y(vec4<T> const& axis) noexcept
{
set_column(1, axis);
}
template<typename T>
constexpr void mat4<T>::set_axis_z(vec4<T> const& axis) noexcept
{
set_column(2, axis);
}
template<typename T>
constexpr void mat4<T>::set_axis_w(vec4<T> const& axis) noexcept
{
set_column(3, axis);
}
template<typename T>
constexpr T mat4<T>::determinant() const noexcept
{
const T* m = data();
T t0 = m[10] * m[15] - m[11] * m[14];
T t1 = m[6] * m[15] - m[7] * m[14];
T t2 = m[6] * m[11] - m[7] * m[10];
T t3 = m[2] * m[15] - m[3] * m[14];
T t4 = m[2] * m[11] - m[3] * m[10];
T t5 = m[2] * m[7] - m[3] * m[6];
T t6 = m[8] * m[13] - m[9] * m[12];
T t7 = m[4] * m[13] - m[5] * m[12];
T t8 = m[4] * m[9] - m[5] * m[8];
T t9 = m[0] * m[13] - m[1] * m[12];
T t10 = m[0] * m[9] - m[1] * m[8];
T t11 = m[0] * m[5] - m[1] * m[4];
return t0 * t11 - t1 * t10 + t2 * t9 + t3 * t8 - t4 * t7 + t5 * t6;
}
///////////////////////////////////////////////////////////////////////////////
// indexing operators
///////////////////////////////////////////////////////////////////////////////
template<typename T>
constexpr T* mat4<T>::data() noexcept
{
return (T*)&column0;
}
template<typename T>
constexpr T const* mat4<T>::data() const noexcept
{
return (T const*)&column0;
}
template<typename T>
constexpr T& mat4<T>::element(size_t column, size_t row) noexcept
{
TL_PLAIN_ASSERT(column < column_count&& row < row_count);
T* m = data();
return m[column * row_count + row];
}
template<typename T>
constexpr T const& mat4<T>::element(size_t column, size_t row) const noexcept
{
TL_PLAIN_ASSERT(column < column_count&& row < row_count);
const T* m = data();
return m[column * row_count + row];
}
template<typename T>
constexpr mat4<T> mat4<T>::operator*(mat4<T> const& other) const noexcept
{
mat4<T> ret;
return multiply(ret, *this, other);
}
template<typename T>
constexpr mat4<T> mat4<T>::operator+(mat4<T> const& other) const noexcept
{
mat4<T> ret;
return cwise::add(ret, *this, other);
}
template<typename T>
constexpr mat4<T> mat4<T>::operator-(mat4<T> const& other) const noexcept
{
mat4<T> ret;
return cwise::substract(ret, *this, other);
}
template<typename T>
constexpr mat4<T>& mat4<T>::operator*=(mat4<T> const& other) noexcept
{
mat4<T> a(*this);
return multiply(*this, a, other);
}
template<typename T>
constexpr mat4<T>& mat4<T>::operator+=(mat4<T> const& other) noexcept
{
return cwise::add(*this, *this, other);
}
template<typename T>
constexpr mat4<T>& mat4<T>::operator-=(mat4<T> const& other) noexcept
{
return cwise::substract(*this, *this, other);
}
template<typename T>
constexpr mat4<T> mat4<T>::operator*(T scalar) const noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
mat4<T> ret;
return cwise::multiply(ret, *this, scalar);
}
template<typename T>
constexpr mat4<T> mat4<T>::operator+(T scalar) const noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
mat4<T> ret;
return cwise::add(ret, *this, scalar);
}
template<typename T>
constexpr mat4<T> mat4<T>::operator-(T scalar) const noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
mat4<T> ret;
return cwise::substract(ret, *this, scalar);
}
template<typename T>
constexpr mat4<T>& mat4<T>::operator*=(T scalar) noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
return cwise::multiply(*this, *this, scalar);
}
template<typename T>
constexpr mat4<T>& mat4<T>::operator+=(T scalar) noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
return cwise::add(*this, *this, scalar);
}
template<typename T>
constexpr mat4<T>& mat4<T>::operator-=(T scalar) noexcept
{
TL_PLAIN_ASSERT(is_finite(scalar));
return cwise::substract(*this, *this, scalar);
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::mat4<T>>
{
std::size_t operator()(const math::mat4<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.column0);
tl::hash_and_combine(seed, p.column1);
tl::hash_and_combine(seed, p.column2);
tl::hash_and_combine(seed, p.column3);
return seed;
}
};
+31
View File
@@ -0,0 +1,31 @@
#pragma once
namespace math
{
///////////////////////////////////////////////////////////////////////////////
//! Oriented bounding box in R^3 space
template<typename T>
struct obb3
{
using vec3_t = vec3<T>;
/// Fast initializer, members will contain garbage
explicit obb3(ZUninitialized);
obb3();
obb3(const vec3_t& i_center, const vec3_t& i_half_extent, const vec3_t(&i_axes)[3]);
bool is_valid() const;
void get_vertices(vec3_t(&o_vertices)[8]) const;
//////////////////////////////////////////////////////////////////////////
// members
//////////////////////////////////////////////////////////////////////////
vec3_t center;
vec3_t half_extent;
vec3_t axes[3];
};
}//namespace
+61
View File
@@ -0,0 +1,61 @@
namespace math
{
///////////////////////////////////////////////////////////////////////////////
template<typename T> inline
obb3<T>::obb3(ZUninitialized tag)
: center(tag), half_extent(tag), axes({tag,tag,tag})
{}
template<typename T> inline
obb3<T>::obb3()
{
center = vec3_t::zero();
half_extent = vec3_t(1.f);
axes[0] = vec3_t(1.f);
axes[1] = vec3_t(1.f);
axes[2] = vec3_t(1.f);
}
template<typename T> inline
obb3<T>::obb3(const vec3_t& center, const vec3_t& half_extent, const vec3_t(&axes)[3])
: center(center)
, half_extent(half_extent)
, axes{axes[0], axes[1], axes[2]}
{
JTL_ASSERT(is_valid());
}
template<typename T> inline
bool obb3<T>::is_valid() const
{
return has_positive_sign(half_extent)
&& is_normalized(axes[0])
&& is_normalized(axes[1])
&& is_normalized(axes[2]);
}
template<typename T> inline
void obb3<T>::get_vertices(vec3_t(&o_vertices)[8]) const
{
const int numAxes = 3;
std::array<vec3_t, 3> half_side;
for (unsigned int d = 0; d < numAxes; ++d)
{
half_side[d] = half_extent[d] * axes[d];
}
const int numVertices = 8;
for (int i = 0; i < numVertices; ++i)
{
o_vertices[i] = center;
for (unsigned int d = 0, mask = 1; d < numAxes; ++d, mask <<= 1)
{
T sign = (i & mask ? (T)1 : (T)-1);
o_vertices[i] += sign * half_side[d];
}
}
}
///////////////////////////////////////////////////////////////////////////////
}//namespace
+103
View File
@@ -0,0 +1,103 @@
#pragma once
namespace math
{
//! Plane class with explicit formulation ax + by + cz + d =0
template <class T>
struct plane
{
typedef T value_t;
typedef plane<T> this_t;
///////////////////////////////////////////////////////////////////////////////
// constructors
///////////////////////////////////////////////////////////////////////////////
/// Constructs a plane with normal (0,0,1) and crossing origin
plane();
/// Warning - fast constructor, members will contain garbage
explicit plane(ZUninitialized);
plane(const vec3<T>& point, const vec3<T>& normal);
plane(const vec3<T>& point1, const vec3<T>& point2, const vec3<T>& point3);
///////////////////////////////////////////////////////////////////////////////
// operators
///////////////////////////////////////////////////////////////////////////////
bool operator==(const this_t& other) const;
bool operator!=(const this_t& other) const;
///////////////////////////////////////////////////////////////////////////////
// methods
///////////////////////////////////////////////////////////////////////////////
//! Gets a member point of the plane.
vec3<T> get_member_point() const;
///! Computes the inverse half space
this_t& invert();
//! Computes the signed distance to the point
T signed_distance(const vec3<T>& point) const;
#if JMATH_USE_DEPRECATED
//! Recalculates the distance from origin by applying a new member point to the plane.
void recalculate_d(const vec3<T>& MPoint);
//! Test if the triangle would be front or backfacing from any point.
/** Thus, this method assumes a camera position from
which the triangle is definitely visible when looking into
the given direction.
Note that this only works if the normal is Normalized.
Do not use this method with points as it will give wrong results!
\param lookDirection: Look direction.
\return True if the plane is front facing and
false if it is backfacing. */
bool is_front_facing(const vec3<T>& lookDirection) const;
//! Get the distance to a point.
/** Note that this only works if the normal is normalized. */
T get_distance_to(const vec3<T>& point) const;
//! Project a point on the plane.
vec3<T> project_point(const vec3<T>& point) const;
//! Get percentage of line between two points where an intersection with this plane happens.
/** Only useful if known that there is an intersection.
\param linePoint1 Point1 of the line to intersect with.
\param linePoint2 Point2 of the line to intersect with.
\return Where on a line between two points an intersection with this plane happened.
For example, 0.5 is returned if the intersection happened exactly in the middle of the two points.
*/
float get_known_intersection_with_line(const vec3<T>& linePoint1,const vec3<T>& linePoint2) const;
//! Enumeration for intersection relations of 3d objects
enum class RelationEnum
{
FRONT,
BACK,
ON_PLANE
};
//! Classifies the relation of a point to this plane.
/** \param point Point to classify its relation.
\return FRONT if the point is in front of the plane,
BACK if the point is behind of the plane, and
ON_PLANE if the point is within the plane. */
RelationEnum classify_point_relation(const vec3<T>& point) const;
///! Checks for plane AABB overlap
// Return values:
// 0: box is totally outside of the plane
// 1: box is totally inside of the plane
// 2: box is partially inside of the plane
RelationEnum overlap(const vec3<T>& boxCenter, vec3<T>& boxHalfsize) const;
#endif//JMATH_USE_DEPRECATED
///Plane equation Ax + By + Cz + D = 0
//! Normal of the plane. i.e., (A,B,C)
vec3<T> normal;
//! Distance from origin negated. i.e., D = -(A*x0 + B*y0 + C*z0)
T offset;
};
}
+66
View File
@@ -0,0 +1,66 @@
namespace math
{
template <class T>
inline plane<T>::plane()
: normal(0, 0, 1)
, offset(0)
{
}
template <class T>
inline plane<T>::plane(ZUninitialized tag) : normal(tag)
{
}
template <class T>
inline plane<T>::plane(const vec3<T>& ipoint, const vec3<T>& inormal)
: normal(inormal)
, offset(-dot(ipoint, normal))
{
TL_PLAIN_ASSERT(is_normalized(inormal));
}
template <class T>
inline plane<T>::plane(const vec3<T>& point1, const vec3<T>& point2, const vec3<T>& point3)
{
normal = normalized(cross(point2 - point1, point3 - point1));
TL_PLAIN_ASSERT(is_normalized(normal));
offset = -dot(point1, normal);
}
template <class T>
inline bool plane<T>::operator==(const plane<T>& other) const
{
return offset == other.offset && normal == other.normal;
}
template <class T>
inline bool plane<T>::operator!=(const plane<T>& other) const
{
return !(*this == other);
}
template <class T>
inline vec3<T> plane<T>::get_member_point() const
{
return normal * -offset;
}
template <class T>
plane<T>& plane<T>::invert()
{
this_t tmp = *this;
tmp.normal = -normal;
tmp.offset = -dot(tmp.normal, get_member_point());
*this = tmp;
return *this;
}
template <class T>
T plane<T>::signed_distance(const vec3<T>& point) const
{
return dot(normal, point) + offset;
}
}
+102
View File
@@ -0,0 +1,102 @@
#pragma once
#include <compare>
namespace math
{
template<typename T>
struct quat
{
typedef T value_t;
typedef quat<T> this_t;
static constexpr size_t element_count = 4;
template<class Policy = standard>
constexpr static quat<T> from_axis_x(T rotation) noexcept;
template<class Policy = standard>
constexpr static quat<T> from_axis_y(T rotation) noexcept;
template<class Policy = standard>
constexpr static quat<T> from_axis_z(T rotation) noexcept;
template<class Policy = standard>
constexpr static quat<T> from_angle_axis(T rotation, vec3<T> const& axis) noexcept;
template<class Policy = standard>
constexpr static quat<T> from_euler_xyz(vec3<T> const& euler) noexcept;
template<class Policy = standard>
constexpr static quat<T> from_euler_xzy(vec3<T> const& euler) noexcept;
template<class Policy = standard>
constexpr static quat<T> from_euler_yxz(vec3<T> const& euler) noexcept;
template<class Policy = standard>
constexpr static quat<T> from_euler_yzx(vec3<T> const& euler) noexcept;
template<class Policy = standard>
constexpr static quat<T> from_euler_zxy(vec3<T> const& euler) noexcept;
template<class Policy = standard>
constexpr static quat<T> from_euler_zyx(vec3<T> const& euler) noexcept;
template<class Policy = standard>
constexpr static quat<T> from_a_to_b(vec3<T> const& a, vec3<T> const& b) noexcept;
template<class Policy = standard>
constexpr static quat<T> from_a_to_b(quat<T> const& a, quat<T> const& b) noexcept;
constexpr quat() noexcept = default;
constexpr explicit quat(T v) noexcept;
constexpr quat(T x, T y, T z, T w) noexcept;
constexpr quat(quat<T> const&) noexcept = default;
constexpr quat& operator=(quat<T> const& other) noexcept = default;
constexpr T& operator[](size_t i) noexcept;
constexpr T const& operator[](size_t i) const noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
constexpr quat<T> operator+(quat<T> const& other) const noexcept;
constexpr quat<T>& operator+=(quat<T> const& other) noexcept;
constexpr quat<T> operator-(quat<T> const& other) const noexcept;
constexpr quat<T>& operator-=(quat<T> const& other) noexcept;
constexpr quat<T> operator*(quat<T> const& other) const noexcept;
constexpr quat<T>& operator*=(quat<T> const& other) noexcept;
constexpr this_t operator*(T s) const noexcept;
constexpr quat<T>& operator*=(T s) noexcept;
//! Negation (additive inverse) (-x,-y,-z,-w).
// A + (-A) == A - A == identity
constexpr quat<T> operator-() const noexcept;
//! Conjugation (spatial inverse) (-x,-y,-z,+w).
// A * (~A) == identity
constexpr quat<T> operator~() const noexcept;
template<class Policy = standard>
constexpr vec3<T> get_euler_xyz() const noexcept;
template<class Policy = standard>
constexpr vec3<T> get_euler_xzy() const noexcept;
template<class Policy = standard>
constexpr vec3<T> get_euler_yxz() const noexcept;
template<class Policy = standard>
constexpr vec3<T> get_euler_yzx() const noexcept;
template<class Policy = standard>
constexpr vec3<T> get_euler_zxy() const noexcept;
template<class Policy = standard>
constexpr vec3<T> get_euler_zyx() const noexcept;
template<class Policy = standard>
constexpr tl::pair<T, vec3<T>> get_angle_axis() const noexcept;
template<class Policy = standard>
constexpr quat<T>& normalize() noexcept;
template<class Policy = standard>
constexpr T length() const noexcept;
constexpr T length_sq() const noexcept;
T x = T(0);
T y = T(0);
T z = T(0);
T w = T(1);
};
}
+529
View File
@@ -0,0 +1,529 @@
namespace math
{
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_axis_x(T rotation) noexcept
{
T a, b;
math::sin_cos(rotation * T(0.5), a, b);
return { a, 0, 0, b };
}
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_axis_y(T rotation) noexcept
{
T a, b;
math::sin_cos(rotation * T(0.5), a, b);
return { 0, a, 0, b };
}
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_axis_z(T rotation) noexcept
{
T a, b;
math::sin_cos(rotation * T(0.5), a, b);
return { 0, 0, a, b };
}
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_angle_axis(T rotation, vec3<T> const& axis) noexcept
{
TL_PLAIN_ASSERT(is_equal(axis.length(), T(1), T(0.001)) || is_zero(rotation));
T s, w;
sin_cos<T, Policy>(rotation * T(0.5), s, w);
return { s * axis.x, s * axis.y, s * axis.z, w };
}
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_euler_xyz(vec3<T> const& euler) noexcept
{
vec3<T> a = euler * T(0.5);
vec3<T> s, c;
sin_cos<T, Policy>(a, s, c);
return
{
c.z * s.x * c.y + s.z * c.x * s.y,
c.z * c.x * s.y - s.z * s.x * c.y,
s.z * c.x * c.y + c.z * s.x * s.y,
c.z * c.x * c.y - s.z * s.x * s.y
};
}
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_euler_xzy(vec3<T> const& euler) noexcept
{
vec3<T> a = euler * T(0.5);
vec3<T> s, c;
sin_cos<T, Policy>(a, s, c);
return
{
c.z * s.x * c.y - s.z * c.x * s.y,
c.z * c.x * s.y - s.z * s.x * c.y,
s.z * c.x * c.y + c.z * s.x * s.y,
c.z * c.x * c.y + s.z * s.x * s.y,
};
}
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_euler_yxz(vec3<T> const& euler) noexcept
{
vec3<T> a = euler * T(0.5);
vec3<T> s, c;
sin_cos<T, Policy>(a, s, c);
return
{
c.z * s.x * c.y + s.z * c.x * s.y,
c.z * c.x * s.y - s.z * s.x * c.y,
s.z * c.x * c.y - c.z * s.x * s.y,
c.z * c.x * c.y + s.z * s.x * s.y,
};
}
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_euler_yzx(vec3<T> const& euler) noexcept
{
vec3<T> a = euler * T(0.5);
vec3<T> s, c;
sin_cos<T, Policy>(a, s, c);
return
{
c.z * s.x * c.y + s.z * c.x * s.y,
c.z * c.x * s.y + s.z * s.x * c.y,
s.z * c.x * c.y - c.z * s.x * s.y,
c.z * c.x * c.y - s.z * s.x * s.y,
};
}
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_euler_zxy(vec3<T> const& euler) noexcept
{
vec3<T> a = euler * T(0.5);
vec3<T> s, c;
sin_cos<T, Policy>(a, s, c);
return
{
c.z * s.x * c.y - s.z * c.x * s.y,
c.z * c.x * s.y + s.z * s.x * c.y,
s.z * c.x * c.y + c.z * s.x * s.y,
c.z * c.x * c.y - s.z * s.x * s.y,
};
}
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_euler_zyx(vec3<T> const& euler) noexcept
{
vec3<T> a = euler * T(0.5);
vec3<T> s, c;
sin_cos<T, Policy>(a, s, c);
return
{
c.z * s.x * c.y - s.z * c.x * s.y,
c.z * c.x * s.y + s.z * s.x * c.y,
s.z * c.x * c.y - c.z * s.x * s.y,
c.z * c.x * c.y + s.z * s.x * s.y,
};
}
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_a_to_b(vec3<T> const& a, vec3<T> const& b) noexcept
{
//see: http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors
TL_PLAIN_ASSERT(is_one(a.length()));
TL_PLAIN_ASSERT(is_one(b.length()));
const T cos_theta = dot(a, b);
const vec3<T> axis = cross(a, b);
if (dot(cos_theta) >= T(1) - tl::numeric_limits<T>::epsilon() * T(4))
{
//handle parallel vectors - cos ~ 1
const T value = cos_theta > (T)0 ? (T)0 : (T)1;
vec3<T> axis;
axis[cwise::min_component_index(abs(a))] = value; // coordinate axis most nearly orthogonal to "a"
return { axis.x, axis.y, axis.z, (T)1 - value };
}
else
{
//common case - non parallel - cos < 1
TL_PLAIN_ASSERT(math::length_sq(axis) > square((T)0.0002));
return normalized<T, Policy>(quat(axis.x, axis.y, axis.z, (T)1 + cos_theta));
}
}
template<typename T>
template<class Policy>
constexpr quat<T> quat<T>::from_a_to_b(quat<T> const& a, quat<T> const& b) noexcept
{
quat<T> inv_a;
math::inverse(a, inv_a); //this should never fail, quats are always invertible
return inv_a * b;
}
template<typename T>
constexpr quat<T>::quat(T v) noexcept : x(v), y(v), z(v), w(v) {}
template<typename T>
constexpr quat<T>::quat(T _x, T _y, T _z, T _w) noexcept : x(_x), y(_y), z(_z), w(_w) {}
template<typename T>
constexpr T& quat<T>::operator[](size_t i) noexcept
{
TL_PLAIN_ASSERT(i < element_count);
TL_PLAIN_ASSERT(&((T*)this)[0] == &x && &((T*)this)[1] == &y);
return ((T*)this)[i];
}
template<typename T>
constexpr T const& quat<T>::operator[](size_t i) const noexcept
{
TL_PLAIN_ASSERT(i < element_count);
TL_PLAIN_ASSERT(&((T*)this)[0] == &x && &((T*)this)[1] == &y);
return ((T*)this)[i];
}
template<typename T>
constexpr quat<T> quat<T>::operator+(quat<T> const& b) const noexcept
{
return { x + b.x, y + b.y, z + b.z, w + b.w };
}
template<typename T>
constexpr quat<T>& quat<T>::operator+=(quat<T> const& b) noexcept
{
x += b.x;
y += b.y;
z += b.z;
w += b.w;
return *this;
}
template<typename T>
constexpr quat<T> quat<T>::operator-(quat<T> const& b) const noexcept
{
return { x - b.x, y - b.y, z - b.z, w - b.w };
}
template<typename T>
constexpr quat<T>& quat<T>::operator-=(quat<T> const& b) noexcept
{
x -= b.x;
y -= b.y;
z -= b.z;
w -= b.w;
return *this;
}
template<typename T>
constexpr quat<T> quat<T>::operator*(quat<T> const& other) const noexcept
{
return
{
(other.x * w) + (other.w * x) + (other.z * y) - (other.y * z),
(other.y * w) + (other.w * y) + (other.x * z) - (other.z * x),
(other.z * w) + (other.w * z) + (other.y * x) - (other.x * y),
(other.w * w) - (other.x * x) - (other.y * y) - (other.z * z),
};
}
template<typename T>
constexpr quat<T>& quat<T>::operator*=(quat<T> const& other) noexcept
{
return (*this = (*this) * other);
}
template<typename T>
constexpr quat<T> quat<T>::operator*(T s) const noexcept
{
return { s * x, s * y, s * z, s * w };
}
template<typename T>
constexpr quat<T>& quat<T>::operator*=(T s) noexcept
{
x *= s;
y *= s;
z *= s;
w *= s;
return *this;
}
template<typename T>
constexpr quat<T> quat<T>::operator-() const noexcept
{
return { -x, -y, -z, -w };
}
template<typename T>
constexpr quat<T> quat<T>::operator~() const noexcept
{
return { -x, -y, -z, w };
}
template<typename T>
template<class Policy>
constexpr vec3<T> quat<T>::get_euler_xyz() const noexcept
{
T const s = T(2) * (z * x + w * y);
if (s < T(0.9999))
{
if (s > -T(0.9999))
{
return
{
atan2<T, Policy>(-T(2) * (z * y - w * x), T(1) - T(2) * (x * x + y * y)),
asin<T, Policy>(s),
atan2<T, Policy>(-T(2) * (x * y - w * z), T(1) - T(2) * (z * z + y * y)),
};
}
else
{
return
{
-atan2<T, Policy>(T(2) * (x * y + w * z), T(1) - T(2) * (z * z + x * x)),
-angle<T>::pi2,
0,
};
}
}
else
{
return
{
atan2<T, Policy>(T(2) * (x * y + w * z), T(1) - T(2) * (z * z + x * x)),
angle<T>::pi2,
0
};
}
}
template<typename T>
template<class Policy>
constexpr vec3<T> quat<T>::get_euler_xzy() const noexcept
{
T const s = -T(2) * (x * y - w * z);
if (s < T(0.9999))
{
if (s > -T(0.9999))
{
return
{
atan2<T, Policy>(T(2) * (z * y + w * x), T(1) - T(2) * (z * z + x * x)),
atan2<T, Policy>(T(2) * (z * x + w * y), T(1) - T(2) * (z * z + y * y)),
asin<T, Policy>(s),
};
}
else
{
return
{
0,
-atan2<T, Policy>(T(2) * (z * x - w * y), T(1) - T(2) * (x * x + y * y)),
-angle<T>::pi2,
};
}
}
else
{
return
{
0,
-atan2<T, Policy>(T(2) * (z * x - w * y), T(1) - T(2) * (x * x + y * y)),
angle<T>::pi2,
};
}
}
template<typename T>
template<class Policy>
constexpr vec3<T> quat<T>::get_euler_yxz() const noexcept
{
T const s = -T(2) * (z * y - w * x);
if (s < T(0.9999))
{
if (s > -T(0.9999))
{
return
{
asin<T, Policy>(s),
atan2<T, Policy>(T(2) * (z * x + w * y), T(1) - T(2) * (x * x + y * y)),
atan2<T, Policy>(T(2) * (x * y + w * z), T(1) - T(2) * (z * z + x * x)),
};
}
else
{
return
{
-angle<T>::pi2,
0,
atan2<T, Policy>(-T(2) * (y * x - w * z), T(1) - T(2) * (y * y + z * z)),
};
}
}
else
{
return
{
angle<T>::pi2,
0,
atan2<T, Policy>(-T(2) * (y * x - w * z), T(1) - T(2) * (y * y + z * z)),
};
}
}
template<typename T>
template<class Policy>
constexpr vec3<T> quat<T>::get_euler_yzx() const noexcept
{
T const s = T(2) * (x * y + w * z);
if (s < T(0.9999))
{
if (s > -T(0.9999))
{
return
{
atan2<T, Policy>(-T(2) * (z * y - w * x), T(1) - T(2) * (z * z + x * x)),
atan2<T, Policy>(-T(2) * (z * x - w * y), T(1) - T(2) * (z * z + y * y)),
asin<T, Policy>(s),
};
}
else
{
return
{
0,
-atan2<T, Policy>(T(2) * (z * y + w * x), T(1) - T(2) * (x * x + y * y)),
-angle<T>::pi2,
};
}
}
else
{
return
{
0,
atan2<T, Policy>(T(2) * (z * y + w * x), T(1) - T(2) * (x * x + y * y)),
angle<T>::pi2,
};
}
}
template<typename T>
template<class Policy>
constexpr vec3<T> quat<T>::get_euler_zxy() const noexcept
{
T const s = T(2) * (z * y + w * x);
if (s < T(0.9999))
{
if (s > -T(0.9999))
{
return
{
asin<T, Policy>(s),
atan2<T, Policy>(-T(2) * (z * x - w * y), T(1) - T(2) * (x * x + y * y)),
atan2<T, Policy>(-T(2) * (x * y - w * z), T(1) - T(2) * (z * z + x * x)),
};
}
else
{
return
{
-angle<T>::pi2,
0,
-atan2<T, Policy>(T(2) * (z * x + w * y), T(1) - T(2) * (z * z + y * y)),
};
}
}
else
{
return
{
angle<T>::pi2,
0,
atan2<T, Policy>(T(2) * (z * x + w * y), T(1) - T(2) * (z * z + y * y)),
};
}
}
template<typename T>
template<class Policy>
constexpr vec3<T> quat<T>::get_euler_zyx() const noexcept
{
T const s = -T(2) * (z * x - w * y);
if (s < T(0.9999))
{
if (s > -T(0.9999))
{
return
{
atan2<T, Policy>(T(2) * (z * y + w * x), T(1) - T(2) * (x * x + y * y)),
asin<T, Policy>(s),
atan2<T, Policy>(T(2) * (x * y + w * z), T(1) - T(2) * (z * z + y * y)),
};
}
else
{
return
{
0,
-angle<T>::pi2,
atan2<T, Policy>(-T(2) * (z * y - w * x), T(1) - T(2) * (z * z + x * x)),
};
}
}
else
{
return
{
0,
angle<T>::pi2,
-atan2<T, Policy>(-T(2) * (z * y - w * x), T(1) - T(2) * (z * z + x * x)),
};
}
}
template<typename T>
template<class Policy>
constexpr tl::pair<T, vec3<T>> quat<T>::get_angle_axis() const noexcept
{
T const w = clamp(w, T(-1), T(1));
T const scale = sqrt<T, Policy>(T(1) - w * w);
T angle = acos<T, Policy>(w) * T(2);
if (scale < tl::numeric_limits<T>::epsilon())
return tl::make_pair(angle, vec3<T>(x, y, z));
else
return tl::make_pair(angle, vec3<T>(x, y, z) / scale);
}
template<typename T>
template<class Policy>
constexpr quat<T>& quat<T>::normalize() noexcept
{
const T len_sq = x * x + y * y + z * z + w * w;
const T len_inv = inv_sqrt<T, Policy>(len_sq);
x *= len_inv;
y *= len_inv;
z *= len_inv;
w *= len_inv;
return *this;
}
template<typename T>
template<class Policy>
constexpr T quat<T>::length() const noexcept
{
return sqrt<T, Policy>(x * x + y * y + z * z + w * w);
}
template<typename T>
constexpr T quat<T>::length_sq() const noexcept
{
return x * x + y * y + z * z + w * w;
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::quat<T>>
{
std::size_t operator()(const math::quat<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.x);
tl::hash_and_combine(seed, p.y);
tl::hash_and_combine(seed, p.z);
tl::hash_and_combine(seed, p.w);
return seed;
}
};
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include <compare>
#include <tl/numeric_limits.h>
namespace math
{
template<typename T>
struct range
{
typedef T value_t;
typedef range<T> this_t;
constexpr range() noexcept = default;
constexpr range(const T& min, const T& max) noexcept;
constexpr range(const range<T>&) noexcept = default;
auto operator<=>(const this_t&) const noexcept = default;
bool operator==(const this_t&) const noexcept = default;
constexpr range<T>& operator=(const range<T>&) noexcept = default;
constexpr bool is_valid() const noexcept;
constexpr T get_center() const noexcept;
constexpr T get_extent() const noexcept;
constexpr T get_half_extent() const noexcept;
T min = T(tl::numeric_limits<T>::lowest());
T max = T(tl::numeric_limits<T>::max());
};
}
+58
View File
@@ -0,0 +1,58 @@
namespace math
{
template<typename T>
constexpr range<T>::range(const T& min, const T& max) noexcept
: min(min)
, max(max)
{
TL_PLAIN_ASSERT(is_gequal(max, min));
}
template<typename T>
constexpr bool range<T>::is_valid() const noexcept
{
return is_gequal(max, min);
}
template<typename T>
constexpr T range<T>::get_center() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
if constexpr (std::is_floating_point_v<T>)
return (min + max) * T(0.5);
else
return (min + max) / T(2);
}
template<typename T>
constexpr T range<T>::get_extent() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
return max - min;
}
template<typename T>
constexpr T range<T>::get_half_extent() const noexcept
{
if constexpr (std::is_floating_point_v<T>)
return get_extent() * T(0.5);
else
return get_extent() / T(2);
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::range<T>>
{
std::size_t operator()(const math::range<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.min);
tl::hash_and_combine(seed, p.max);
return seed;
}
};
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <compare>
namespace math
{
template<typename T>
struct ray2
{
typedef T value_t;
typedef ray2<T> this_t;
constexpr ray2() noexcept = default;
constexpr ray2(const vec2<T>&start, const vec2<T>&direction) noexcept;
constexpr ray2(const ray2<T>&) noexcept = default;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
constexpr ray2<T>& operator=(const ray2<T>&) noexcept = default;
constexpr bool is_valid() const noexcept;
//distance has to be positive
constexpr vec2<T> get_point(T distance) const noexcept;
constexpr void translate(const vec2<T>&offset) noexcept;
vec2<T> origin;
vec2<T> direction;
};
}
+48
View File
@@ -0,0 +1,48 @@
namespace math
{
template<typename T>
constexpr ray2<T>::ray2(const vec2<T>& start, const vec2<T>& direction) noexcept
: origin(start)
, direction(direction)
{
}
template<typename T>
constexpr bool ray2<T>::is_valid() const noexcept
{
return !is_zero(direction);
}
template<typename T>
constexpr vec2<T> ray2<T>::get_point(T distance) const noexcept
{
TL_PLAIN_ASSERT(is_valid());
TL_PLAIN_ASSERT(is_positive(distance));
return origin + direction * distance;
}
template<typename T>
constexpr void ray2<T>::translate(const vec2<T>& offset) noexcept
{
TL_PLAIN_ASSERT(is_valid());
origin += offset;
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::ray2<T>>
{
std::size_t operator()(const math::ray2<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.origin);
tl::hash_and_combine(seed, p.direction);
return seed;
}
};
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#include <compare>
namespace math
{
template<typename T>
struct ray3
{
typedef T value_t;
typedef ray3<T> this_t;
constexpr ray3() noexcept = default;
constexpr ray3(const vec3<T>& start, const vec3<T>& direction) noexcept;
constexpr ray3(const ray3<T>&) noexcept = default;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
constexpr ray3<T>& operator=(const ray3<T>&) noexcept = default;
constexpr bool is_valid() const noexcept;
constexpr vec3<T> get_point(T distance) const noexcept;
constexpr void translate(const vec3<T>& offset) noexcept;
vec3<T> origin;
vec3<T> direction;
};
}
+46
View File
@@ -0,0 +1,46 @@
namespace math
{
template<typename T>
constexpr ray3<T>::ray3(const vec3<T>& start, const vec3<T>& direction) noexcept
: origin(start)
, direction(direction)
{
}
template<typename T>
constexpr bool ray3<T>::is_valid() const noexcept
{
return !is_zero(direction);
}
template<typename T>
constexpr vec3<T> ray3<T>::get_point(T distance) const noexcept
{
TL_PLAIN_ASSERT(is_valid());
return origin + direction * distance;
}
template<typename T>
constexpr void ray3<T>::translate(const vec3<T>& offset) noexcept
{
TL_PLAIN_ASSERT(is_valid());
origin += offset;
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::ray3<T>>
{
std::size_t operator()(const math::ray3<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.origin);
tl::hash_and_combine(seed, p.direction);
return seed;
}
};
+67
View File
@@ -0,0 +1,67 @@
#pragma once
#include <compare>
#include <tl/numeric_limits.h>
namespace math
{
/*
* Rectangle class to be used in 2D where Y goes down.
* Due to this (Y goes down), the bottom_right corner has a higher Y than the top Y for a valid rect
*/
template<typename T>
struct rect
{
typedef T value_t;
typedef rect<T> this_t;
constexpr rect() noexcept = default;
constexpr rect(const vec2<T>& top_left, const vec2<T>& bottom_right) noexcept;
constexpr rect(T x1, T y1, T x2, T y2) noexcept;
constexpr rect(const rect<T>&) noexcept = default;
constexpr rect<T>& operator=(const rect<T>&) noexcept = default;
constexpr bool is_valid() const noexcept;
constexpr bool is_empty() const noexcept;
constexpr T get_area() const noexcept;
constexpr T get_width() const noexcept;
constexpr T get_height() const noexcept;
constexpr vec2<T> get_center() const noexcept;
constexpr vec2<T> get_top_right_corner() const noexcept;
constexpr vec2<T> get_bottom_left_corner() const noexcept;
constexpr vec2<T> get_extent() const noexcept;
constexpr vec2<T> get_half_extent() const noexcept;
constexpr void translate(const vec2<T>& offset) noexcept;
//size must be positive
constexpr void grow(const T& size) noexcept;
constexpr void grow(const vec2<T>& size) noexcept;
//size must be positive
constexpr void shrink(const T& size) noexcept;
constexpr void shrink(const vec2<T>& size) noexcept;
//size can be positive or negative to grow or shrink
//Only useful for integral / float types. Unsigned types will fail with this
constexpr void resize(const T& size) noexcept;
constexpr void resize(const vec2<T>& size) noexcept;
//only valid for floating point types
constexpr void scale(T scale) noexcept;
constexpr void scale(const vec2<T>& size) noexcept;
constexpr void add(const vec2<T>& p) noexcept;
constexpr void add(const rect<T>& other) noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
vec2<T> top_left = vec2<T>(tl::numeric_limits<T>::max());
vec2<T> bottom_right = vec2<T>(tl::numeric_limits<T>::lowest());
};
}
+243
View File
@@ -0,0 +1,243 @@
namespace math
{
template<typename T>
constexpr rect<T>::rect(const vec2<T>& top_left, const vec2<T>& bottom_right) noexcept
: top_left(top_left)
, bottom_right(bottom_right)
{
TL_PLAIN_ASSERT(is_lequal(top_left, bottom_right));
}
template<typename T>
constexpr rect<T>::rect(T x1, T y1, T x2, T y2) noexcept
: top_left(x1, y1)
, bottom_right(x2, y2)
{
TL_PLAIN_ASSERT(is_lequal(top_left, bottom_right));
}
template<typename T>
constexpr bool rect<T>::is_valid() const noexcept
{
return is_gequal(bottom_right, top_left);
}
template<typename T>
constexpr bool rect<T>::is_empty() const noexcept
{
return is_equal(top_left, bottom_right);
}
template<typename T>
constexpr T rect<T>::get_area() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
vec2<T> ex = get_extent();
return ex.x * ex.y;
}
template<typename T>
constexpr T rect<T>::get_width() const noexcept
{
return get_extent().x;
}
template<typename T>
constexpr T rect<T>::get_height() const noexcept
{
return get_extent().y;
}
template<typename T>
constexpr vec2<T> rect<T>::get_center() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
if constexpr (std::is_floating_point_v<T>)
return (top_left + bottom_right) * T(0.5);
else
return (top_left + bottom_right) / T(2);
}
template<typename T>
constexpr vec2<T> rect<T>::get_top_right_corner() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
return { bottom_right.x, top_left.y };
}
template<typename T>
constexpr vec2<T> rect<T>::get_bottom_left_corner() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
return { top_left.x, bottom_right.y };
}
template<typename T>
constexpr vec2<T> rect<T>::get_extent() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
return bottom_right - top_left;
}
template<typename T>
constexpr vec2<T> rect<T>::get_half_extent() const noexcept
{
TL_PLAIN_ASSERT(is_valid());
if constexpr (std::is_floating_point_v<T>)
return (bottom_right - top_left) * T(0.5);
else
return (bottom_right - top_left) / T(2);
}
template<typename T>
constexpr void rect<T>::translate(const vec2<T>& offset) noexcept
{
TL_PLAIN_ASSERT(is_valid());
top_left += offset;
bottom_right += offset;
}
template<typename T>
constexpr void rect<T>::grow(const T& size) noexcept
{
TL_PLAIN_ASSERT(is_positive(size));
TL_PLAIN_ASSERT(is_valid());
vec2<T> s1;
if constexpr (std::is_floating_point_v<T>)
s1 = size * T(0.5);
else
s1 = size / T(2);
vec2<T> s2 = size - s1;
top_left -= s1;
bottom_right += s2;
}
template<typename T>
constexpr void rect<T>::grow(const vec2<T>& size) noexcept
{
TL_PLAIN_ASSERT(is_positive(size));
TL_PLAIN_ASSERT(is_valid());
vec2<T> s1;
if constexpr (std::is_floating_point_v<T>)
s1 = size * T(0.5);
else
s1 = size / T(2);
vec2<T> s2 = size - s1;
top_left -= s1;
bottom_right += s2;
}
template<typename T>
constexpr void rect<T>::shrink(const T& size) noexcept
{
TL_PLAIN_ASSERT(is_positive(size));
TL_PLAIN_ASSERT(is_valid());
vec2<T> s1;
if constexpr (std::is_floating_point_v<T>)
s1 = size * T(0.5);
else
s1 = size / T(2);
vec2<T> s2 = size - s1;
top_left += s1;
bottom_right -= s2;
}
template<typename T>
constexpr void rect<T>::shrink(const vec2<T>& size) noexcept
{
TL_PLAIN_ASSERT(is_positive(size));
vec2<T> s1;
if constexpr (std::is_floating_point_v<T>)
s1 = size * T(0.5);
else
s1 = size / T(2);
vec2<T> s2 = size - s1;
top_left += s1;
bottom_right -= s2;
}
template<typename T>
constexpr void rect<T>::resize(const T& size) noexcept
{
TL_PLAIN_ASSERT(is_valid());
vec2<T> s1;
if constexpr (std::is_floating_point_v<T>)
s1 = size * T(0.5);
else
s1 = size / T(2);
vec2<T> s2 = size - s1;
top_left -= s1;
bottom_right += s2;
}
template<typename T>
constexpr void rect<T>::resize(const vec2<T>& size) noexcept
{
TL_PLAIN_ASSERT(is_valid());
vec2<T> s1;
if constexpr (std::is_floating_point_v<T>)
s1 = size * T(0.5);
else
s1 = size / T(2);
vec2<T> s2 = size - s1;
top_left -= s1;
bottom_right += s2;
}
template<typename T>
constexpr void rect<T>::scale(T scale) noexcept
{
TL_PLAIN_ASSERT(is_positive(scale));
TL_PLAIN_ASSERT(is_valid());
const vec2<T> center = get_center();
T half_scale;
if constexpr (std::is_floating_point_v<T>)
half_scale = scale * T(0.5);
else
half_scale = scale / T(2);
vec2<T> ex = get_extent();
vec2<T> half_ex = ex * half_scale;
top_left = center - half_ex;
bottom_right = center + half_ex;
}
template<typename T>
constexpr void rect<T>::scale(const vec2<T>& size) noexcept
{
TL_PLAIN_ASSERT(is_positive(size));
TL_PLAIN_ASSERT(is_valid());
const vec2<T> center = get_center();
T half_scale;
if constexpr (std::is_floating_point_v<T>)
half_scale = size * T(0.5);
else
half_scale = size / T(2);
vec2<T> ex = get_extent();
vec2<T> half_ex = ex * half_scale;
top_left = center - half_ex;
bottom_right = center + half_ex;
}
template<typename T>
constexpr void rect<T>::add(const vec2<T>& p) noexcept
{
top_left = math::min(top_left, p);
bottom_right = math::max(bottom_right, p);
}
template<typename T>
constexpr void rect<T>::add(const rect<T>& other) noexcept
{
add(other.top_left);
add(other.bottom_right);
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::rect<T>>
{
std::size_t operator()(const math::rect<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.top_left);
tl::hash_and_combine(seed, p.bottom_right);
return seed;
}
};
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include <compare>
namespace math
{
template<typename T> struct vec2;
template<typename T>
struct rigid2
{
typedef T value_t;
typedef rigid2<T> this_t;
constexpr rigid2() noexcept = default;
constexpr rigid2(rigid2<T> const& other) noexcept = default;
constexpr explicit rigid2(vec2<T> const& translation) noexcept;
constexpr rigid2(vec2<T> const& translation, T rotation) noexcept;
constexpr rigid2<T> operator*(rigid2<T> const& other) const noexcept;
constexpr rigid2<T>& operator*=(rigid2<T> const& other) noexcept;
constexpr rigid2<T>& post_translate(vec2<T> const& trans) noexcept;
constexpr rigid2<T>& post_rotate(T rotation) noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
vec2<T> translation;
T rotation = T(0); /// rotation angle in radians
};
}
+63
View File
@@ -0,0 +1,63 @@
namespace math
{
template<typename T>
constexpr rigid2<T>::rigid2(vec2<T> const& translation) noexcept
: translation(translation)
{
}
template<typename T>
constexpr rigid2<T>::rigid2(vec2<T> const& translation, T rotation) noexcept
: translation(translation)
, rotation(rotation)
{
}
template<typename T>
constexpr rigid2<T>& rigid2<T>::post_translate(vec2<T> const& trans) noexcept
{
translation += rotate(rotation, trans);
return *this;
}
template<typename T>
constexpr rigid2<T>& rigid2<T>::post_rotate(T rotation) noexcept
{
rotation += rotation;
return *this;
}
template<typename T>
constexpr rigid2<T> rigid2<T>::operator*(rigid2<T> const& other) const noexcept
{
rigid2<T> ret;
multiply(ret, *this, other);
return ret;
}
template<typename T>
constexpr rigid2<T>& rigid2<T>::operator*=(rigid2<T> const& other) noexcept
{
rigid2<T> a(*this);
return multiply(*this, a, other);
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::rigid2<T>>
{
std::size_t operator()(const math::rigid2<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.translation);
tl::hash_and_combine(seed, p.rotation);
return seed;
}
};
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include <compare>
namespace math
{
template<typename T> struct vec3;
template<typename T> struct quat;
template<typename T>
struct rigid3
{
typedef T value_t;
typedef rigid3<T> this_t;
constexpr rigid3() noexcept = default;
constexpr rigid3(rigid3<T> const& other) noexcept = default;
constexpr explicit rigid3(vec3<T> const& translation) noexcept;
constexpr rigid3(vec3<T> const& translation, quat<T> const& rotation) noexcept;
constexpr rigid3<T> operator*(rigid3<T> const& other) const noexcept;
constexpr rigid3<T>& operator*=(rigid3<T> const& other) noexcept;
constexpr rigid3<T>& post_translate(vec3<T> const& trans) noexcept;
constexpr rigid3<T>& post_rotate(quat<T> const& rotation) noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
vec3<T> translation;
quat<T> rotation;
};
}
+62
View File
@@ -0,0 +1,62 @@
namespace math
{
template<typename T>
constexpr rigid3<T>::rigid3(vec3<T> const& translation) noexcept
: translation(translation)
{
}
template<typename T>
constexpr rigid3<T>::rigid3(vec3<T> const& translation, quat<T> const& rotation) noexcept
: translation(translation)
, rotation(rotation)
{
}
template<typename T>
constexpr rigid3<T>& rigid3<T>::post_translate(vec3<T> const& trans) noexcept
{
translation += rotate(rotation, trans);
return *this;
}
template<typename T>
constexpr rigid3<T>& rigid3<T>::post_rotate(quat<T> const& rotation) noexcept
{
rotation *= rotation;
return *this;
}
template<typename T>
constexpr rigid3<T> rigid3<T>::operator*(rigid3<T> const& other) const noexcept
{
rigid3<T> ret;
multiply(ret, *this, other);
return ret;
}
template<typename T>
constexpr rigid3<T>& rigid3<T>::operator*=(rigid3<T> const& other) noexcept
{
rigid3<T> a(*this);
return multiply(*this, a, other);
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::rigid3<T>>
{
std::size_t operator()(const math::rigid3<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.translation);
tl::hash_and_combine(seed, p.rotation);
return seed;
}
};
+40
View File
@@ -0,0 +1,40 @@
#pragma once
#include <compare>
namespace math
{
template<typename T>
struct segment2
{
typedef T value_t;
typedef segment2<T> this_t;
constexpr segment2() noexcept = default;
constexpr segment2(T x1, T y1, T x2, T y2) noexcept;
constexpr segment2(const vec2<T>& start, const vec2<T>& end) noexcept;
constexpr segment2(const segment2<T>&) noexcept = default;
constexpr segment2<T>& operator=(const segment2<T>&) noexcept = default;
constexpr bool is_empty() const noexcept;
constexpr vec2<T> get_direction() const noexcept;
constexpr vec2<T> get_center() const noexcept;
constexpr T length() const noexcept;
constexpr T length_sq() const noexcept;
constexpr vec2<T> get_point(T t) const noexcept;
constexpr void translate(const vec2<T>& offset) noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
vec2<T> start;
vec2<T> end;
};
}
+77
View File
@@ -0,0 +1,77 @@
namespace math
{
template<typename T>
constexpr segment2<T>::segment2(T x1, T y1, T x2, T y2) noexcept
: start(x1, y2)
, end(x2, y2)
{
}
template<typename T>
constexpr segment2<T>::segment2(const vec2<T>& start, const vec2<T>& end) noexcept
: start(start)
, end(end)
{
}
template<typename T>
constexpr bool segment2<T>::is_empty() const noexcept
{
return is_equal(start, end);
}
template<typename T>
constexpr vec2<T> segment2<T>::get_direction() const noexcept
{
return normalized(end - start);
}
template<typename T>
constexpr vec2<T> segment2<T>::get_center() const noexcept
{
if constexpr (std::is_floating_point_v<T>)
return (start + end) * T(0.5);
else
return (start + end) / T(2);
}
template<typename T>
constexpr T segment2<T>::length() const noexcept
{
return distance(end, start);
}
template<typename T>
constexpr T segment2<T>::length_sq() const noexcept
{
return distance_sq(end, start);
}
template<typename T>
constexpr vec2<T> segment2<T>::get_point(T t) const noexcept
{
return lerp(start, end, t);
}
template<typename T>
constexpr void segment2<T>::translate(const vec2<T>& offset) noexcept
{
start += offset;
end += offset;
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::segment2<T>>
{
std::size_t operator()(const math::segment2<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.start);
tl::hash_and_combine(seed, p.end);
return seed;
}
};
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <compare>
namespace math
{
template<typename T>
struct segment3
{
typedef T value_t;
typedef segment3<T> this_t;
constexpr segment3() noexcept = default;
constexpr segment3(const vec3<T>& start, const vec3<T>& end) noexcept;
constexpr segment3(const segment3<T>&) noexcept = default;
constexpr segment3<T>& operator=(const segment3<T>&) noexcept = default;
constexpr bool is_empty() const noexcept;
constexpr vec3<T> get_direction() const noexcept;
constexpr vec3<T> get_center() const noexcept;
constexpr T length() const noexcept;
constexpr T length_sq() const noexcept;
constexpr vec3<T> get_point(T t) const noexcept;
constexpr void translate(const vec3<T>& offset) noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
vec3<T> start;
vec3<T> end;
};
}
+70
View File
@@ -0,0 +1,70 @@
namespace math
{
template<typename T>
constexpr segment3<T>::segment3(const vec3<T>& start, const vec3<T>& end) noexcept
: start(start)
, end(end)
{
}
template<typename T>
constexpr bool segment3<T>::is_empty() const noexcept
{
return is_equal(start, end);
}
template<typename T>
constexpr vec3<T> segment3<T>::get_direction() const noexcept
{
return normalized(end - start);
}
template<typename T>
constexpr vec3<T> segment3<T>::get_center() const noexcept
{
if constexpr (std::is_floating_point_v<T>)
return (start + end) * T(0.5);
else
return (start + end) / T(2);
}
template<typename T>
constexpr T segment3<T>::length() const noexcept
{
return distance(end, start);
}
template<typename T>
constexpr T segment3<T>::length_sq() const noexcept
{
return distance_sq(end, start);
}
template<typename T>
constexpr vec3<T> segment3<T>::get_point(T t) const noexcept
{
return lerp(start, end, t);
}
template<typename T>
constexpr void segment3<T>::translate(const vec3<T>& offset) noexcept
{
start += offset;
end += offset;
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::segment3<T>>
{
std::size_t operator()(const math::segment3<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.start);
tl::hash_and_combine(seed, p.end);
return seed;
}
};
+64
View File
@@ -0,0 +1,64 @@
#pragma once
namespace math
{
//! Axis aligned bounding box in 3d dimensional space.
template<typename T>
struct sphere
{
typedef T value_t;
typedef sphere<T> this_t;
static const value_t& invalid_radius();
///////////////////////////////////////////////////////////////////////////////
// constructors
///////////////////////////////////////////////////////////////////////////////
explicit sphere(ZUninitialized tag);
sphere();
explicit sphere(const vec3<T>& center, T radius = T(0));
///////////////////////////////////////////////////////////////////////////////
// methods
///////////////////////////////////////////////////////////////////////////////
//!@return true iff the box is initialized (any test for containment will be false)
bool is_valid() const;
//! Get the volume enclosed by the sphere in cubic units
T get_volume() const;
//! Get the surface area of the sphere in squared units
T get_area() const;
///////////////////////////////////////////////////////////////////////////////
// containment
///////////////////////////////////////////////////////////////////////////////
///@param p: Point to be included in the sphere (will grow accordingly).
void merge(const vec3<T>& p);
///@param s: Sphere to be included in this sphere (will grow accordingly).
void merge(const sphere<T>& b);
///////////////////////////////////////////////////////////////////////////////
// operators
///////////////////////////////////////////////////////////////////////////////
bool operator==(const sphere<T>& other) const;
bool operator!=(const sphere<T>& other) const;
///////////////////////////////////////////////////////////////////////////////
// members
///////////////////////////////////////////////////////////////////////////////
vec3<T> center;
T radius;
};
///////////////////////////////////////////////////////////////////////////////
}//namespace math
+114
View File
@@ -0,0 +1,114 @@
namespace math
{
///////////////////////////////////////////////////////////////////////////////
// constructors
///////////////////////////////////////////////////////////////////////////////
template<typename T>
const typename sphere<T>::value_t& sphere<T>::invalid_radius()
{
static value_t value(-limits<T>::infinity());
return value;
}
template<typename T>
sphere<T>::sphere(ZUninitialized tag) : center(tag)
{
}
template<typename T>
sphere<T>::sphere() : center(constants<T>::zero()), radius(invalid_radius())
{
}
template<typename T>
sphere<T>::sphere(const vec3<T>& _center, T _radius) : center(_center), radius(_radius)
{
JTL_ASSERT(radius >= T(0));
}
///////////////////////////////////////////////////////////////////////////////
// methods
///////////////////////////////////////////////////////////////////////////////
template<typename T>
void sphere<T>::merge(const vec3<T>& p)
{
if (radius != invalid_radius())
{
const vec3<T> pc = p - center;
const value_t pc_len2 = length_sq(pc);
if (pc_len2 > square(radius))
{// point is outside of the sphere
const value_t pc_len = std::sqrt(pc_len2);
radius = constants<T>::half() * (radius + pc_len);
center = center + (pc_len - radius) / pc_len * pc;
}
}
else
{// the empty sphere becomes the point
center = p;
radius = constants<T>::zero();
}
}
template<typename T>
void sphere<T>::merge(const sphere<T>& b)
{
vec3<T> c1c2 = b.center - center;
value_t c1c2_len2 = length_sq(c1c2);
value_t dr = b.radius - radius;
if (square(dr) >= c1c2_len2)
{
if (is_positive(dr))
{// b contains this
*this = b;
}
}
else
{
value_t c1c2_len = sqrt(c1c2_len2);
if (is_positive(c1c2_len)) {
center += (c1c2_len + dr) / (constants<T>::two() * c1c2_len) * c1c2;
}
radius = constants<T>::half() * (c1c2_len + radius + b.radius);
}
}
template<typename T>
bool sphere<T>::is_valid() const
{
return !is_negative(radius);
}
template<typename T>
T sphere<T>::get_volume() const
{
return constants<T>::pi() * radius*radius*radius * T(4) / T(3);
}
template<typename T>
T sphere<T>::get_area() const
{
return T(4) * constants<T>::pi() * radius*radius;
}
///////////////////////////////////////////////////////////////////////////////
// operators
///////////////////////////////////////////////////////////////////////////////
template<typename T>
bool sphere<T>::operator==(const sphere<T>& other) const
{
return (center == other.center && radius == other.radius);
}
template<typename T>
bool sphere<T>::operator!=(const sphere<T>& other) const
{
return !(*this == other);
}
}//namespace math
+62
View File
@@ -0,0 +1,62 @@
#pragma once
#include <compare>
namespace math
{
template<typename T> struct vec2;
template<typename T> struct mat2;
// mat3 layout trans2 layout
// 0 3 6 0 2 tx
// 1 4 7 -> 1 3 ty
// 2 5 8
// the last row is always constant (0 0 1) for the trans
template<typename T>
struct trans2
{
typedef T value_t;
using this_t = trans2<T>;
constexpr trans2() noexcept = default;
constexpr explicit trans2(math::ZUninitialized) noexcept;
constexpr trans2(trans2<T> const&) noexcept = default;
constexpr explicit trans2(vec2<T> const& translation) noexcept;
constexpr trans2(vec2<T> const& translation, T rotation) noexcept;
constexpr trans2(vec2<T> const& translation, T rotation, vec2<T> const& scale) noexcept;
constexpr trans2(vec2<T> const& translation, mat2<T> const& rotation_scale) noexcept;
constexpr trans2(vec2<T> const& translation, mat2<T> const& rotation_scale, vec2<T> const& scale) noexcept;
constexpr trans2<T>& operator=(trans2<T> const&) = default;
constexpr trans2<T> operator*(trans2<T> const& other) const noexcept;
constexpr trans2<T>& operator*=(trans2<T> const& other) noexcept;
constexpr trans2<T>& post_scale(vec2<T> const& scale) noexcept;
constexpr trans2<T>& post_translate(vec2<T> const& trans) noexcept;
constexpr vec2<T> const& get_axis_x() const noexcept;
constexpr trans2<T>& set_axis_x(vec2<T> const& axis) noexcept;
constexpr vec2<T> const& get_axis_y() const noexcept;
constexpr trans2<T>& set_axis_y(vec2<T> const& axis) noexcept;
template<class Policy = standard>
constexpr vec2<T> get_scale() const noexcept;
constexpr trans2<T>& set_scale(vec2<T> const& scale) noexcept;
constexpr trans2<T>& set_rotation_scale(T rotation) noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
vec2<T> translation;
mat2<T> rotation_scale;
};
}
+124
View File
@@ -0,0 +1,124 @@
namespace math
{
template<typename T>
constexpr trans2<T>::trans2(math::ZUninitialized) noexcept
: rotation_scale(math::uninitialized)
{
}
template<typename T>
constexpr trans2<T>::trans2(vec2<T> const& translation) noexcept
: translation(translation)
{
}
template<typename T>
constexpr trans2<T>::trans2(vec2<T> const& translation, T rotation) noexcept
: trans2(translation, mat2<T>::from_rotation(rotation))
{
}
template<typename T>
constexpr trans2<T>::trans2(vec2<T> const& translation, T rotation, vec2<T> const& scale) noexcept
: trans2(translation, mat2<T>::from_rotation(rotation), scale)
{
}
template<typename T>
constexpr trans2<T>::trans2(vec2<T> const& translation, mat2<T> const& rotation_scale, vec2<T> const& scale) noexcept
: translation(translation)
, rotation_scale(rotation_scale)
{
post_scale(scale);
}
template<typename T>
constexpr trans2<T>::trans2(vec2<T> const& translation, mat2<T> const& rotation_scale) noexcept
: translation(translation)
, rotation_scale(rotation_scale)
{
}
template<typename T>
constexpr vec2<T> const& trans2<T>::get_axis_x() const noexcept
{
return rotation_scale.column0;
}
template<typename T>
constexpr vec2<T> const& trans2<T>::get_axis_y() const noexcept
{
return rotation_scale.column1;
}
template<typename T>
template<class Policy>
constexpr vec2<T> trans2<T>::get_scale() const noexcept
{
return vec2<T>(get_axis_x().template length<Policy>(), get_axis_y().template length<Policy>());
}
template<typename T>
constexpr trans2<T>& trans2<T>::set_axis_x(vec2<T> const& axis) noexcept
{
rotation_scale.set_axis_x(axis);
return *this;
}
template<typename T>
constexpr trans2<T>& trans2<T>::set_axis_y(vec2<T> const& axis) noexcept
{
rotation_scale.set_axis_y(axis);
return *this;
}
template<typename T>
constexpr trans2<T>& trans2<T>::set_scale(vec2<T> const& s) noexcept
{
rotation_scale.set_scale(s);
return *this;
}
template<typename T>
constexpr trans2<T>& trans2<T>::set_rotation_scale(T rotation) noexcept
{
rotation_scale = mat2<T>::from_rotation(rotation);
return *this;
}
template<typename T>
constexpr trans2<T>& trans2<T>::post_scale(const vec2<T>& scale) noexcept
{
rotation_scale.column0 *= scale.x;
rotation_scale.column1 *= scale.y;
return *this;
}
template<typename T>
constexpr trans2<T>& trans2<T>::post_translate(vec2<T> const& trans) noexcept
{
translation += rotate(rotation_scale, trans);
return *this;
}
template<typename T>
constexpr trans2<T> trans2<T>::operator*(trans2<T> const& other) const noexcept
{
trans2<T> ret;
multiply(ret, *this, other);
return ret;
}
template<typename T>
constexpr trans2<T>& trans2<T>::operator*=(const trans2<T>& other) noexcept
{
trans2<T> a(*this);
multiply(*this, a, other);
return *this;
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::trans2<T>>
{
std::size_t operator()(const math::trans2<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.rotation_scale);
tl::hash_and_combine(seed, p.translation);
return seed;
}
};
+67
View File
@@ -0,0 +1,67 @@
#pragma once
#include <compare>
namespace math
{
template<typename T> struct vec3;
template<typename T> struct mat4;
template<typename T> struct quat;
// mat4 layout trans3 layout (4 vec3)
// 0 4 8 12 0 3 6 tx
// 1 5 9 13 -> 1 4 7 ty
// 2 6 10 14 2 5 8 tz
// 3 7 11 15
// the last row is always constant (0 0 0 1) for the trans
template<typename T>
struct trans3
{
typedef T value_t;
using this_t = trans3<T>;
constexpr trans3() noexcept = default;
constexpr explicit trans3(math::ZUninitialized) noexcept;
constexpr trans3(trans3<T> const&) noexcept = default;
constexpr explicit trans3(vec3<T> const& translation) noexcept;
constexpr trans3(vec3<T> const& translation, quat<T> const& rotation_scale) noexcept;
constexpr trans3(vec3<T> const& translation, quat<T> const& rotation_scale, vec3<T> const& scale) noexcept;
constexpr trans3(vec3<T> const& translation, mat3<T> const& rotation_scale) noexcept;
constexpr trans3(vec3<T> const& translation, mat3<T> const& rotation_scale, vec3<T> const& scale) noexcept;
constexpr trans3<T>& operator=(trans3<T> const&) noexcept = default;
constexpr trans3<T> operator*(trans3<T> const& other) const noexcept;
constexpr trans3<T>& operator*=(trans3<T> const& other) noexcept;
constexpr trans3<T>& post_scale(vec3<T> const& scale) noexcept;
constexpr trans3<T>& post_translate(vec3<T> const& translation) noexcept;
constexpr vec3<T> const& get_axis_x() const noexcept;
constexpr trans3<T>& set_axis_x(vec3<T> const& axis) noexcept;
constexpr vec3<T> const& get_axis_y() const noexcept;
constexpr trans3<T>& set_axis_y(vec3<T> const& axis) noexcept;
constexpr vec3<T> const& get_axis_z() const noexcept;
constexpr trans3<T>& set_axis_z(vec3<T> const& axis) noexcept;
template<class Policy = standard>
constexpr vec3<T> get_scale() const noexcept;
constexpr trans3<T>& set_scale(vec3<T> const& scale) noexcept;
constexpr trans3<T>& set_rotation_scale(quat<T> const& rotation_scale) noexcept;
constexpr auto operator<=>(const this_t&) const noexcept = default;
constexpr bool operator==(const this_t&) const noexcept = default;
vec3<T> translation;
mat3<T> rotation_scale;
};
}
+135
View File
@@ -0,0 +1,135 @@
namespace math
{
template<typename T>
constexpr trans3<T>::trans3(math::ZUninitialized) noexcept
: rotation_scale(math::uninitialized)
{
}
template<typename T>
constexpr trans3<T>::trans3(vec3<T> const& translation) noexcept
: translation(translation)
{
}
template<typename T>
constexpr trans3<T>::trans3(vec3<T> const& translation, quat<T> const& rs) noexcept
: trans3(translation, to_mat3(rs))
{
}
template<typename T>
constexpr trans3<T>::trans3(vec3<T> const& translation, quat<T> const& rs, vec3<T> const& scale) noexcept
: trans3(translation, to_mat3(rs), scale)
{
}
template<typename T>
constexpr trans3<T>::trans3(vec3<T> const& translation, mat3<T> const& rs) noexcept
: translation(translation)
, rotation_scale(rs)
{
}
template<typename T>
constexpr trans3<T>::trans3(vec3<T> const& translation, mat3<T> const& rs, vec3<T> const& scale) noexcept
: translation(translation)
, rotation_scale(rs)
{
post_scale(scale);
}
template<typename T>
constexpr vec3<T> const& trans3<T>::get_axis_x() const noexcept
{
return rotation_scale.get_axis_x();
}
template<typename T>
constexpr vec3<T> const& trans3<T>::get_axis_y() const noexcept
{
return rotation_scale.get_axis_y();
}
template<typename T>
constexpr vec3<T> const& trans3<T>::get_axis_z() const noexcept
{
return rotation_scale.get_axis_z();
}
template<typename T>
template<class Policy>
constexpr vec3<T> trans3<T>::get_scale() const noexcept
{
return vec3<T>(get_axis_x().template length<Policy>(), get_axis_y().template length<Policy>(), get_axis_z().template length<Policy>());
}
template<typename T>
constexpr trans3<T>& trans3<T>::set_axis_x(vec3<T> const& axis) noexcept
{
rotation_scale.set_axis_x(axis);
return *this;
}
template<typename T>
constexpr trans3<T>& trans3<T>::set_axis_y(vec3<T> const& axis) noexcept
{
rotation_scale.set_axis_y(axis);
return *this;
}
template<typename T>
constexpr trans3<T>& trans3<T>::set_axis_z(vec3<T> const& axis) noexcept
{
rotation_scale.set_axis_z(axis);
return *this;
}
template<typename T>
constexpr trans3<T>& trans3<T>::set_scale(vec3<T> const& s) noexcept
{
rotation_scale.set_scale(s);
return *this;
}
template<typename T>
constexpr trans3<T>& trans3<T>::set_rotation_scale(quat<T> const& rs) noexcept
{
rotation_scale = mat3_from_trans2(rs);
return *this;
}
template<typename T>
constexpr trans3<T>& trans3<T>::post_scale(vec3<T> const& scale) noexcept
{
rotation_scale.column0 *= scale.x;
rotation_scale.column1 *= scale.y;
rotation_scale.column2 *= scale.z;
return *this;
}
template<typename T>
constexpr trans3<T>& trans3<T>::post_translate(vec3<T> const& translation) noexcept
{
translation += rotate(rotation_scale, translation);
return *this;
}
template<typename T>
constexpr trans3<T> trans3<T>::operator*(trans3<T> const& other) const noexcept
{
trans3<T> ret;
multiply(ret, *this, other);
return ret;
}
template<typename T>
constexpr trans3<T>& trans3<T>::operator*=(trans3<T> const& other) noexcept
{
trans3<T> a(*this);
multiply(*this, a, other);
return *this;
}
}
#include "tl/hash_and_combine.h"
template<typename T>
struct eastl::hash<math::trans3<T>>
{
std::size_t operator()(const math::trans3<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.rotation_scale);
tl::hash_and_combine(seed, p.translation);
return seed;
}
};
+39
View File
@@ -0,0 +1,39 @@
#pragma once
#include <compare>
namespace math
{
template<typename T> struct vec3;
//! 3d triangle template class
template<typename T>
struct triangle3
{
constexpr triangle3() noexcept = default;
constexpr triangle3(const vec3<T>& a, const vec3<T>& b, const vec3<T>& c) noexcept;
constexpr triangle3(triangle3<T> const&) noexcept = default;
constexpr auto operator<=>(const triangle3<T>&) const noexcept = default;
constexpr bool operator==(const triangle3<T>&) const noexcept = default;
constexpr triangle3<T>& operator=(triangle3<T> const&) noexcept = default;
//! Get the normal of the triangle.
/** Please note: The normal is not always normalized. */
template<class Policy>
constexpr vec3<T> get_normal() const noexcept;
constexpr plane<T> get_plane() const noexcept;
template<class Policy>
constexpr T get_area() const noexcept;
constexpr T get_area_sq() const noexcept;
vec3<T> a;
vec3<T> b;
vec3<T> c;
};
}
+30
View File
@@ -0,0 +1,30 @@
namespace math
{
template<typename T>
constexpr triangle3<T>::triangle3(const vec3<T>& a, const vec3<T>& b, const vec3<T>& c) noexcept : a(a), b(b), c(c) {}
template<typename T>
template<class Policy>
constexpr vec3<T> triangle3<T>::get_normal() const noexcept
{
return normalized<T, Policy>(cross(b - a, c - a));
}
template<typename T>
constexpr plane<T> triangle3<T>::get_plane() const noexcept
{
return plane<T>(a, b, c);
}
template<typename T>
template<class Policy>
constexpr T triangle3<T>::get_area() const noexcept
{
return length<Policy>(cross(b - a, c - a)) * T(0.5);
}
template<typename T>
constexpr T triangle3<T>::get_area_sq() const noexcept
{
return length_sq(cross(b - a, c - a)) * T(0.25);
}
}
+73
View File
@@ -0,0 +1,73 @@
#pragma once
#include <array>
#include <compare>
namespace math
{
template<typename T>
struct vec2
{
typedef T value_t;
static constexpr size_t element_count = 2;
constexpr vec2() noexcept = default;
constexpr vec2(T x, T y) noexcept;
constexpr explicit vec2(T s) noexcept;
constexpr explicit vec2(std::array<T, 2> const& v) noexcept;
constexpr vec2(vec2<T> const& v) noexcept = default;
constexpr T& operator[](size_t i) noexcept;
constexpr T const& operator[](size_t i) const noexcept;
constexpr auto operator<=>(const vec2<T>&) const noexcept = default;
constexpr bool operator==(const vec2<T>&) const noexcept = default;
constexpr vec2<T> operator-() const noexcept;
constexpr vec2<T> operator+(T s) const noexcept;
constexpr vec2<T> operator+(vec2<T> const& v2) const noexcept;
constexpr vec2<T> operator-(T s) const noexcept;
constexpr vec2<T> operator-(vec2<T> const& v2) const noexcept;
constexpr vec2<T> operator*(T s) const noexcept;
constexpr vec2<T> operator/(T s) const noexcept;
constexpr vec2<T>& operator=(vec2<T> const& v) noexcept = default;
constexpr vec2<T>& operator+=(T s) noexcept;
constexpr vec2<T>& operator+=(vec2<T> const& v) noexcept;
constexpr vec2<T>& operator-=(T s) noexcept;
constexpr vec2<T>& operator-=(vec2<T> const& v) noexcept;
constexpr vec2<T>& operator*=(T s) noexcept;
constexpr vec2<T>& operator*=(vec2<T> const& v) noexcept;
constexpr vec2<T>& operator/=(T s) noexcept;
constexpr vec2<T>& operator/=(vec2<T> const& v) noexcept;
template<class Policy = standard>
constexpr vec2<T>& normalize() noexcept;
template<class Policy = standard>
constexpr T length() const noexcept;
constexpr T length_sq() const noexcept;
T x = T(0);
T y = T(0);
};
template<typename T> constexpr vec2<T> operator*(T s, vec2<T> const&) noexcept;
template<typename T> constexpr vec2<T> operator/(T s, vec2<T> const&) noexcept;
template<typename T> constexpr vec2<T> operator*(vec2<T> const& v0, vec2<T> const& v1) noexcept;
template<typename T> constexpr vec2<T> operator/(vec2<T> const& v0, vec2<T> const& v2) noexcept;
//////////////////////////////////////////////////////////////////////////
} //math
+256
View File
@@ -0,0 +1,256 @@
namespace math
{
template<typename T> constexpr vec2<T>::vec2(T x, T y) noexcept : x(x), y(y) {}
template<typename T> constexpr vec2<T>::vec2(T v) noexcept : x(v), y(v) {}
template<typename T> constexpr vec2<T>::vec2(std::array<T, 2> const& v) noexcept : x(v[0]), y(v[1]) {}
template<typename T>
constexpr T& vec2<T>::operator[](size_t i) noexcept
{
TL_PLAIN_ASSERT(i < sizeof(*this) / sizeof(T));
//if you hit this TL_PLAIN_ASSERT, your compiler introduces padding. Check for #pragma packs without pop
TL_PLAIN_ASSERT(&((T*)this)[0] == &x && &((T*)this)[1] == &y);
return ((T*)this)[i];
}
template<typename T>
constexpr T const& vec2<T>::operator[](size_t i) const noexcept
{
TL_PLAIN_ASSERT(i < sizeof(*this) / sizeof(T));
//if you hit this TL_PLAIN_ASSERT, your compiler introduces padding. Check for #pragma packs without pop
TL_PLAIN_ASSERT(&((T*)this)[0] == &x && &((T*)this)[1] == &y);
return ((T*)this)[i];
}
template<typename T>
constexpr vec2<T> vec2<T>::operator-() const noexcept
{
return vec2<T>(-x, -y);
}
template<typename T>
constexpr vec2<T> vec2<T>::operator+(T s) const noexcept
{
return vec2<T>(x + s, y + s);
}
template<typename T>
constexpr vec2<T> vec2<T>::operator+(vec2<T> const& v) const noexcept
{
return vec2<T>(x + v.x, y + v.y);
}
template<typename T>
constexpr vec2<T> vec2<T>::operator-(T s) const noexcept
{
return vec2<T>(x - s, y - s);
}
template<typename T>
constexpr vec2<T> vec2<T>::operator-(vec2<T> const& v2) const noexcept
{
return vec2<T>(x - v2.x, y - v2.y);
}
template<typename T>
constexpr vec2<T> vec2<T>::operator*(T s) const noexcept
{
return vec2<T>(x * s, y * s);
}
template<typename T>
constexpr vec2<T> vec2<T>::operator/(T s) const noexcept
{
TL_PLAIN_ASSERT(s != T(0));
if constexpr (std::is_floating_point_v<T>)
{
T is = T(1) / s;
return vec2<T>(x * is, y * is);
}
else
return vec2<T>(x / s, y / s);
}
template<typename T>
constexpr vec2<T>& vec2<T>::operator+=(T s) noexcept
{
x += s;
y += s;
return *this;
}
template<typename T>
constexpr vec2<T>& vec2<T>::operator+=(vec2<T> const& v) noexcept
{
x += v.x;
y += v.y;
return *this;
}
template<typename T>
constexpr vec2<T>& vec2<T>::operator-=(T s) noexcept
{
x -= s;
y -= s;
return *this;
}
template<typename T>
constexpr vec2<T>& vec2<T>::operator-=(vec2<T> const& v) noexcept
{
x -= v.x;
y -= v.y;
return *this;
}
template<typename T>
constexpr vec2<T>& vec2<T>::operator*=(T s) noexcept
{
x *= s;
y *= s;
return *this;
}
template<typename T>
constexpr vec2<T>& vec2<T>::operator*=(vec2<T> const& v) noexcept
{
x *= v.x;
y *= v.y;
return *this;
}
template<typename T>
constexpr vec2<T>& vec2<T>::operator/=(T s) noexcept
{
TL_PLAIN_ASSERT(!is_zero(s));
if constexpr (std::is_floating_point_v<T>)
{
T is = T(1) / s;
x *= is;
y *= is;
}
else
{
x /= s;
y /= s;
}
return *this;
}
template<typename T>
constexpr vec2<T>& vec2<T>::operator/=(vec2<T> const& v) noexcept
{
TL_PLAIN_ASSERT(!cwise::any(cwise::is_zero(v)));
x /= v.x;
y /= v.y;
return *this;
}
template<typename T>
constexpr vec2<T> operator*(T s, vec2<T> const& v) noexcept
{
return v*s;
}
template<typename T>
constexpr vec2<T> operator/(T s, vec2<T> const& v) noexcept
{
return vec2<T>(s) / v;
}
template<typename T>
constexpr vec2<T> operator*(vec2<T> const& v0, vec2<T> const& v1) noexcept
{
return vec2<T>(v0.x * v1.x, v0.y * v1.y);
}
template<typename T>
constexpr vec2<T> operator/(vec2<T> const& u, vec2<T> const& v) noexcept
{
TL_PLAIN_ASSERT(!cwise::any(cwise::is_zero(v)));
return vec2<T>(u.x / v.x, u.y / v.y);
}
template<typename T>
template<class Policy>
constexpr vec2<T>& vec2<T>::normalize() noexcept
{
const T len_sq = x * x + y * y;
const T len_inv = inv_sqrt<T, Policy>(len_sq);
x *= len_inv;
y *= len_inv;
return *this;
}
template<typename T>
template<class Policy>
constexpr T vec2<T>::length() const noexcept
{
return sqrt<T, Policy>(x * x + y * y);
}
template<typename T>
constexpr T vec2<T>::length_sq() const noexcept
{
return x * x + y * y;
}
} //math
#include "tl/hash_and_combine.h"
namespace eastl
{
template<typename T>
struct hash<math::vec2<T>>
{
std::size_t operator()(const math::vec2<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.x);
tl::hash_and_combine(seed, p.y);
return seed;
}
};
template<typename T>
class numeric_limits<math::vec2<T>>
{
public:
typedef math::vec2<T> value_type;
static EA_CONSTEXPR_OR_CONST bool is_specialized = true;
static EA_CONSTEXPR_OR_CONST int digits = tl::numeric_limits<T>::digits;
static EA_CONSTEXPR_OR_CONST int digits10 = tl::numeric_limits<T>::digits10;
static EA_CONSTEXPR_OR_CONST int max_digits10 = tl::numeric_limits<T>::max_digits10;
static EA_CONSTEXPR_OR_CONST bool is_signed = tl::numeric_limits<T>::is_signed;
static EA_CONSTEXPR_OR_CONST bool is_integer = tl::numeric_limits<T>::is_integer;
static EA_CONSTEXPR_OR_CONST bool is_exact = tl::numeric_limits<T>::is_exact;
static EA_CONSTEXPR_OR_CONST int radix = tl::numeric_limits<T>::radix;
static EA_CONSTEXPR_OR_CONST int min_exponent = tl::numeric_limits<T>::min_exponent;
static EA_CONSTEXPR_OR_CONST int min_exponent10 = tl::numeric_limits<T>::min_exponent10;
static EA_CONSTEXPR_OR_CONST int max_exponent = tl::numeric_limits<T>::max_exponent;
static EA_CONSTEXPR_OR_CONST int max_exponent10 = tl::numeric_limits<T>::max_exponent10;
static EA_CONSTEXPR_OR_CONST bool is_bounded = tl::numeric_limits<T>::is_bounded;
static EA_CONSTEXPR_OR_CONST bool is_modulo = tl::numeric_limits<T>::is_modulo;
static EA_CONSTEXPR_OR_CONST bool traps = tl::numeric_limits<T>::traps;
static EA_CONSTEXPR_OR_CONST bool tinyness_before = tl::numeric_limits<T>::tinyness_before;
static EA_CONSTEXPR_OR_CONST float_round_style round_style = tl::numeric_limits<T>::round_style;
static EA_CONSTEXPR_OR_CONST bool has_infinity = tl::numeric_limits<T>::has_infinity;
static EA_CONSTEXPR_OR_CONST bool has_quiet_NaN = tl::numeric_limits<T>::has_quiet_NaN;
static EA_CONSTEXPR_OR_CONST bool has_signaling_NaN = tl::numeric_limits<T>::has_signaling_NaN;
static EA_CONSTEXPR_OR_CONST float_denorm_style has_denorm = tl::numeric_limits<T>::has_denorm;
static EA_CONSTEXPR_OR_CONST bool has_denorm_loss = tl::numeric_limits<T>::has_denorm_loss;
static EA_CONSTEXPR_OR_CONST bool is_iec559 = tl::numeric_limits<T>::is_iec559;
static value_type min() noexcept { return value_type(tl::numeric_limits<T>::min()); }
static value_type max() noexcept { return value_type(tl::numeric_limits<T>::max()); }
static value_type lowest() noexcept { return value_type(tl::numeric_limits<T>::lowest()); }
static value_type epsilon() noexcept { return value_type(tl::numeric_limits<T>::epsilon()); }
static value_type round_error() noexcept { return value_type(tl::numeric_limits<T>::round_error()); }
static value_type infinity() noexcept { return value_type(tl::numeric_limits<T>::infinity()); }
static value_type quiet_NaN() noexcept { return value_type(tl::numeric_limits<T>::quiet_NaN()); }
static value_type signaling_NaN() noexcept { return value_type(tl::numeric_limits<T>::signaling_NaN()); }
static value_type denorm_min() noexcept { return value_type(tl::numeric_limits<T>::denorm_min()); }
};
}
+73
View File
@@ -0,0 +1,73 @@
#pragma once
#include <array>
#include <compare>
namespace math
{
template<typename T>
struct vec3
{
typedef T value_t;
static constexpr size_t element_count = 3;
constexpr vec3() noexcept = default;
constexpr vec3(T x, T y, T z) noexcept;
constexpr explicit vec3(T s) noexcept;
constexpr explicit vec3(std::array<T, 3> const& v) noexcept;
constexpr vec3(vec3<T> const& v) noexcept = default;
constexpr T& operator[](size_t i) noexcept;
constexpr T const& operator[](size_t i) const noexcept;
constexpr auto operator<=>(const vec3<T>&) const noexcept = default;
constexpr bool operator==(const vec3<T>&) const noexcept = default;
constexpr vec3<T> operator-() const noexcept;
constexpr vec3<T> operator+(T s) const noexcept;
constexpr vec3<T> operator+(vec3<T> const& v) const noexcept;
constexpr vec3<T> operator-(T s) const noexcept;
constexpr vec3<T> operator-(vec3<T> const& v) const noexcept;
constexpr vec3<T> operator*(T s) const noexcept;
constexpr vec3<T> operator/(T s) const noexcept;
constexpr vec3<T>& operator=(vec3<T> const& v) noexcept = default;
constexpr vec3<T>& operator+=(T s) noexcept;
constexpr vec3<T>& operator+=(vec3<T> const& v) noexcept;
constexpr vec3<T>& operator-=(T s) noexcept;
constexpr vec3<T>& operator-=(vec3<T> const& v) noexcept;
constexpr vec3<T>& operator*=(T s) noexcept;
constexpr vec3<T>& operator*=(vec3<T> const& v) noexcept;
constexpr vec3<T>& operator/=(T s) noexcept;
constexpr vec3<T>& operator/=(vec3<T> const& v) noexcept;
template<class Policy = standard>
constexpr vec3<T>& normalize() noexcept;
template<class Policy = standard>
constexpr T length() const noexcept;
constexpr T length_sq() const noexcept;
T x = T(0);
T y = T(0);
T z = T(0);
};
template<typename T> constexpr vec3<T> operator*(T s, vec3<T> const&) noexcept;
template<typename T> constexpr vec3<T> operator*(vec3<T> const& v0, vec3<T> const& v1) noexcept;
template<typename T> constexpr vec3<T> operator/(T s, vec3<T> const&) noexcept;
template<typename T> constexpr vec3<T> operator/(vec3<T> const& v0, vec3<T> const& v1) noexcept;
//////////////////////////////////////////////////////////////////////////
} //math
+258
View File
@@ -0,0 +1,258 @@
namespace math
{
template<typename T> constexpr vec3<T>::vec3(T x, T y, T z) noexcept : x(x), y(y), z(z) {}
template<typename T> constexpr vec3<T>::vec3(T v) noexcept : x(v), y(v), z(v) {}
template<typename T> constexpr vec3<T>::vec3(std::array<T, 3> const& v) noexcept : x(v[0]), y(v[1]), z(v[2]) {}
template<typename T>
constexpr vec3<T> vec3<T>::operator-() const noexcept
{
return vec3<T>(-x, -y, -z);
}
template<typename T>
constexpr T& vec3<T>::operator[](size_t i) noexcept
{
TL_PLAIN_ASSERT(i < 3);
return ((T*)this)[i];
}
template<typename T>
constexpr T const& vec3<T>::operator[](size_t i) const noexcept
{
TL_PLAIN_ASSERT(i < 3);
return ((T*)this)[i];
}
template<typename T>
constexpr vec3<T> vec3<T>::operator+(T s) const noexcept
{
return vec3<T>(x + s, y + s, z + s);
}
template<typename T>
constexpr vec3<T> vec3<T>::operator+(vec3<T> const& v) const noexcept
{
return vec3<T>(x + v.x, y + v.y, z + v.z);
}
template<typename T>
constexpr vec3<T> vec3<T>::operator-(T s) const noexcept
{
return vec3<T>(x - s, y - s, z - s);
}
template<typename T>
constexpr vec3<T> vec3<T>::operator-(vec3<T> const& v) const noexcept
{
return vec3<T>(x - v.x, y - v.y, z - v.z);
}
template<typename T>
constexpr vec3<T> vec3<T>::operator*(T s) const noexcept
{
return vec3<T>(x * s, y * s, z * s);
}
template<typename T>
constexpr vec3<T> vec3<T>::operator/(T s) const noexcept
{
TL_PLAIN_ASSERT(!is_zero(s));
if constexpr (std::is_floating_point_v<T>)
{
T is = T(1) / s;
return vec3<T>(x * is, y * is, z * is);
}
else
return vec3<T>(x / s, y / s, z / s);
}
template<typename T>
constexpr vec3<T>& vec3<T>::operator+=(T s) noexcept
{
x += s;
y += s;
z += s;
return *this;
}
template<typename T>
constexpr vec3<T>& vec3<T>::operator+=(vec3<T> const& v) noexcept
{
x += v.x;
y += v.y;
z += v.z;
return *this;
}
template<typename T>
constexpr vec3<T>& vec3<T>::operator-=(T s) noexcept
{
x -= s;
y -= s;
z -= s;
return *this;
}
template<typename T>
constexpr vec3<T>& vec3<T>::operator-=(vec3<T> const& v) noexcept
{
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
template<typename T>
constexpr vec3<T>& vec3<T>::operator*=(T s) noexcept
{
x *= s;
y *= s;
z *= s;
return *this;
}
template<typename T>
constexpr vec3<T>& vec3<T>::operator*=(vec3<T> const& v) noexcept
{
x *= v.x;
y *= v.y;
z *= v.z;
return *this;
}
template<typename T>
constexpr vec3<T>& vec3<T>::operator/=(T s) noexcept
{
TL_PLAIN_ASSERT(s != T(0));
if constexpr (std::is_floating_point_v<T>)
{
T is = T(1) / s;
x *= is;
y *= is;
z *= is;
}
else
{
x /= s;
y /= s;
z /= s;
}
return *this;
}
template<typename T>
constexpr vec3<T>& vec3<T>::operator/=(vec3<T> const& v) noexcept
{
TL_PLAIN_ASSERT(!cwise::any(cwise::is_zero(v)));
x /= v.x;
y /= v.y;
z /= v.z;
return *this;
}
template<typename T>
constexpr vec3<T> operator*(T s, vec3<T> const& v) noexcept
{
return v*s;
}
template<typename T>
constexpr vec3<T> operator/(T s, vec3<T> const& v) noexcept
{
return vec3<T>(s) / v;
}
template<typename T>
constexpr vec3<T> operator*(vec3<T> const& v0, vec3<T> const& v1) noexcept
{
return vec3<T>(v0.x * v1.x, v0.y * v1.y, v0.z * v1.z);
}
template<typename T>
constexpr vec3<T> operator/(vec3<T> const& u, vec3<T> const& v) noexcept
{
TL_PLAIN_ASSERT(!cwise::any(cwise::is_zero(v)));
return vec3<T>(u.x / v.x, u.y / v.y, u.z / v.z);
}
template<typename T>
template<class Policy>
constexpr vec3<T>& vec3<T>::normalize() noexcept
{
const T len_sq = x * x + y * y + z * z;
const T len_inv = inv_sqrt<T, Policy>(len_sq);
x *= len_inv;
y *= len_inv;
z *= len_inv;
return *this;
}
template<typename T>
template<class Policy>
constexpr T vec3<T>::length() const noexcept
{
return sqrt<T, Policy>(x * x + y * y + z * z);
}
template<typename T>
constexpr T vec3<T>::length_sq() const noexcept
{
return x * x + y * y + z * z;
}
} //math
#include "tl/hash_and_combine.h"
namespace eastl
{
template<typename T>
struct hash<math::vec3<T>>
{
std::size_t operator()(const math::vec3<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.x);
tl::hash_and_combine(seed, p.y);
tl::hash_and_combine(seed, p.z);
return seed;
}
};
template<typename T>
class numeric_limits<math::vec3<T>>
{
public:
typedef math::vec3<T> value_type;
static EA_CONSTEXPR_OR_CONST bool is_specialized = true;
static EA_CONSTEXPR_OR_CONST int digits = tl::numeric_limits<T>::digits;
static EA_CONSTEXPR_OR_CONST int digits10 = tl::numeric_limits<T>::digits10;
static EA_CONSTEXPR_OR_CONST int max_digits10 = tl::numeric_limits<T>::max_digits10;
static EA_CONSTEXPR_OR_CONST bool is_signed = tl::numeric_limits<T>::is_signed;
static EA_CONSTEXPR_OR_CONST bool is_integer = tl::numeric_limits<T>::is_integer;
static EA_CONSTEXPR_OR_CONST bool is_exact = tl::numeric_limits<T>::is_exact;
static EA_CONSTEXPR_OR_CONST int radix = tl::numeric_limits<T>::radix;
static EA_CONSTEXPR_OR_CONST int min_exponent = tl::numeric_limits<T>::min_exponent;
static EA_CONSTEXPR_OR_CONST int min_exponent10 = tl::numeric_limits<T>::min_exponent10;
static EA_CONSTEXPR_OR_CONST int max_exponent = tl::numeric_limits<T>::max_exponent;
static EA_CONSTEXPR_OR_CONST int max_exponent10 = tl::numeric_limits<T>::max_exponent10;
static EA_CONSTEXPR_OR_CONST bool is_bounded = tl::numeric_limits<T>::is_bounded;
static EA_CONSTEXPR_OR_CONST bool is_modulo = tl::numeric_limits<T>::is_modulo;
static EA_CONSTEXPR_OR_CONST bool traps = tl::numeric_limits<T>::traps;
static EA_CONSTEXPR_OR_CONST bool tinyness_before = tl::numeric_limits<T>::tinyness_before;
static EA_CONSTEXPR_OR_CONST float_round_style round_style = tl::numeric_limits<T>::round_style;
static EA_CONSTEXPR_OR_CONST bool has_infinity = tl::numeric_limits<T>::has_infinity;
static EA_CONSTEXPR_OR_CONST bool has_quiet_NaN = tl::numeric_limits<T>::has_quiet_NaN;
static EA_CONSTEXPR_OR_CONST bool has_signaling_NaN = tl::numeric_limits<T>::has_signaling_NaN;
static EA_CONSTEXPR_OR_CONST float_denorm_style has_denorm = tl::numeric_limits<T>::has_denorm;
static EA_CONSTEXPR_OR_CONST bool has_denorm_loss = tl::numeric_limits<T>::has_denorm_loss;
static EA_CONSTEXPR_OR_CONST bool is_iec559 = tl::numeric_limits<T>::is_iec559;
static value_type min() noexcept { return value_type(tl::numeric_limits<T>::min()); }
static value_type max() noexcept { return value_type(tl::numeric_limits<T>::max()); }
static value_type lowest() noexcept { return value_type(tl::numeric_limits<T>::lowest()); }
static value_type epsilon() noexcept { return value_type(tl::numeric_limits<T>::epsilon()); }
static value_type round_error() noexcept { return value_type(tl::numeric_limits<T>::round_error()); }
static value_type infinity() noexcept { return value_type(tl::numeric_limits<T>::infinity()); }
static value_type quiet_NaN() noexcept { return value_type(tl::numeric_limits<T>::quiet_NaN()); }
static value_type signaling_NaN() noexcept { return value_type(tl::numeric_limits<T>::signaling_NaN()); }
static value_type denorm_min() noexcept { return value_type(tl::numeric_limits<T>::denorm_min()); }
};
}
+74
View File
@@ -0,0 +1,74 @@
#pragma once
#include <array>
#include <compare>
namespace math
{
template<typename T>
struct vec4
{
typedef T value_t;
static constexpr size_t element_count = 4;
constexpr vec4() noexcept = default;
constexpr vec4(T x, T y, T z, T w) noexcept;
constexpr explicit vec4(T s) noexcept;
constexpr explicit vec4(std::array<T, 4> const& v) noexcept;
constexpr vec4(vec4<T> const& v) noexcept = default;
constexpr T& operator[](size_t i) noexcept;
constexpr T const& operator[](size_t i) const noexcept;
constexpr auto operator<=>(const vec4<T>&) const noexcept = default;
constexpr bool operator==(const vec4<T>&) const noexcept = default;
constexpr vec4<T> operator-() const noexcept;
constexpr vec4<T> operator+(T s) const noexcept;
constexpr vec4<T> operator+(vec4<T> const& v) const noexcept;
constexpr vec4<T> operator-(T s) const noexcept;
constexpr vec4<T> operator-(vec4<T> const& v) const noexcept;
constexpr vec4<T> operator*(T s) const noexcept;
constexpr vec4<T> operator/(T s) const noexcept;
constexpr vec4<T>& operator=(vec4<T> const& v) noexcept = default;
constexpr vec4<T>& operator+=(T s) noexcept;
constexpr vec4<T>& operator+=(vec4<T> const& v) noexcept;
constexpr vec4<T>& operator-=(T s) noexcept;
constexpr vec4<T>& operator-=(vec4<T> const& v) noexcept;
constexpr vec4<T>& operator*=(T s) noexcept;
constexpr vec4<T>& operator*=(vec4<T> const& v) noexcept;
constexpr vec4<T>& operator/=(T s) noexcept;
constexpr vec4<T>& operator/=(vec4<T> const& v) noexcept;
template<class Policy = standard>
constexpr vec4<T>& normalize() noexcept;
template<class Policy = standard>
constexpr T length() const noexcept;
constexpr T length_sq() const noexcept;
T x = T(0);
T y = T(0);
T z = T(0);
T w = T(0);
};
template<typename T> constexpr math::vec4<T> operator*(T s, math::vec4<T> const&) noexcept;
template<typename T> constexpr math::vec4<T> operator/(T s, math::vec4<T> const&) noexcept;
template<typename T> constexpr math::vec4<T> operator*(math::vec4<T> const&, math::vec4<T> const&) noexcept;
template<typename T> constexpr math::vec4<T> operator/(math::vec4<T> const&, math::vec4<T> const&) noexcept;
//////////////////////////////////////////////////////////////////////////
} //math
+276
View File
@@ -0,0 +1,276 @@
namespace math
{
template<typename T> constexpr vec4<T>::vec4(T x, T y, T z, T w) noexcept : x(x), y(y), z(z), w(w) {}
template<typename T> constexpr vec4<T>::vec4(T v) noexcept : x(v), y(v), z(v), w(v) {}
template<typename T> constexpr vec4<T>::vec4(std::array<T, 4> const& v) noexcept : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
template<typename T>
constexpr vec4<T> vec4<T>::operator-() const noexcept
{
return vec4<T>(-x, -y, -z, -w);
}
template<typename T>
constexpr T& vec4<T>::operator[](size_t i) noexcept
{
TL_PLAIN_ASSERT(i < sizeof(*this) / sizeof(T));
//if you hit this TL_PLAIN_ASSERT, your compiler introduces padding. Check for #pragma packs without pop
TL_PLAIN_ASSERT(&((T*)this)[0] == &x && &((T*)this)[1] == &y);
return ((T*)this)[i];
}
template<typename T>
constexpr T const& vec4<T>::operator[](size_t i) const noexcept
{
TL_PLAIN_ASSERT(i < sizeof(*this) / sizeof(T));
//if you hit this TL_PLAIN_ASSERT, your compiler introduces padding. Check for #pragma packs without pop
TL_PLAIN_ASSERT(&((T*)this)[0] == &x && &((T*)this)[1] == &y);
return ((T*)this)[i];
}
template<typename T>
constexpr vec4<T> vec4<T>::operator+(T s) const noexcept
{
return vec4<T>(x + s, y + s, z + s, w + s);
}
template<typename T>
constexpr vec4<T> vec4<T>::operator+(vec4<T> const& v) const noexcept
{
return vec4<T>(x + v.x, y + v.y, z + v.z, w + v.w);
}
template<typename T>
constexpr vec4<T> vec4<T>::operator-(T s) const noexcept
{
return vec4<T>(x - s, y - s, z - s, w - s);
}
template<typename T>
constexpr vec4<T> vec4<T>::operator-(vec4<T> const& v) const noexcept
{
return vec4<T>(x - v.x, y - v.y, z - v.z, w - v.w);
}
template<typename T>
constexpr vec4<T> vec4<T>::operator*(T s) const noexcept
{
return vec4<T>(x * s, y * s, z * s, w * s);
}
template<typename T>
constexpr vec4<T> vec4<T>::operator/(T s) const noexcept
{
TL_PLAIN_ASSERT(!is_zero(s));
if constexpr (std::is_floating_point_v<T>)
{
T is = T(1) / s;
return vec4<T>(x * is, y * is, z * is, w * is);
}
else
return vec4<T>(x / s, y / s, z / s, w / s);
}
template<typename T>
constexpr vec4<T>& vec4<T>::operator+=(T s) noexcept
{
x += s;
y += s;
z += s;
w += s;
return *this;
}
template<typename T>
constexpr vec4<T>& vec4<T>::operator+=(vec4<T> const& v) noexcept
{
x += v.x;
y += v.y;
z += v.z;
w += v.w;
return *this;
}
template<typename T>
constexpr vec4<T>& vec4<T>::operator-=(T s) noexcept
{
x -= s;
y -= s;
z -= s;
w -= s;
return *this;
}
template<typename T>
constexpr vec4<T>& vec4<T>::operator-=(vec4<T> const& v) noexcept
{
x -= v.x;
y -= v.y;
z -= v.z;
w -= v.w;
return *this;
}
template<typename T>
constexpr vec4<T>& vec4<T>::operator*=(T s) noexcept
{
x *= s;
y *= s;
z *= s;
w *= s;
return *this;
}
template<typename T>
constexpr vec4<T>& vec4<T>::operator*=(vec4<T> const& v) noexcept
{
x *= v.x;
y *= v.y;
z *= v.z;
w *= v.w;
return *this;
}
template<typename T>
constexpr vec4<T>& vec4<T>::operator/=(T s) noexcept
{
TL_PLAIN_ASSERT(!is_zero(s));
if constexpr (std::is_floating_point_v<T>)
{
T is = T(1) / s;
x *= is;
y *= is;
z *= is;
w *= is;
}
else
{
x /= s;
y /= s;
z /= s;
w /= s;
}
return *this;
}
template<typename T>
constexpr vec4<T>& vec4<T>::operator/=(vec4<T> const& v) noexcept
{
TL_PLAIN_ASSERT(!cwise::any(cwise::is_zero(v)));
x /= v.x;
y /= v.y;
z /= v.z;
w /= v.w;
return *this;
}
template<typename T>
constexpr vec4<T> operator*(T s, vec4<T> const& v) noexcept
{
return v*s;
}
template<typename T>
constexpr vec4<T> operator/(T s, vec4<T> const& v) noexcept
{
return vec4<T>(s) / v;
}
template<typename T>
constexpr vec4<T> operator*(vec4<T> const& v0, vec4<T> const& v1) noexcept
{
return vec4<T>(v0.x * v1.x, v0.y * v1.y, v0.z * v1.z, v0.w * v1.w);
}
template<typename T>
constexpr vec4<T> operator/(vec4<T> const& u, vec4<T> const& v) noexcept
{
TL_PLAIN_ASSERT(!cwise::any(cwise::is_zero(v)));
return vec4<T>(u.x / v.x, u.y / v.y, u.z / v.z, u.w / v.w);
}
template<typename T>
template<class Policy>
constexpr vec4<T>& vec4<T>::normalize() noexcept
{
const T len_sq = x * x + y * y + z * z + w * w;
const T len_inv = inv_sqrt<T, Policy>(len_sq);
x *= len_inv;
y *= len_inv;
z *= len_inv;
w *= len_inv;
return *this;
}
template<typename T>
template<class Policy>
constexpr T vec4<T>::length() const noexcept
{
return sqrt<T, Policy>(x * x + y * y + z * z + w * w);
}
template<typename T>
constexpr T vec4<T>::length_sq() const noexcept
{
return x * x + y * y + z * z + w * w;
}
} //math
#include "tl/hash_and_combine.h"
namespace eastl
{
template<typename T>
struct hash<math::vec4<T>>
{
std::size_t operator()(const math::vec4<T>& p) const
{
size_t seed = 0;
tl::hash_and_combine(seed, p.x);
tl::hash_and_combine(seed, p.y);
tl::hash_and_combine(seed, p.z);
tl::hash_and_combine(seed, p.w);
return seed;
}
};
template<typename T>
class numeric_limits<math::vec4<T>>
{
public:
typedef math::vec4<T> value_type;
static EA_CONSTEXPR_OR_CONST bool is_specialized = true;
static EA_CONSTEXPR_OR_CONST int digits = tl::numeric_limits<T>::digits;
static EA_CONSTEXPR_OR_CONST int digits10 = tl::numeric_limits<T>::digits10;
static EA_CONSTEXPR_OR_CONST int max_digits10 = tl::numeric_limits<T>::max_digits10;
static EA_CONSTEXPR_OR_CONST bool is_signed = tl::numeric_limits<T>::is_signed;
static EA_CONSTEXPR_OR_CONST bool is_integer = tl::numeric_limits<T>::is_integer;
static EA_CONSTEXPR_OR_CONST bool is_exact = tl::numeric_limits<T>::is_exact;
static EA_CONSTEXPR_OR_CONST int radix = tl::numeric_limits<T>::radix;
static EA_CONSTEXPR_OR_CONST int min_exponent = tl::numeric_limits<T>::min_exponent;
static EA_CONSTEXPR_OR_CONST int min_exponent10 = tl::numeric_limits<T>::min_exponent10;
static EA_CONSTEXPR_OR_CONST int max_exponent = tl::numeric_limits<T>::max_exponent;
static EA_CONSTEXPR_OR_CONST int max_exponent10 = tl::numeric_limits<T>::max_exponent10;
static EA_CONSTEXPR_OR_CONST bool is_bounded = tl::numeric_limits<T>::is_bounded;
static EA_CONSTEXPR_OR_CONST bool is_modulo = tl::numeric_limits<T>::is_modulo;
static EA_CONSTEXPR_OR_CONST bool traps = tl::numeric_limits<T>::traps;
static EA_CONSTEXPR_OR_CONST bool tinyness_before = tl::numeric_limits<T>::tinyness_before;
static EA_CONSTEXPR_OR_CONST float_round_style round_style = tl::numeric_limits<T>::round_style;
static EA_CONSTEXPR_OR_CONST bool has_infinity = tl::numeric_limits<T>::has_infinity;
static EA_CONSTEXPR_OR_CONST bool has_quiet_NaN = tl::numeric_limits<T>::has_quiet_NaN;
static EA_CONSTEXPR_OR_CONST bool has_signaling_NaN = tl::numeric_limits<T>::has_signaling_NaN;
static EA_CONSTEXPR_OR_CONST float_denorm_style has_denorm = tl::numeric_limits<T>::has_denorm;
static EA_CONSTEXPR_OR_CONST bool has_denorm_loss = tl::numeric_limits<T>::has_denorm_loss;
static EA_CONSTEXPR_OR_CONST bool is_iec559 = tl::numeric_limits<T>::is_iec559;
static value_type min() noexcept { return value_type(tl::numeric_limits<T>::min()); }
static value_type max() noexcept { return value_type(tl::numeric_limits<T>::max()); }
static value_type lowest() noexcept { return value_type(tl::numeric_limits<T>::lowest()); }
static value_type epsilon() noexcept { return value_type(tl::numeric_limits<T>::epsilon()); }
static value_type round_error() noexcept { return value_type(tl::numeric_limits<T>::round_error()); }
static value_type infinity() noexcept { return value_type(tl::numeric_limits<T>::infinity()); }
static value_type quiet_NaN() noexcept { return value_type(tl::numeric_limits<T>::quiet_NaN()); }
static value_type signaling_NaN() noexcept { return value_type(tl::numeric_limits<T>::signaling_NaN()); }
static value_type denorm_min() noexcept { return value_type(tl::numeric_limits<T>::denorm_min()); }
};
}
+122
View File
@@ -0,0 +1,122 @@
#include "VMath.h"
namespace math
{
namespace detail
{
// for (int i = 0; i < 806; i++)
// {
// //THERE are 805 elements for 0 .. pi/2
// float a = math::clamp((float(i) / 804.f) * constantsf::pi2, 0.f, constantsf::pi2);
// float _sin = std::sin(a) + 1;
// float _cos = std::cos(a) + 1;
//
// uint32_t _cosx = *reinterpret_cast<uint32_t*>(&_cos) >> 7;
// if (_cos >= 2.f)
// {
// _cosx = 0xFFFFu;
// }
// uint32_t _sinx = *reinterpret_cast<uint32_t*>(&_sin) >> 7;
// if (_sin >= 2.f)
// {
// _sinx = 0xFFFFu;
// }
//
// if (i % 10 == 0)
// {
// printf("\n");
// }
//
// printf("0x%04x%04x, ", _sinx & 0xFFFF, _cosx & 0xFFFF);
// }
//the last element is to allow interpolating without checking for out of bounds
const uint32_t k_sin_cos[806] =
{
0x0000ffff, 0x0080ffff, 0x0100ffff, 0x0180fffe, 0x0200fffe, 0x0280fffc, 0x0300fffb, 0x0380fff9, 0x0400fff8, 0x0480fff5,
0x0500fff3, 0x0580fff0, 0x0600ffed, 0x0680ffea, 0x0700ffe7, 0x0780ffe3, 0x0800ffdf, 0x0880ffdb, 0x0900ffd7, 0x0980ffd2,
0x0a00ffcd, 0x0a80ffc8, 0x0b00ffc3, 0x0b7fffbd, 0x0bffffb7, 0x0c7fffb1, 0x0cffffab, 0x0d7fffa4, 0x0dffff9d, 0x0e7fff96,
0x0efeff8f, 0x0f7eff87, 0x0ffeff7f, 0x107eff77, 0x10feff6f, 0x117dff66, 0x11fdff5d, 0x127dff54, 0x12fdff4b, 0x137cff41,
0x13fcff37, 0x147cff2d, 0x14fbff23, 0x157bff18, 0x15faff0e, 0x167aff02, 0x16f9fef7, 0x1779feeb, 0x17f8fee0, 0x1878fed3,
0x18f7fec7, 0x1977feba, 0x19f6feae, 0x1a75fea0, 0x1af5fe93, 0x1b74fe86, 0x1bf3fe78, 0x1c73fe6a, 0x1cf2fe5b, 0x1d71fe4d,
0x1df0fe3e, 0x1e6ffe2f, 0x1eeffe1f, 0x1f6efe10, 0x1fedfe00, 0x206cfdf0, 0x20ebfddf, 0x216afdcf, 0x21e9fdbe, 0x2267fdad,
0x22e6fd9c, 0x2365fd8a, 0x23e4fd78, 0x2463fd66, 0x24e1fd54, 0x2560fd41, 0x25dffd2e, 0x265dfd1b, 0x26dcfd08, 0x275bfcf4,
0x27d9fce1, 0x2857fccd, 0x28d6fcb8, 0x2954fca4, 0x29d3fc8f, 0x2a51fc7a, 0x2acffc65, 0x2b4dfc4f, 0x2bccfc39, 0x2c4afc23,
0x2cc8fc0d, 0x2d46fbf6, 0x2dc4fbe0, 0x2e42fbc9, 0x2ec0fbb1, 0x2f3efb9a, 0x2fbbfb82, 0x3039fb6a, 0x30b7fb52, 0x3135fb39,
0x31b2fb21, 0x3230fb08, 0x32adfaef, 0x332bfad5, 0x33a8fabb, 0x3426faa1, 0x34a3fa87, 0x3520fa6d, 0x359dfa52, 0x361bfa37,
0x3698fa1c, 0x3715fa00, 0x3792f9e5, 0x380ff9c9, 0x388cf9ad, 0x3908f990, 0x3985f974, 0x3a02f957, 0x3a7ff93a, 0x3afbf91c,
0x3b78f8ff, 0x3bf4f8e1, 0x3c71f8c3, 0x3cedf8a4, 0x3d6af886, 0x3de6f867, 0x3e62f848, 0x3edef828, 0x3f5af809, 0x3fd6f7e9,
0x4052f7c9, 0x40cef7a9, 0x414af788, 0x41c6f767, 0x4241f746, 0x42bdf725, 0x4339f704, 0x43b4f6e2, 0x4430f6c0, 0x44abf69e,
0x4526f67b, 0x45a2f659, 0x461df636, 0x4698f612, 0x4713f5ef, 0x478ef5cb, 0x4809f5a7, 0x4884f583, 0x48fef55f, 0x4979f53a,
0x49f4f515, 0x4a6ef4f0, 0x4ae9f4cb, 0x4b63f4a5, 0x4bddf47f, 0x4c58f459, 0x4cd2f433, 0x4d4cf40d, 0x4dc6f3e6, 0x4e40f3bf,
0x4ebaf398, 0x4f34f370, 0x4fadf348, 0x5027f320, 0x50a1f2f8, 0x511af2d0, 0x5193f2a7, 0x520df27e, 0x5286f255, 0x52fff22c,
0x5378f202, 0x53f1f1d8, 0x546af1ae, 0x54e3f184, 0x555cf159, 0x55d4f12e, 0x564df103, 0x56c5f0d8, 0x573ef0ac, 0x57b6f081,
0x582ef055, 0x58a7f028, 0x591feffc, 0x5997efcf, 0x5a0fefa2, 0x5a86ef75, 0x5afeef48, 0x5b76ef1a, 0x5bedeeec, 0x5c65eebe,
0x5cdcee90, 0x5d53ee61, 0x5dcbee32, 0x5e42ee03, 0x5eb9edd4, 0x5f30eda5, 0x5fa6ed75, 0x601ded45, 0x6094ed15, 0x610aece4,
0x6181ecb4, 0x61f7ec83, 0x626dec52, 0x62e3ec20, 0x6359ebef, 0x63cfebbd, 0x6445eb8b, 0x64bbeb59, 0x6531eb26, 0x65a6eaf4,
0x661ceac1, 0x6691ea8d, 0x6706ea5a, 0x677cea26, 0x67f1e9f2, 0x6866e9be, 0x68dae98a, 0x694fe955, 0x69c4e921, 0x6a38e8ec,
0x6aade8b6, 0x6b21e881, 0x6b95e84b, 0x6c0ae815, 0x6c7ee7df, 0x6cf1e7a9, 0x6d65e772, 0x6dd9e73b, 0x6e4de704, 0x6ec0e6cd,
0x6f33e696, 0x6fa7e65e, 0x701ae626, 0x708de5ee, 0x7100e5b5, 0x7173e57d, 0x71e5e544, 0x7258e50b, 0x72cbe4d1, 0x733de498,
0x73afe45e, 0x7421e424, 0x7493e3ea, 0x7505e3b0, 0x7577e375, 0x75e9e33a, 0x765be2ff, 0x76cce2c4, 0x773de288, 0x77afe24c,
0x7820e210, 0x7891e1d4, 0x7902e198, 0x7972e15b, 0x79e3e11e, 0x7a54e0e1, 0x7ac4e0a4, 0x7b34e066, 0x7ba4e029, 0x7c15dfeb,
0x7c84dfad, 0x7cf4df6e, 0x7d64df30, 0x7dd4def1, 0x7e43deb2, 0x7eb2de72, 0x7f21de33, 0x7f91ddf3, 0x8000ddb3, 0x806edd73,
0x80dddd33, 0x814cdcf2, 0x81badcb2, 0x8228dc71, 0x8297dc2f, 0x8305dbee, 0x8373dbac, 0x83e0db6a, 0x844edb28, 0x84bcdae6,
0x8529daa4, 0x8596da61, 0x8603da1e, 0x8670d9db, 0x86ddd997, 0x874ad954, 0x87b7d910, 0x8823d8cc, 0x8890d888, 0x88fcd844,
0x8968d7ff, 0x89d4d7ba, 0x8a40d775, 0x8aabd730, 0x8b17d6ea, 0x8b82d6a5, 0x8beed65f, 0x8c59d619, 0x8cc4d5d2, 0x8d2fd58c,
0x8d9ad545, 0x8e04d4fe, 0x8e6fd4b7, 0x8ed9d470, 0x8f43d428, 0x8fadd3e0, 0x9017d398, 0x9081d350, 0x90ead308, 0x9154d2bf,
0x91bdd277, 0x9226d22e, 0x928fd1e4, 0x92f8d19b, 0x9361d151, 0x93cad108, 0x9432d0be, 0x949bd073, 0x9503d029, 0x956bcfde,
0x95d3cf93, 0x963acf48, 0x96a2cefd, 0x9709ceb2, 0x9771ce66, 0x97d8ce1a, 0x983fcdce, 0x98a6cd82, 0x990dcd35, 0x9973cce9,
0x99d9cc9c, 0x9a40cc4f, 0x9aa6cc02, 0x9b0ccbb4, 0x9b72cb67, 0x9bd7cb19, 0x9c3dcacb, 0x9ca2ca7c, 0x9d07ca2e, 0x9d6cc9df,
0x9dd1c991, 0x9e36c941, 0x9e9bc8f2, 0x9effc8a3, 0x9f63c853, 0x9fc7c803, 0xa02bc7b3, 0xa08fc763, 0xa0f3c713, 0xa156c6c2,
0xa1bac671, 0xa21dc620, 0xa280c5cf, 0xa2e3c57e, 0xa345c52c, 0xa3a8c4db, 0xa40ac489, 0xa46dc436, 0xa4cfc3e4, 0xa530c392,
0xa592c33f, 0xa5f4c2ec, 0xa655c299, 0xa6b6c246, 0xa718c1f2, 0xa778c19e, 0xa7d9c14b, 0xa83ac0f6, 0xa89ac0a2, 0xa8fbc04e,
0xa95bbff9, 0xa9bbbfa4, 0xaa1abf4f, 0xaa7abefa, 0xaad9bea5, 0xab39be4f, 0xab98bdfa, 0xabf7bda4, 0xac55bd4e, 0xacb4bcf7,
0xad12bca1, 0xad71bc4a, 0xadcfbbf3, 0xae2dbb9c, 0xae8abb45, 0xaee8baee, 0xaf45ba96, 0xafa3ba3e, 0xb000b9e6, 0xb05db98e,
0xb0b9b936, 0xb116b8de, 0xb172b885, 0xb1ceb82c, 0xb22bb7d3, 0xb286b77a, 0xb2e2b720, 0xb33eb6c7, 0xb399b66d, 0xb3f4b613,
0xb44fb5b9, 0xb4aab55f, 0xb504b504, 0xb55fb4aa, 0xb5b9b44f, 0xb613b3f4, 0xb66db399, 0xb6c7b33e, 0xb720b2e2, 0xb77ab286,
0xb7d3b22b, 0xb82cb1ce, 0xb885b172, 0xb8deb116, 0xb936b0b9, 0xb98eb05d, 0xb9e6b000, 0xba3eafa3, 0xba96af45, 0xbaeeaee8,
0xbb45ae8a, 0xbb9cae2d, 0xbbf3adcf, 0xbc4aad71, 0xbca1ad12, 0xbcf7acb4, 0xbd4eac55, 0xbda4abf7, 0xbdfaab98, 0xbe4fab39,
0xbea5aad9, 0xbefaaa7a, 0xbf4faa1a, 0xbfa4a9bb, 0xbff9a95b, 0xc04ea8fb, 0xc0a2a89a, 0xc0f7a83a, 0xc14ba7d9, 0xc19ea778,
0xc1f2a718, 0xc246a6b6, 0xc299a655, 0xc2eca5f4, 0xc33fa592, 0xc392a530, 0xc3e4a4cf, 0xc436a46d, 0xc489a40a, 0xc4dba3a8,
0xc52ca345, 0xc57ea2e3, 0xc5cfa280, 0xc620a21d, 0xc671a1ba, 0xc6c2a156, 0xc713a0f3, 0xc763a08f, 0xc7b3a02b, 0xc8039fc7,
0xc8539f63, 0xc8a39eff, 0xc8f29e9b, 0xc9419e36, 0xc9919dd1, 0xc9df9d6c, 0xca2e9d07, 0xca7c9ca2, 0xcacb9c3d, 0xcb199bd7,
0xcb679b72, 0xcbb49b0c, 0xcc029aa6, 0xcc4f9a40, 0xcc9c99d9, 0xcce99973, 0xcd35990d, 0xcd8298a6, 0xcdce983f, 0xce1a97d8,
0xce669771, 0xceb29709, 0xcefd96a2, 0xcf48963a, 0xcf9395d3, 0xcfde956b, 0xd0299503, 0xd073949b, 0xd0be9432, 0xd10893ca,
0xd1519361, 0xd19b92f8, 0xd1e4928f, 0xd22e9226, 0xd27791bd, 0xd2bf9154, 0xd30890ea, 0xd3509081, 0xd3989017, 0xd3e08fad,
0xd4288f43, 0xd4708ed9, 0xd4b78e6f, 0xd4fe8e04, 0xd5458d9a, 0xd58c8d2f, 0xd5d28cc4, 0xd6198c59, 0xd65f8bee, 0xd6a58b82,
0xd6ea8b17, 0xd7308aab, 0xd7758a40, 0xd7ba89d4, 0xd7ff8968, 0xd84488fc, 0xd8888890, 0xd8cc8823, 0xd91087b7, 0xd954874a,
0xd99786dd, 0xd9db8670, 0xda1e8603, 0xda618596, 0xdaa48529, 0xdae684bc, 0xdb28844e, 0xdb6a83e0, 0xdbac8373, 0xdbee8305,
0xdc2f8297, 0xdc718228, 0xdcb281ba, 0xdcf2814c, 0xdd3380dd, 0xdd73806e, 0xddb38000, 0xddf37f91, 0xde337f21, 0xde727eb2,
0xdeb27e43, 0xdef17dd4, 0xdf307d64, 0xdf6e7cf4, 0xdfad7c84, 0xdfeb7c15, 0xe0297ba4, 0xe0667b34, 0xe0a47ac4, 0xe0e17a54,
0xe11e79e3, 0xe15b7972, 0xe1987902, 0xe1d47891, 0xe2107820, 0xe24c77af, 0xe288773d, 0xe2c476cc, 0xe2ff765b, 0xe33a75e9,
0xe3757577, 0xe3b07505, 0xe3ea7493, 0xe4247421, 0xe45e73af, 0xe498733d, 0xe4d172cb, 0xe50b7258, 0xe54471e5, 0xe57d7173,
0xe5b57100, 0xe5ee708d, 0xe626701a, 0xe65e6fa7, 0xe6966f33, 0xe6cd6ec0, 0xe7046e4d, 0xe73b6dd9, 0xe7726d65, 0xe7a96cf1,
0xe7df6c7e, 0xe8156c0a, 0xe84b6b95, 0xe8816b21, 0xe8b66aad, 0xe8ec6a38, 0xe92169c4, 0xe955694f, 0xe98a68da, 0xe9be6866,
0xe9f267f1, 0xea26677c, 0xea5a6706, 0xea8d6691, 0xeac1661c, 0xeaf465a6, 0xeb266531, 0xeb5964bb, 0xeb8b6445, 0xebbd63cf,
0xebef6359, 0xec2062e3, 0xec52626d, 0xec8361f7, 0xecb46181, 0xece4610a, 0xed156094, 0xed45601d, 0xed755fa6, 0xeda55f30,
0xedd45eb9, 0xee035e42, 0xee325dcb, 0xee615d53, 0xee905cdc, 0xeebe5c65, 0xeeec5bed, 0xef1a5b76, 0xef485afe, 0xef755a86,
0xefa25a0f, 0xefcf5997, 0xeffc591f, 0xf02858a7, 0xf055582e, 0xf08157b6, 0xf0ac573e, 0xf0d856c5, 0xf103564d, 0xf12e55d4,
0xf159555c, 0xf18454e3, 0xf1ae546a, 0xf1d853f1, 0xf2025378, 0xf22c52ff, 0xf2555286, 0xf27e520d, 0xf2a75193, 0xf2d0511a,
0xf2f850a1, 0xf3205027, 0xf3484fad, 0xf3704f34, 0xf3984eba, 0xf3bf4e40, 0xf3e64dc6, 0xf40d4d4c, 0xf4334cd2, 0xf4594c58,
0xf47f4bdd, 0xf4a54b63, 0xf4cb4ae9, 0xf4f04a6e, 0xf51549f4, 0xf53a4979, 0xf55f48fe, 0xf5834884, 0xf5a74809, 0xf5cb478e,
0xf5ef4713, 0xf6124698, 0xf636461d, 0xf65945a2, 0xf67b4526, 0xf69e44ab, 0xf6c04430, 0xf6e243b4, 0xf7044339, 0xf72542bd,
0xf7464241, 0xf76741c6, 0xf788414a, 0xf7a940ce, 0xf7c94052, 0xf7e93fd6, 0xf8093f5a, 0xf8283ede, 0xf8483e62, 0xf8673de6,
0xf8863d6a, 0xf8a43ced, 0xf8c33c71, 0xf8e13bf4, 0xf8ff3b78, 0xf91c3afb, 0xf93a3a7f, 0xf9573a02, 0xf9743985, 0xf9903908,
0xf9ad388c, 0xf9c9380f, 0xf9e53792, 0xfa003715, 0xfa1c3698, 0xfa37361b, 0xfa52359d, 0xfa6d3520, 0xfa8734a3, 0xfaa13426,
0xfabb33a8, 0xfad5332b, 0xfaef32ad, 0xfb083230, 0xfb2131b2, 0xfb393135, 0xfb5230b7, 0xfb6a3039, 0xfb822fbb, 0xfb9a2f3e,
0xfbb12ec0, 0xfbc92e42, 0xfbe02dc4, 0xfbf62d46, 0xfc0d2cc8, 0xfc232c4a, 0xfc392bcc, 0xfc4f2b4d, 0xfc652acf, 0xfc7a2a51,
0xfc8f29d3, 0xfca42954, 0xfcb828d6, 0xfccd2857, 0xfce127d9, 0xfcf4275b, 0xfd0826dc, 0xfd1b265d, 0xfd2e25df, 0xfd412560,
0xfd5424e1, 0xfd662463, 0xfd7823e4, 0xfd8a2365, 0xfd9c22e6, 0xfdad2267, 0xfdbe21e9, 0xfdcf216a, 0xfddf20eb, 0xfdf0206c,
0xfe001fed, 0xfe101f6e, 0xfe1f1eef, 0xfe2f1e6f, 0xfe3e1df0, 0xfe4d1d71, 0xfe5b1cf2, 0xfe6a1c73, 0xfe781bf3, 0xfe861b74,
0xfe931af5, 0xfea01a75, 0xfeae19f6, 0xfeba1977, 0xfec718f7, 0xfed31878, 0xfee017f8, 0xfeeb1779, 0xfef716f9, 0xff02167a,
0xff0e15fa, 0xff18157b, 0xff2314fb, 0xff2d147c, 0xff3713fc, 0xff41137c, 0xff4b12fd, 0xff54127d, 0xff5d11fd, 0xff66117d,
0xff6f10fe, 0xff77107e, 0xff7f0ffe, 0xff870f7e, 0xff8f0efe, 0xff960e7f, 0xff9d0dff, 0xffa40d7f, 0xffab0cff, 0xffb10c7f,
0xffb70bff, 0xffbd0b7f, 0xffc30b00, 0xffc80a80, 0xffcd0a00, 0xffd20980, 0xffd70900, 0xffdb0880, 0xffdf0800, 0xffe30780,
0xffe70700, 0xffea0680, 0xffed0600, 0xfff00580, 0xfff30500, 0xfff50480, 0xfff80400, 0xfff90380, 0xfffb0300, 0xfffc0280,
0xfffe0200, 0xfffe0180, 0xffff0100, 0xffff0080, 0xffff0000, 0xffff0000
};
}
}