- Component-Wise Functions for Quaternions
- Fixed Allocation Bug with Strings
This commit is contained in:
@@ -108,7 +108,11 @@ add_library(fennec STATIC
|
||||
include/fennec/math/trigonometric.h
|
||||
include/fennec/math/relational.h
|
||||
|
||||
include/fennec/math/ext/common.h
|
||||
include/fennec/math/ext/constants.h
|
||||
include/fennec/math/ext/quaternion.h
|
||||
include/fennec/math/ext/transform.h
|
||||
include/fennec/math/ext/trigonometric.h
|
||||
|
||||
include/fennec/math/detail/__fwd.h
|
||||
include/fennec/math/detail/__math.h
|
||||
@@ -128,8 +132,6 @@ add_library(fennec STATIC
|
||||
# Filesystem
|
||||
include/fennec/fproc/filesystem/file.h source/fproc/filesystem/file.cpp
|
||||
include/fennec/fproc/filesystem/path.h source/fproc/filesystem/path.cpp
|
||||
include/fennec/math/ext/transform.h
|
||||
include/fennec/math/ext/quaternion.h
|
||||
)
|
||||
|
||||
# add metaprogramming templates as a dependency and also force documentation to be generated when fennec is compiled
|
||||
|
||||
@@ -52,42 +52,62 @@ public:
|
||||
///
|
||||
/// \brief Alloc Constructor, initialize empty allocation with allocator instance.
|
||||
/// \param alloc An allocator object to copy, for instances where the allocator needs to be initialized with some data.
|
||||
dynarray(const alloc_t& alloc) : _alloc(8, alloc), _size(0) {}
|
||||
dynarray(const alloc_t& alloc)
|
||||
: _alloc(8, alloc)
|
||||
, _size(0) {
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Sized Allocation, create an allocation with a size of `n` elements, initialized with the default constructor.
|
||||
dynarray(size_t n) : _alloc(n), _size(n)
|
||||
dynarray(size_t n)
|
||||
: _alloc(n)
|
||||
, _size(n)
|
||||
{
|
||||
element_t* addr = _alloc.data();
|
||||
for(; n > 0; --n, ++addr) { fennec::construct(addr); }
|
||||
for(; n > 0; --n, ++addr) {
|
||||
fennec::construct(addr);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief
|
||||
/// \param n
|
||||
/// \param alloc
|
||||
dynarray(size_t n, const alloc_t& alloc) : _alloc(n, alloc), _size(n) {
|
||||
dynarray(size_t n, const alloc_t& alloc)
|
||||
: _alloc(n, alloc)
|
||||
, _size(n) {
|
||||
element_t* addr = _alloc.data();
|
||||
for(; n > 0; --n, ++addr) { fennec::construct(addr); }
|
||||
for(; n > 0; --n, ++addr) {
|
||||
fennec::construct(addr);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Create an allocation of size `n`, with each element constructed using the copy constructor
|
||||
/// \brief n the number of elements
|
||||
dynarray(size_t n, const TypeT& val) {
|
||||
dynarray(size_t n, const TypeT& val)
|
||||
: _alloc(n)
|
||||
, _size(n) {
|
||||
element_t* addr = _alloc.data();
|
||||
for(; n > 0; --n, ++addr) { fennec::construct(addr, val); }
|
||||
for(; n > 0; --n, ++addr) {
|
||||
fennec::construct(addr, val);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename...ArgsT>
|
||||
dynarray(size_t n, ArgsT&&...args) {
|
||||
element_t* addr = _alloc.data();
|
||||
for(; n > 0; --n, ++addr) { fennec::construct(addr, fennec::forward<ArgsT>(args)...); }
|
||||
for(; n > 0; --n, ++addr) {
|
||||
fennec::construct(addr, fennec::forward<ArgsT>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
~dynarray() {
|
||||
element_t* addr = _alloc.data();
|
||||
for(; n > 0; --n, ++addr) { fennec::destruct(addr); }
|
||||
for(int n = _size; n > 0; --n, ++addr) {
|
||||
fennec::destruct(addr);
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
|
||||
@@ -81,9 +81,9 @@ public:
|
||||
/// \param mode the bitfield
|
||||
/// \returns true if the combination of flags is valid, false otherwise
|
||||
static constexpr bool is_valid(uint8_t mode) {
|
||||
bool t = mode & fmode_trunc;
|
||||
bool x = mode & fmode_exclusive;
|
||||
bool w = mode & fmode_write;
|
||||
const bool t = mode & fmode_trunc;
|
||||
const bool x = mode & fmode_exclusive;
|
||||
const bool w = mode & fmode_write;
|
||||
|
||||
// when x is true, t must be true
|
||||
// when t is true, w must be true
|
||||
@@ -151,21 +151,21 @@ public:
|
||||
/// \param path the path to the file
|
||||
/// \param mode the mode flags to open the file with
|
||||
/// \returns false on success, true on error
|
||||
bool open(const cstring& p, uint8_t mode);
|
||||
bool open(const cstring& path, uint8_t mode);
|
||||
|
||||
///
|
||||
/// \brief open a file
|
||||
/// \param path the path to the file
|
||||
/// \param mode the mode flags to open the file with
|
||||
/// \returns false on success, true on error
|
||||
bool open(const string& p, uint8_t mode);
|
||||
bool open(const string& path, uint8_t mode);
|
||||
|
||||
///
|
||||
/// \brief open a file
|
||||
/// \param path the path to the file
|
||||
/// \param mode the mode flags to open the file with
|
||||
/// \returns false on success, true on error
|
||||
bool open(const path& p, uint8_t mode);
|
||||
bool open(const path& path, uint8_t mode);
|
||||
|
||||
///
|
||||
/// \brief close a stream
|
||||
@@ -195,7 +195,7 @@ public:
|
||||
/// copies the contents of this file to the new stream,
|
||||
/// reopen the new stream with the flags of this file and binds to it,
|
||||
/// closes the old file.
|
||||
bool rename(const cstring& p);
|
||||
bool rename(const cstring& path);
|
||||
|
||||
///
|
||||
/// \brief rebinds the stream, copying contents to path, and erasing the old file
|
||||
@@ -207,7 +207,7 @@ public:
|
||||
/// copies the contents of this file to the new stream,
|
||||
/// reopen the new stream with the flags of this file and binds to it,
|
||||
/// closes the old file.
|
||||
bool rename(const string& p);
|
||||
bool rename(const string& path);
|
||||
|
||||
///
|
||||
/// \brief rebinds the stream, copying contents to path, and erasing the old file
|
||||
@@ -219,25 +219,25 @@ public:
|
||||
/// copies the contents of this file to the new stream,
|
||||
/// reopen the new stream with the flags of this file and binds to it,
|
||||
/// closes the old file.
|
||||
bool rename(const path& p);
|
||||
bool rename(const path& path);
|
||||
|
||||
///
|
||||
/// \brief copies the contents of this file to path.
|
||||
/// \param path the path to copy to
|
||||
/// \returns a file at the new path with the copied contents
|
||||
file copy(const cstring& p);
|
||||
file copy(const cstring& path);
|
||||
|
||||
///
|
||||
/// \brief copies the contents of this file to path.
|
||||
/// \param path the path to copy to
|
||||
/// \returns a file at the new path with the copied contents
|
||||
file copy(const string& p);
|
||||
file copy(const string& path);
|
||||
|
||||
///
|
||||
/// \brief copies the contents of this file to path.
|
||||
/// \param path the path to copy to
|
||||
/// \returns a file at the new path with the copied contents
|
||||
file copy(const path& p);
|
||||
file copy(const path& path);
|
||||
|
||||
|
||||
// File Positioning ====================================================================================================
|
||||
|
||||
@@ -53,7 +53,8 @@ public:
|
||||
///
|
||||
/// \brief C-String Conversion Constructor
|
||||
/// \param str the cstring to convert
|
||||
path(const cstring& str) : _str(str) {
|
||||
path(const cstring& str)
|
||||
: _str(str) {
|
||||
while (not _str.empty() && _str[_str.size() - 1] == '/') {
|
||||
_str = _str.substring(0, str.size() - 1);
|
||||
}
|
||||
@@ -62,7 +63,8 @@ public:
|
||||
///
|
||||
/// \brief String Conversion Constructor
|
||||
/// \param str the string to convert
|
||||
path(const string& str) : _str(str) {
|
||||
path(const string& str)
|
||||
: _str(str) {
|
||||
while (_str[_str.size() - 1] == '/') {
|
||||
_str = _str.substring(0, str.size() - 1);
|
||||
}
|
||||
@@ -71,7 +73,9 @@ public:
|
||||
///
|
||||
/// \brief Path Copy Constructor
|
||||
/// \param p the path to copy
|
||||
path(const path& p) : _str(p._str) { }
|
||||
path(const path& p)
|
||||
: _str(p._str) {
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Path Move Constructor
|
||||
@@ -144,10 +148,11 @@ public:
|
||||
|
||||
bool empty() {
|
||||
size_t size = _str.size();
|
||||
if (size == 0) return true;
|
||||
#ifdef _WIN32
|
||||
return (_str[1] == ':' && size == 3) || size == 0;
|
||||
return (_str[1] == ':' && size == 3);
|
||||
#else
|
||||
return (_str[0] == '/' && size == 1) || size == 0;
|
||||
return (_str[0] == '/' && size == 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -213,7 +218,7 @@ public:
|
||||
if (parse.empty()) break;
|
||||
|
||||
// Push the path
|
||||
size_t loc = parse._str.find('/');
|
||||
const size_t loc = parse._str.find('/');
|
||||
working._str += '/';
|
||||
working._str += parse._str.substring(0, loc);
|
||||
parse._str = parse._str.substring(loc + 1);
|
||||
|
||||
@@ -206,6 +206,8 @@ public:
|
||||
///
|
||||
/// \brief String Comparison
|
||||
/// \param str the string to compare against
|
||||
/// \param i the index to start at
|
||||
/// \param n the number of characters to compare
|
||||
/// \returns Zero if both strings are equal, otherwise a negative value if lhs appears before rhs according to the
|
||||
/// current locale, otherwise a positive value.
|
||||
constexpr int compare(const cstring& str, size_t i = 0, size_t n = npos) const {
|
||||
|
||||
@@ -75,52 +75,46 @@ public:
|
||||
/// \details adds additional character for null termination.
|
||||
constexpr _string(char c, size_t n)
|
||||
: _str(n + 1) {
|
||||
fennec::memset(_str.data(), c, n); _str[n] = '\0';
|
||||
fennec::memset(_str.data(), c, n);
|
||||
_str[n] = '\0';
|
||||
}
|
||||
///
|
||||
/// \brief Buffer Copy Constructor
|
||||
/// \param str the buffer to copy
|
||||
/// \param len number of characters in the buffer
|
||||
/// \tparam n number of characters in the buffer
|
||||
///
|
||||
/// \details adds additional character for null termination. Ignores whether str is null-terminated.
|
||||
/// This constructor makes the assumption that `len` is the intended number of characters.
|
||||
template<size_t n>
|
||||
constexpr _string(const char str[n])
|
||||
: _str(str, n + 1) {
|
||||
::strncpy(_str.data(), str, n);
|
||||
_str[n] = '\0';
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Copy Constructor
|
||||
/// \param str the buffer to copy
|
||||
/// \param len number of characters in the buffer
|
||||
/// \param n number of characters in the buffer
|
||||
///
|
||||
/// \details adds additional character for null termination. Ignores whether str is null-terminated.
|
||||
/// This constructor makes the assumption that `len` is the intended number of characters.
|
||||
/// This constructor makes the assumption that `n` is the intended number of characters.
|
||||
constexpr _string(const char* str, size_t n)
|
||||
: _str(str, n + 1) {
|
||||
::strncpy(_str.data(), str, n);
|
||||
_str[n] = '\0';
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief Buffer Copy Constructor
|
||||
/// \param str the buffer to copy
|
||||
/// \param len number of characters in the buffer
|
||||
///
|
||||
/// \details adds additional character for null termination. Ignores whether str is null-terminated.
|
||||
/// This constructor makes the assumption that `len` is the intended number of characters.
|
||||
constexpr _string(const cstring& str)
|
||||
: _str(str, str.size() + 1) {
|
||||
_str[str.size()] = '\0';
|
||||
}
|
||||
|
||||
///
|
||||
/// \brief String Copy Constructor
|
||||
/// \param str the string to copy
|
||||
constexpr _string(const string& str)
|
||||
: _string(str, str.size()) {
|
||||
constexpr _string(const _string& str)
|
||||
: _str(str._str) {
|
||||
}
|
||||
|
||||
constexpr _string(_string&& str) noexcept
|
||||
|
||||
@@ -126,7 +126,7 @@ constexpr void* bit_and(void* arr, const void* mask, size_t n) {
|
||||
const uint8_t* s = static_cast<const uint8_t*>(mask);
|
||||
|
||||
while (n > 0) {
|
||||
size_t step = detail::__bit_and(d, s, n);
|
||||
const size_t step = detail::__bit_and(d, s, n);
|
||||
d += step; s += step; n -= step;
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ constexpr void* bit_or(void* arr, const void* mask, size_t n) {
|
||||
const uint8_t* s = static_cast<const uint8_t*>(mask);
|
||||
while (n > 0)
|
||||
{
|
||||
size_t step = detail::__bit_or(d, s, n);
|
||||
const size_t step = detail::__bit_or(d, s, n);
|
||||
d += step; s += step; n -= step;
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ constexpr void* bit_xor(void* arr, const void* mask, size_t n) {
|
||||
uint8_t* d = static_cast<uint8_t*>(arr);
|
||||
const uint8_t* s = static_cast<const uint8_t*>(mask);
|
||||
while (n > 0) {
|
||||
size_t step = detail::__bit_xor(d, s, n);
|
||||
const size_t step = detail::__bit_xor(d, s, n);
|
||||
d += step; s += step; n -= step;
|
||||
}
|
||||
|
||||
|
||||
@@ -805,7 +805,7 @@ constexpr genType ldexp(genType x, genIType exp) {
|
||||
// Vector Specializations ----------------------------------------------------------------------------------------------
|
||||
|
||||
template<typename genType, typename genIType = int_t, size_t...i> requires(is_integral_v<genIType>)
|
||||
constexpr vector<genType, i...> ldexp(const vector<genType, i...>& x, const vector<genType, i...>& exp) {
|
||||
constexpr vector<genType, i...> ldexp(const vector<genType, i...>& x, const vector<genIType, i...>& exp) {
|
||||
return vector<genType, i...>(fennec::ldexp(x[i], exp[i])...);
|
||||
}
|
||||
|
||||
|
||||
230
include/fennec/math/ext/common.h
Normal file
230
include/fennec/math/ext/common.h
Normal file
@@ -0,0 +1,230 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_MATH_EXT_COMMON_H
|
||||
#define FENNEC_MATH_EXT_COMMON_H
|
||||
|
||||
#include <fennec/lang/limits.h>
|
||||
|
||||
#include <fennec/math/trigonometric.h>
|
||||
#include <fennec/math/ext/quaternion.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// Sign Functions ======================================================================================================
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> sign(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::sign(x.w),
|
||||
fennec::sign(x.x),
|
||||
fennec::sign(x.y),
|
||||
fennec::sign(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> abs(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
x.w * fennec::sign(x.w),
|
||||
x.x * fennec::sign(x.x),
|
||||
x.y * fennec::sign(x.y),
|
||||
x.z * fennec::sign(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Rounding Functions ==================================================================================================
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> floor(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::floor(x.w),
|
||||
fennec::floor(x.x),
|
||||
fennec::floor(x.y),
|
||||
fennec::floor(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> ceil(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::ceil(x.w),
|
||||
fennec::ceil(x.x),
|
||||
fennec::ceil(x.y),
|
||||
fennec::ceil(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> trunc(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::trunc(x.w),
|
||||
fennec::trunc(x.x),
|
||||
fennec::trunc(x.y),
|
||||
fennec::trunc(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> round(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::round(x.w),
|
||||
fennec::round(x.x),
|
||||
fennec::round(x.y),
|
||||
fennec::round(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> roundEven(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::roundEven(x.w),
|
||||
fennec::roundEven(x.x),
|
||||
fennec::roundEven(x.y),
|
||||
fennec::roundEven(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
// Fractional Functions ================================================================================================
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> fract(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::fract(x.w),
|
||||
fennec::fract(x.x),
|
||||
fennec::fract(x.y),
|
||||
fennec::fract(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> mod(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::mod(x.w),
|
||||
fennec::mod(x.x),
|
||||
fennec::mod(x.y),
|
||||
fennec::mod(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> modf(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::modf(x.w),
|
||||
fennec::modf(x.x),
|
||||
fennec::modf(x.y),
|
||||
fennec::modf(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> isnan(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::isnan(x.w),
|
||||
fennec::isnan(x.x),
|
||||
fennec::isnan(x.y),
|
||||
fennec::isnan(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> isinf(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::isinf(x.w),
|
||||
fennec::isinf(x.x),
|
||||
fennec::isinf(x.y),
|
||||
fennec::isinf(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> fma(const qua<genType>& a, const qua<genType>& b, const qua<genType>& c) {
|
||||
return qua<genType>(
|
||||
fennec::fma(a.w, b.w, c.w),
|
||||
fennec::fma(a.x, b.x, c.x),
|
||||
fennec::fma(a.y, b.y, c.y),
|
||||
fennec::fma(a.z, b.z, c.z)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Comparison Functions ================================================================================================
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> min(const qua<genType>& x, const qua<genType>& y) {
|
||||
return qua<genType>(
|
||||
fennec::min(x.w, y.w),
|
||||
fennec::min(x.x, y.x),
|
||||
fennec::min(x.y, y.y),
|
||||
fennec::min(x.z, y.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> max(const qua<genType>& x, const qua<genType>& y) {
|
||||
return qua<genType>(
|
||||
fennec::max(x.w, y.w),
|
||||
fennec::max(x.x, y.x),
|
||||
fennec::max(x.y, y.y),
|
||||
fennec::max(x.z, y.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> clamp(const qua<genType>& x, genType minVal, genType maxVal) {
|
||||
return qua<genType>(
|
||||
fennec::clamp(x.w, minVal, maxVal),
|
||||
fennec::clamp(x.x, minVal, maxVal),
|
||||
fennec::clamp(x.y, minVal, maxVal),
|
||||
fennec::clamp(x.z, minVal, maxVal)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> clamp(const qua<genType>& x, const qua<genType>& minVal, const qua<genType>& maxVal) {
|
||||
return qua<genType>(
|
||||
fennec::clamp(x.w, minVal.w, maxVal.w),
|
||||
fennec::clamp(x.x, minVal.x, maxVal.x),
|
||||
fennec::clamp(x.y, minVal.y, maxVal.y),
|
||||
fennec::clamp(x.z, minVal.z, maxVal.z)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Curves ==============================================================================================================
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> mix(const qua<genType>& x, const qua<genType>& y, genType a) {
|
||||
genType cT = fennec::dot(x, y);
|
||||
qua<genType> z = cT < genType(0) ? -y : y;
|
||||
cT = cT < genType(0) ? -cT : cT;
|
||||
|
||||
if (cT > genType(1) - numeric_limits<genType>::epsilon()) {
|
||||
return x * (genType(1) - a) + y * a;
|
||||
}
|
||||
|
||||
genType t = fennec::acos(cT);
|
||||
return (fennec::sin(x * (genType(1) - a) * t) + z * (fennec::sin(a * t))) / fennec::sin(t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // FENNEC_MATH_EXT_COMMON_H
|
||||
@@ -19,7 +19,6 @@
|
||||
#ifndef FENNEC_MATH_EXT_QUATERNION_H
|
||||
#define FENNEC_MATH_EXT_QUATERNION_H
|
||||
|
||||
#include <fennec/math/trigonometric.h>
|
||||
#include <fennec/math/vector_base.h>
|
||||
|
||||
namespace fennec
|
||||
@@ -27,16 +26,18 @@ namespace fennec
|
||||
|
||||
template<typename ScalarT> struct quaternion;
|
||||
|
||||
template<typename genType> using qua = quaternion<genType>;
|
||||
|
||||
using quat = quaternion<float>;
|
||||
using dquat = quaternion<double>;
|
||||
using quat = qua<float>;
|
||||
using dquat = qua<double>;
|
||||
|
||||
///
|
||||
/// \brief Dot Function
|
||||
/// \param q The Quaternion
|
||||
/// \returns The square sum of all components.
|
||||
/// \param x the first quaternion
|
||||
/// \param y the second quaternion
|
||||
/// \returns The sum of component products.
|
||||
template<typename genType>
|
||||
constexpr genType dot(const quaternion<genType>& x, const quaternion<genType>& y) {
|
||||
constexpr genType dot(const qua<genType>& x, const qua<genType>& y) {
|
||||
return x.w*y.w + x.x*y.x + x.y*y.y + x.z*y.z;
|
||||
}
|
||||
|
||||
@@ -45,7 +46,7 @@ constexpr genType dot(const quaternion<genType>& x, const quaternion<genType>& y
|
||||
/// \param q The Quaternion
|
||||
/// \returns The square sum of all components.
|
||||
template<typename genType>
|
||||
constexpr genType sqnorm(const quaternion<genType>& q) {
|
||||
constexpr genType sqnorm(const qua<genType>& q) {
|
||||
return fennec::dot(q, q);
|
||||
}
|
||||
|
||||
@@ -54,7 +55,7 @@ constexpr genType sqnorm(const quaternion<genType>& q) {
|
||||
/// \param q The Quaternion
|
||||
/// \returns The Hamilton Tensor of `q`
|
||||
template<typename genType>
|
||||
constexpr genType norm(const quaternion<genType>& q) {
|
||||
constexpr genType norm(const qua<genType>& q) {
|
||||
return fennec::sqrt(sqnorm(q));
|
||||
}
|
||||
|
||||
@@ -63,7 +64,7 @@ constexpr genType norm(const quaternion<genType>& q) {
|
||||
/// \param q The Quaternion
|
||||
/// \returns A Quaternion of `q` with norm `1`
|
||||
template<typename genType>
|
||||
constexpr quaternion<genType> unit(const quaternion<genType>& q) {
|
||||
constexpr qua<genType> unit(const qua<genType>& q) {
|
||||
genType n = fennec::norm(q);
|
||||
return q * (genType(1) / n);
|
||||
}
|
||||
@@ -73,23 +74,10 @@ constexpr quaternion<genType> unit(const quaternion<genType>& q) {
|
||||
/// \param q The Quaternion
|
||||
/// \returns The quaternion \f${q}^{-1}\f$
|
||||
template<typename genType>
|
||||
constexpr quaternion<genType> reciprocal(const quaternion<genType>& q) {
|
||||
constexpr qua<genType> reciprocal(const qua<genType>& q) {
|
||||
return ~q / fennec::sqnorm(q);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr quaternion<genType> mix(const quaternion<genType>& x, const quaternion<genType>& y, genType a) {
|
||||
genType cT = fennec::dot(x, y);
|
||||
quaternion<genType> z = cT < genType(0) ? -y : y;
|
||||
cT = cT < genType(0) ? -cT : cT;
|
||||
|
||||
if (cT > genType(1) - numeric_limits<genType>::epsilon()) {
|
||||
return x * (genType(1) - a) + y * a;
|
||||
}
|
||||
|
||||
genType t = fennec::acos(cT);
|
||||
return (fennec::sin(x * (genType(1) - a) * t) + z * (fennec::sin(a * t))) / fennec::sin(t);
|
||||
}
|
||||
|
||||
template<typename ScalarT>
|
||||
struct quaternion : detail::vector_base_type<ScalarT, 4>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <fennec/math/matrix.h>
|
||||
#include <fennec/math/trigonometric.h>
|
||||
#include <fennec/math/ext/constants.h>
|
||||
#include <fennec/math/ext/quaternion.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
@@ -125,6 +126,14 @@ constexpr mat<genType, 4, 4> rotation(const vec<genType, 3>& A, genType a) {
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> rotation(const vec<genType, 3>& axis, genType angle) {
|
||||
vec<genType, 3> a = fennec::normalize(axis);
|
||||
const genType s = fennec::sin(angle);
|
||||
|
||||
return qua<genType>(fennec::cos(angle * genType(0.5)), s * a.x, s * a.y, s * a.z);
|
||||
}
|
||||
|
||||
/// \brief enum to denote the unit-axis of rotation
|
||||
enum rot_
|
||||
{
|
||||
|
||||
168
include/fennec/math/ext/trigonometric.h
Normal file
168
include/fennec/math/ext/trigonometric.h
Normal file
@@ -0,0 +1,168 @@
|
||||
// =====================================================================================================================
|
||||
// fennec, a free and open source game engine
|
||||
// Copyright © 2025 Medusa Slockbower
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// =====================================================================================================================
|
||||
|
||||
#ifndef FENNEC_MATH_EXT_TRIGONOMETRIC_H
|
||||
#define FENNEC_MATH_EXT_TRIGONOMETRIC_H
|
||||
|
||||
#include <fennec/math/trigonometric.h>
|
||||
#include <fennec/math/ext/quaternion.h>
|
||||
|
||||
namespace fennec
|
||||
{
|
||||
|
||||
// Angle Conversions ===================================================================================================
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> radians(const qua<genType>& degrees) {
|
||||
return qua<genType>(degrees * 0.01745329251994329576923690768489);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> degrees(const qua<genType>& radians) {
|
||||
return qua<genType>(radians * 57.29577951308232087679815481410517);
|
||||
}
|
||||
|
||||
|
||||
// Trigonometric Functions =============================================================================================
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> sin(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::sin(x.w),
|
||||
fennec::sin(x.x),
|
||||
fennec::sin(x.y),
|
||||
fennec::sin(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> cos(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::cos(x.w),
|
||||
fennec::cos(x.x),
|
||||
fennec::cos(x.y),
|
||||
fennec::cos(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> tan(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::tan(x.w),
|
||||
fennec::tan(x.x),
|
||||
fennec::tan(x.y),
|
||||
fennec::tan(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> asin(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::asin(x.w),
|
||||
fennec::asin(x.x),
|
||||
fennec::asin(x.y),
|
||||
fennec::asin(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> acos(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::acos(x.w),
|
||||
fennec::acos(x.x),
|
||||
fennec::acos(x.y),
|
||||
fennec::acos(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> atan(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::atan(x.w),
|
||||
fennec::atan(x.x),
|
||||
fennec::atan(x.y),
|
||||
fennec::atan(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Hyperbolic Functions ================================================================================================
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> sinh(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::sinh(x.w),
|
||||
fennec::sinh(x.x),
|
||||
fennec::sinh(x.y),
|
||||
fennec::sinh(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> cosh(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::cosh(x.w),
|
||||
fennec::cosh(x.x),
|
||||
fennec::cosh(x.y),
|
||||
fennec::cosh(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> tanh(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::tanh(x.w),
|
||||
fennec::tanh(x.x),
|
||||
fennec::tanh(x.y),
|
||||
fennec::tanh(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> asinh(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::asinh(x.w),
|
||||
fennec::asinh(x.x),
|
||||
fennec::asinh(x.y),
|
||||
fennec::asinh(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> acosh(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::acosh(x.w),
|
||||
fennec::acosh(x.x),
|
||||
fennec::acosh(x.y),
|
||||
fennec::acosh(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename genType>
|
||||
constexpr qua<genType> atanh(const qua<genType>& x) {
|
||||
return qua<genType>(
|
||||
fennec::atanh(x.w),
|
||||
fennec::atanh(x.x),
|
||||
fennec::atanh(x.y),
|
||||
fennec::atanh(x.z)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // FENNEC_MATH_EXT_TRIGONOMETRIC_H
|
||||
@@ -169,7 +169,7 @@ constexpr genType radians(genType degrees) {
|
||||
|
||||
template<typename genType, size_t...i>
|
||||
constexpr vector<genType, i...> radians(const vector<genType, i...>& degrees) {
|
||||
return genType(degrees * 0.01745329251994329576923690768489);
|
||||
return vector<genType, i...>(degrees * 0.01745329251994329576923690768489);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -326,6 +326,7 @@ public:
|
||||
///
|
||||
/// \brief Sized Constructor, initializes the allocation with a block of size `n * sizeof(T)` bytes
|
||||
/// \param n The number of elements of type `T` to allocate for
|
||||
/// \param align The alignment of the allocation
|
||||
constexpr allocation(size_t n, align_t align) noexcept
|
||||
: _data(nullptr)
|
||||
, _capacity(0)
|
||||
@@ -338,6 +339,7 @@ public:
|
||||
/// Then, the contents of data are copied into the allocation.
|
||||
/// \param data the buffer to copy
|
||||
/// \param n the number of elements
|
||||
/// \param align The alignment of the allocation
|
||||
constexpr allocation(const T* data, size_t n, align_t align)
|
||||
: allocation(n, align) {
|
||||
fennec::memcpy(_data, data, n);
|
||||
@@ -383,6 +385,7 @@ public:
|
||||
///
|
||||
/// \brief Sized Allocator Constructor
|
||||
/// \param n The number of elements of type `T` to allocate for
|
||||
/// \param align The alignment of the allocation
|
||||
/// \param alloc The allocation object to copy.
|
||||
///
|
||||
/// \details This constructor should be used when the type `AllocT` needs internal data.
|
||||
@@ -399,6 +402,7 @@ public:
|
||||
/// Then, the contents of data are copied into the allocation.
|
||||
/// \param data the buffer to copy
|
||||
/// \param n the number of elements
|
||||
/// \param align The alignment of the allocation
|
||||
/// \param alloc The allocation object to copy.
|
||||
///
|
||||
/// \details This constructor should be used when the type `AllocT` needs internal data.
|
||||
@@ -475,7 +479,7 @@ public:
|
||||
constexpr void allocate(size_t n, align_t align = zero<align_t>()) noexcept {
|
||||
deallocate();
|
||||
|
||||
if (_alignment != zero<align_t>()) {
|
||||
if (align != zero<align_t>()) {
|
||||
_data = _alloc.allocate(_capacity = n, _alignment = align);
|
||||
} else {
|
||||
_data = _alloc.allocate(_capacity = n);
|
||||
@@ -521,7 +525,7 @@ public:
|
||||
return _data[i];
|
||||
}
|
||||
|
||||
constexpr const value_t operator[](size_t i) const {
|
||||
constexpr const value_t& operator[](size_t i) const {
|
||||
assertd(i < size(), "Array Out of Bounds");
|
||||
return _data[i];
|
||||
}
|
||||
|
||||
@@ -69,7 +69,8 @@ using ::wmemcmp;
|
||||
|
||||
///
|
||||
/// \brief Safe version of memcmp
|
||||
/// \copydoc fennec::memcmp
|
||||
/// \param lhs The first object, interpreted as an array of bytes
|
||||
/// \param rhs The second object, interpreted as an array of bytes
|
||||
/// \param n0 The size, in bytes, of lhs
|
||||
/// \param n1 The size, in bytes, of rhs
|
||||
constexpr int memcmp_s(const void* lhs, size_t n0, const void* rhs, size_t n1) {
|
||||
@@ -93,7 +94,8 @@ using ::wmemcpy;
|
||||
|
||||
///
|
||||
/// \brief Safe version of memcpy
|
||||
/// \copydoc fennec::memcpy
|
||||
/// \param dst The destination object, interpreted as an array of bytes
|
||||
/// \param src The source object, interpreted as an array of bytes
|
||||
/// \param n0 The size, in bytes, of dst
|
||||
/// \param n1 The size, in bytes, of src
|
||||
constexpr void* memcpy_s(void* dst, size_t n0, const void* src, size_t n1) {
|
||||
@@ -111,7 +113,8 @@ using ::wmemmove;
|
||||
|
||||
///
|
||||
/// \brief Safe version of memmove
|
||||
/// \copydoc fennec::memmove
|
||||
/// \param dst The destination object, interpreted as an array of bytes
|
||||
/// \param src The source object, interpreted as an array of bytes
|
||||
/// \param n0 The size, in bytes, of dst
|
||||
/// \param n1 The size, in bytes, of src
|
||||
constexpr void* memmove_s(void* dst, size_t n0, const void* src, size_t n1) {
|
||||
|
||||
@@ -307,7 +307,7 @@ bool file::erase() {
|
||||
}
|
||||
|
||||
// Close the file
|
||||
path path = move(_path);
|
||||
const path path = move(_path);
|
||||
if (close()) {
|
||||
return true;
|
||||
}
|
||||
@@ -512,7 +512,7 @@ bool file::rename(const path& p) {
|
||||
}
|
||||
|
||||
// Validate path
|
||||
path fpath = p.absolute();
|
||||
const path fpath = p.absolute();
|
||||
if (_path == fpath) {
|
||||
return false;
|
||||
}
|
||||
@@ -783,7 +783,7 @@ file file::copy(const path& p) {
|
||||
}
|
||||
|
||||
// Validate path
|
||||
path fpath = p.absolute();
|
||||
const path fpath = p.absolute();
|
||||
if (_path == fpath) {
|
||||
return file();
|
||||
}
|
||||
@@ -951,7 +951,7 @@ size_t file::read(void* data, size_t size, size_t n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t read = fread(data, size, n, _handle);
|
||||
const size_t read = fread(data, size, n, _handle);
|
||||
if (read != size && ferror(_handle)) {
|
||||
_error = strerror(errno);
|
||||
}
|
||||
@@ -971,7 +971,7 @@ string file::getline() {
|
||||
// Read the next line;
|
||||
char* line = nullptr;
|
||||
size_t size = 0;
|
||||
size_t read = ::getline(&line, &size, _handle);
|
||||
const size_t read = ::getline(&line, &size, _handle);
|
||||
if (read == npos && ferror(_handle)) {
|
||||
_error = strerror(errno);
|
||||
if (line) free(line);
|
||||
@@ -1053,7 +1053,7 @@ size_t file::write(const void* data, size_t size, size_t n) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t r = fwrite(data, size, n, _handle);
|
||||
const size_t r = fwrite(data, size, n, _handle);
|
||||
|
||||
if (r != size && ferror(_handle)) {
|
||||
_error = strerror(errno);
|
||||
|
||||
@@ -27,11 +27,11 @@ namespace fennec
|
||||
namespace test
|
||||
{
|
||||
|
||||
static char test_string[] = "Hello World!";
|
||||
static const char test_string_const[] = "Hello World!";
|
||||
|
||||
inline void fennec_test_fproc_strings_cstring()
|
||||
{
|
||||
static char test_string[] = "Hello World!";
|
||||
static const char test_string_const[] = "Hello World!";
|
||||
|
||||
cstring str = test_string;
|
||||
const cstring cstr = test_string_const;
|
||||
|
||||
@@ -40,12 +40,12 @@ inline void fennec_test_fproc_strings_cstring()
|
||||
|
||||
fennec_test_spacer(1);
|
||||
|
||||
fennec_test_run(str.length(), size_t(12));
|
||||
fennec_test_run(str.length(), static_cast<size_t>(12));
|
||||
fennec_test_run(str.compare(cstr), 0);
|
||||
fennec_test_run(str.find('W'), size_t(6));
|
||||
fennec_test_run(str.find("World"), size_t(6));
|
||||
fennec_test_run(str.rfind('o'), size_t(7));
|
||||
fennec_test_run(str.rfind("World"), size_t(6));
|
||||
fennec_test_run(str.find('W'), static_cast<size_t>(6));
|
||||
fennec_test_run(str.find("World"), static_cast<size_t>(6));
|
||||
fennec_test_run(str.rfind('o'), static_cast<size_t>(7));
|
||||
fennec_test_run(str.rfind("World"), static_cast<size_t>(6));
|
||||
|
||||
fennec_test_spacer(2);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user