First
This commit is contained in:
@@ -0,0 +1 @@
|
||||
out
|
||||
@@ -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
@@ -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
|
||||
@@ -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());
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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());
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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{};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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()); }
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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; }
|
||||
|
||||
}
|
||||
@@ -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
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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ö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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
};
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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());
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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());
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()); }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()); }
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user