| @@ -17,10 +17,11 @@ | |||||
| // ——————————————————————— | // ——————————————————————— | ||||
| // | // | ||||
| #include <iostream> | |||||
| #include <iomanip> | |||||
| #include <sstream> | |||||
| #include <cstdio> | |||||
| #include <iostream> // std::cout | |||||
| #include <iomanip> // std::setprecision | |||||
| #include <sstream> // std::stringstream | |||||
| #include <string> // std::string | |||||
| #include <cmath> // std::fabs | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -18,7 +18,9 @@ | |||||
| // Provides various color conversion routines. | // Provides various color conversion routines. | ||||
| // | // | ||||
| #include <lol/math/vector.h> | |||||
| #include <../legacy/lol/math/functions.h> // FIXME: try to remove this | |||||
| #include <lol/math/vector.h> // vec_t | |||||
| #include <lol/math/transform.h> // mat_t | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -25,6 +25,7 @@ | |||||
| #include <functional> // std::function | #include <functional> // std::function | ||||
| #include <tuple> // std::tuple | #include <tuple> // std::tuple | ||||
| #include <cassert> // assert() | #include <cassert> // assert() | ||||
| #include <cmath> // sqrt(), cbrt(), acos() | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -114,6 +115,9 @@ struct [[nodiscard]] polynomial | |||||
| std::vector<T> roots() const | std::vector<T> roots() const | ||||
| { | { | ||||
| using std::cos, std::acos, std::atan2; | |||||
| using std::sqrt, std::cbrt, std::fabs; | |||||
| /* For now we can only solve polynomials of degrees 0, 1, 2 or 3. */ | /* For now we can only solve polynomials of degrees 0, 1, 2 or 3. */ | ||||
| assert(degree() >= 0 && degree() <= 3); | assert(degree() >= 0 && degree() <= 3); | ||||
| @@ -212,8 +216,8 @@ struct [[nodiscard]] polynomial | |||||
| { | { | ||||
| T const sqrt_delta = sqrt(delta); | T const sqrt_delta = sqrt(delta); | ||||
| u_norm = cbrt(abs(n - sqrt_delta) / T(2)); | |||||
| v_norm = cbrt(abs(n + sqrt_delta) / T(2)); | |||||
| u_norm = cbrt(fabs(n - sqrt_delta) / T(2)); | |||||
| v_norm = cbrt(fabs(n + sqrt_delta) / T(2)); | |||||
| u3_angle = (n >= sqrt_delta) ? pi : 0; | u3_angle = (n >= sqrt_delta) ? pi : 0; | ||||
| v3_angle = (n <= -sqrt_delta) ? 0 : -pi; | v3_angle = (n <= -sqrt_delta) ? 0 : -pi; | ||||
| @@ -117,10 +117,6 @@ private: | |||||
| vec_t<T,2> m_data[2]; | vec_t<T,2> m_data[2]; | ||||
| }; | }; | ||||
| static_assert(sizeof(imat2) == 16, "sizeof(imat2) == 16"); | |||||
| static_assert(sizeof(mat2) == 16, "sizeof(mat2) == 16"); | |||||
| static_assert(sizeof(dmat2) == 32, "sizeof(dmat2) == 32"); | |||||
| /* | /* | ||||
| * 3×3-element matrices | * 3×3-element matrices | ||||
| */ | */ | ||||
| @@ -207,10 +203,6 @@ private: | |||||
| vec_t<T,3> m_data[3]; | vec_t<T,3> m_data[3]; | ||||
| }; | }; | ||||
| static_assert(sizeof(imat3) == 36, "sizeof(imat3) == 36"); | |||||
| static_assert(sizeof(mat3) == 36, "sizeof(mat3) == 36"); | |||||
| static_assert(sizeof(dmat3) == 72, "sizeof(dmat3) == 72"); | |||||
| /* | /* | ||||
| * 4×4-element matrices | * 4×4-element matrices | ||||
| */ | */ | ||||
| @@ -340,10 +332,6 @@ private: | |||||
| vec_t<T,4> m_data[4]; | vec_t<T,4> m_data[4]; | ||||
| }; | }; | ||||
| static_assert(sizeof(imat4) == 64, "sizeof(imat4) == 64"); | |||||
| static_assert(sizeof(mat4) == 64, "sizeof(mat4) == 64"); | |||||
| static_assert(sizeof(dmat4) == 128, "sizeof(dmat4) == 128"); | |||||
| /* | /* | ||||
| * stdstream method implementations | * stdstream method implementations | ||||
| */ | */ | ||||
| @@ -383,8 +371,6 @@ static inline mat_t<T, ROWS, COLS> transpose(mat_t<T, COLS, ROWS> const &m) | |||||
| template<typename T, int N> | template<typename T, int N> | ||||
| mat_t<T, N - 1, N - 1> submatrix(mat_t<T, N, N> const &m, int i, int j) | mat_t<T, N - 1, N - 1> submatrix(mat_t<T, N, N> const &m, int i, int j) | ||||
| { | { | ||||
| ASSERT(i >= 0); ASSERT(j >= 0); ASSERT(i < N); ASSERT(j < N); | |||||
| mat_t<T, N - 1, N - 1> ret; | mat_t<T, N - 1, N - 1> ret; | ||||
| for (int i2 = 0; i2 < N - 1; ++i2) | for (int i2 = 0; i2 < N - 1; ++i2) | ||||
| for (int j2 = 0; j2 < N - 1; ++j2) | for (int j2 = 0; j2 < N - 1; ++j2) | ||||
| @@ -400,7 +386,6 @@ mat_t<T, N - 1, N - 1> submatrix(mat_t<T, N, N> const &m, int i, int j) | |||||
| template<typename T, int N> [[nodiscard]] | template<typename T, int N> [[nodiscard]] | ||||
| T cofactor(mat_t<T, N, N> const &m, int i, int j) | T cofactor(mat_t<T, N, N> const &m, int i, int j) | ||||
| { | { | ||||
| ASSERT(i >= 0); ASSERT(j >= 0); ASSERT(i < N); ASSERT(j < N); | |||||
| T tmp = determinant(submatrix(m, i, j)); | T tmp = determinant(submatrix(m, i, j)); | ||||
| return ((i + j) & 1) ? -tmp : tmp; | return ((i + j) & 1) ? -tmp : tmp; | ||||
| } | } | ||||
| @@ -409,7 +394,6 @@ template<typename T> [[nodiscard]] | |||||
| T cofactor(mat_t<T, 2, 2> const &m, int i, int j) | T cofactor(mat_t<T, 2, 2> const &m, int i, int j) | ||||
| { | { | ||||
| /* This specialisation shouldn't be needed, but Visual Studio. */ | /* This specialisation shouldn't be needed, but Visual Studio. */ | ||||
| ASSERT(i >= 0); ASSERT(j >= 0); ASSERT(i < 2); ASSERT(j < 2); | |||||
| T tmp = m[1 - i][1 - j]; | T tmp = m[1 - i][1 - j]; | ||||
| return (i ^ j) ? -tmp : tmp; | return (i ^ j) ? -tmp : tmp; | ||||
| } | } | ||||
| @@ -430,7 +414,7 @@ std::tuple<mat_t<T, N, N>, vec_t<int, N>, int> lu_decomposition(mat_t<T, N, N> c | |||||
| // Find row with the largest absolute value | // Find row with the largest absolute value | ||||
| int best_j = k; | int best_j = k; | ||||
| for (int j = k + 1; j < N; ++j) | for (int j = k + 1; j < N; ++j) | ||||
| if (abs(lu[k][j]) > lol::abs(lu[k][best_j])) | |||||
| if (fabs(lu[k][j]) > fabs(lu[k][best_j])) | |||||
| best_j = j; | best_j = j; | ||||
| // Swap rows in result | // Swap rows in result | ||||
| @@ -13,7 +13,8 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <cassert> | #include <cassert> | ||||
| #include <cmath> | |||||
| #include <cmath> // std::tan | |||||
| #include <algorithm> // std::max | |||||
| #if _WIN32 | #if _WIN32 | ||||
| # pragma push_macro("near") | # pragma push_macro("near") | ||||
| @@ -256,7 +257,9 @@ template<> | |||||
| inline mat4 mat4::perspective(float fov_y, float width, | inline mat4 mat4::perspective(float fov_y, float width, | ||||
| float height, float near, float far) | float height, float near, float far) | ||||
| { | { | ||||
| float t2 = lol::tan(fov_y * 0.5f); | |||||
| using std::tan; | |||||
| float t2 = tan(fov_y * 0.5f); | |||||
| float t1 = t2 * width / height; | float t1 = t2 * width / height; | ||||
| return frustum(-near * t1, near * t1, -near * t2, near * t2, near, far); | return frustum(-near * t1, near * t1, -near * t2, near * t2, near, far); | ||||
| @@ -272,13 +275,15 @@ inline mat4 mat4::shifted_perspective(float fov_y, float screen_size, | |||||
| float screen_ratio_yx, | float screen_ratio_yx, | ||||
| float near, float far) | float near, float far) | ||||
| { | { | ||||
| float tan_y = tanf(fov_y * .5f); | |||||
| using std::tan; | |||||
| float tan_y = tan(fov_y * .5f); | |||||
| assert(tan_y > 0.000001f); | assert(tan_y > 0.000001f); | ||||
| float dist_scr = (screen_size * screen_ratio_yx * .5f) / tan_y; | float dist_scr = (screen_size * screen_ratio_yx * .5f) / tan_y; | ||||
| return mat4::perspective(fov_y, screen_size, screen_size * screen_ratio_yx, | return mat4::perspective(fov_y, screen_size, screen_size * screen_ratio_yx, | ||||
| max(.001f, dist_scr + near), | |||||
| max(.001f, dist_scr + far)) * | |||||
| std::max(.001f, dist_scr + near), | |||||
| std::max(.001f, dist_scr + far)) * | |||||
| mat4::translate(.0f, .0f, -dist_scr); | mat4::translate(.0f, .0f, -dist_scr); | ||||
| } | } | ||||
| @@ -20,9 +20,16 @@ | |||||
| #include <ostream> | #include <ostream> | ||||
| #include <type_traits> | #include <type_traits> | ||||
| // HACK: if this is declared int const, Visual Studio becomes unable | |||||
| // to perform template argument deduction. | |||||
| // FIXME: should we get rid of this #define? | |||||
| #define FULL_SWIZZLE (0) | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| template<typename T, int N, int SWIZZLE = FULL_SWIZZLE> struct vec_t; | |||||
| /* | /* | ||||
| * Utility namespaces for traits -- this file uses a combination of | * Utility namespaces for traits -- this file uses a combination of | ||||
| * ADL black magic and enable_if to ensure that only the expected type | * ADL black magic and enable_if to ensure that only the expected type | ||||
| @@ -12,6 +12,8 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <cmath> // std::cos, std::sin | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -31,10 +33,10 @@ inline std::string quat::tostring() const | |||||
| template<> | template<> | ||||
| inline quat quat::rotate(float radians, vec3 const &v) | inline quat quat::rotate(float radians, vec3 const &v) | ||||
| { | { | ||||
| float half_angle = radians * 0.5f; | |||||
| using std::sin, std::cos; | |||||
| float half_angle = radians * 0.5f; | |||||
| vec3 tmp = normalize(v) * sin(half_angle); | vec3 tmp = normalize(v) * sin(half_angle); | ||||
| return quat(cos(half_angle), tmp.x, tmp.y, tmp.z); | return quat(cos(half_angle), tmp.x, tmp.y, tmp.z); | ||||
| } | } | ||||
| @@ -47,10 +49,12 @@ inline quat quat::rotate(float radians, float x, float y, float z) | |||||
| template<> | template<> | ||||
| inline quat quat::rotate(vec3 const &src, vec3 const &dst) | inline quat quat::rotate(vec3 const &src, vec3 const &dst) | ||||
| { | { | ||||
| using std::sqrt; | |||||
| /* Algorithm directly taken from Sam Hocevar's article "Quaternion from | /* Algorithm directly taken from Sam Hocevar's article "Quaternion from | ||||
| * two vectors: the final version". | * two vectors: the final version". | ||||
| * http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final */ | * http://lolengine.net/blog/2014/02/24/quaternion-from-two-vectors-final */ | ||||
| float magnitude = lol::sqrt(sqlength(src) * sqlength(dst)); | |||||
| float magnitude = sqrt(sqlength(src) * sqlength(dst)); | |||||
| float real_part = magnitude + dot(src, dst); | float real_part = magnitude + dot(src, dst); | ||||
| vec3 w; | vec3 w; | ||||
| @@ -60,8 +64,7 @@ inline quat quat::rotate(vec3 const &src, vec3 const &dst) | |||||
| * around an arbitrary orthogonal axis. Axis normalisation | * around an arbitrary orthogonal axis. Axis normalisation | ||||
| * can happen later, when we normalise the quaternion. */ | * can happen later, when we normalise the quaternion. */ | ||||
| real_part = 0.0f; | real_part = 0.0f; | ||||
| w = abs(src.x) > abs(src.z) ? vec3(-src.y, src.x, 0.f) | |||||
| : vec3(0.f, -src.z, src.y); | |||||
| w = orthogonal(src); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -75,8 +78,10 @@ inline quat quat::rotate(vec3 const &src, vec3 const &dst) | |||||
| template<> | template<> | ||||
| inline quat slerp(quat const &qa, quat const &qb, float f) | inline quat slerp(quat const &qa, quat const &qb, float f) | ||||
| { | { | ||||
| float const magnitude = lol::sqrt(sqlength(qa) * sqlength(qb)); | |||||
| float const product = lol::dot(qa, qb) / magnitude; | |||||
| using std::sin, std::cos, std::sqrt, std::acos; | |||||
| float const magnitude = sqrt(sqlength(qa) * sqlength(qb)); | |||||
| float const product = dot(qa, qb) / magnitude; | |||||
| /* If quaternions are equal or opposite, there is no need | /* If quaternions are equal or opposite, there is no need | ||||
| * to slerp anything, just return qa. */ | * to slerp anything, just return qa. */ | ||||
| @@ -84,18 +89,25 @@ inline quat slerp(quat const &qa, quat const &qb, float f) | |||||
| return qa; | return qa; | ||||
| float const sign = (product < 0.0f) ? -1.0f : 1.0f; | float const sign = (product < 0.0f) ? -1.0f : 1.0f; | ||||
| float const theta = lol::acos(sign * product); | |||||
| float const s1 = lol::sin(sign * f * theta); | |||||
| float const s0 = lol::sin((1.0f - f) * theta); | |||||
| float const theta = acos(sign * product); | |||||
| float const s1 = sin(sign * f * theta); | |||||
| float const s0 = sin((1.0f - f) * theta); | |||||
| /* This is the same as 1/sin(theta) */ | /* This is the same as 1/sin(theta) */ | ||||
| float const d = 1.0f / lol::sqrt(1.f - product * product); | |||||
| float const d = 1.0f / sqrt(1.f - product * product); | |||||
| return qa * (s0 * d) + qb * (s1 * d); | return qa * (s0 * d) + qb * (s1 * d); | ||||
| } | } | ||||
| static inline float sq(float x) | |||||
| { | |||||
| return x * x; | |||||
| } | |||||
| static inline vec3 quat_toeuler_generic(quat const &q, int i, int j, int k) | static inline vec3 quat_toeuler_generic(quat const &q, int i, int j, int k) | ||||
| { | { | ||||
| using std::atan2, std::acos, std::asin; | |||||
| float n = norm(q); | float n = norm(q); | ||||
| if (!n) | if (!n) | ||||
| @@ -132,6 +144,8 @@ static inline vec3 quat_toeuler_generic(quat const &q, int i, int j, int k) | |||||
| static inline mat3 mat3_fromeuler_generic(vec3 const &v, int i, int j, int k) | static inline mat3 mat3_fromeuler_generic(vec3 const &v, int i, int j, int k) | ||||
| { | { | ||||
| using std::sin, std::cos; | |||||
| mat3 ret; | mat3 ret; | ||||
| float const s0 = sin(v[0]), c0 = cos(v[0]); | float const s0 = sin(v[0]), c0 = cos(v[0]); | ||||
| @@ -179,6 +193,8 @@ static inline mat3 mat3_fromeuler_generic(vec3 const &v, int i, int j, int k) | |||||
| static inline quat quat_fromeuler_generic(vec3 const &v, int i, int j, int k) | static inline quat quat_fromeuler_generic(vec3 const &v, int i, int j, int k) | ||||
| { | { | ||||
| using std::sin, std::cos; | |||||
| vec3 const half_angles = v * 0.5f; | vec3 const half_angles = v * 0.5f; | ||||
| float const s0 = sin(half_angles[0]), c0 = cos(half_angles[0]); | float const s0 = sin(half_angles[0]), c0 = cos(half_angles[0]); | ||||
| float const s1 = sin(half_angles[1]), c1 = cos(half_angles[1]); | float const s1 = sin(half_angles[1]), c1 = cos(half_angles[1]); | ||||
| @@ -218,7 +234,7 @@ static inline quat quat_fromeuler_generic(vec3 const &v, int i, int j, int k) | |||||
| /* Create quaternions from Euler angles */ \ | /* Create quaternions from Euler angles */ \ | ||||
| template<> inline quat quat::fromeuler_##name(vec3 const &v) \ | template<> inline quat quat::fromeuler_##name(vec3 const &v) \ | ||||
| { \ | { \ | ||||
| int x = 0, y = 1, z = 2; UNUSED(x, y, z); \ | |||||
| int x = 0, y = 1, z = 2; (void)x, (void)y, (void)z; \ | |||||
| return quat_fromeuler_generic(v, a1, a2, a3); \ | return quat_fromeuler_generic(v, a1, a2, a3); \ | ||||
| } \ | } \ | ||||
| \ | \ | ||||
| @@ -230,7 +246,7 @@ static inline quat quat_fromeuler_generic(vec3 const &v, int i, int j, int k) | |||||
| /* Create 3×3 matrices from Euler angles */ \ | /* Create 3×3 matrices from Euler angles */ \ | ||||
| template<> inline mat3 mat3::fromeuler_##name(vec3 const &v) \ | template<> inline mat3 mat3::fromeuler_##name(vec3 const &v) \ | ||||
| { \ | { \ | ||||
| int x = 0, y = 1, z = 2; UNUSED(x, y, z); \ | |||||
| int x = 0, y = 1, z = 2; (void)x, (void)y, (void)z; \ | |||||
| return mat3_fromeuler_generic(v, a1, a2, a3); \ | return mat3_fromeuler_generic(v, a1, a2, a3); \ | ||||
| } \ | } \ | ||||
| \ | \ | ||||
| @@ -242,7 +258,7 @@ static inline quat quat_fromeuler_generic(vec3 const &v, int i, int j, int k) | |||||
| /* Create 4×4 matrices from Euler angles */ \ | /* Create 4×4 matrices from Euler angles */ \ | ||||
| template<> inline mat4 mat4::fromeuler_##name(vec3 const &v) \ | template<> inline mat4 mat4::fromeuler_##name(vec3 const &v) \ | ||||
| { \ | { \ | ||||
| int x = 0, y = 1, z = 2; UNUSED(x, y, z); \ | |||||
| int x = 0, y = 1, z = 2; (void)x, (void)y, (void)z; \ | |||||
| return mat4(mat3_fromeuler_generic(v, a1, a2, a3), 1.f); \ | return mat4(mat3_fromeuler_generic(v, a1, a2, a3), 1.f); \ | ||||
| } \ | } \ | ||||
| \ | \ | ||||
| @@ -254,7 +270,7 @@ static inline quat quat_fromeuler_generic(vec3 const &v, int i, int j, int k) | |||||
| /* Retrieve Euler angles from a quaternion */ \ | /* Retrieve Euler angles from a quaternion */ \ | ||||
| template<> inline vec3 vec3::toeuler_##name(quat const &q) \ | template<> inline vec3 vec3::toeuler_##name(quat const &q) \ | ||||
| { \ | { \ | ||||
| int x = 0, y = 1, z = 2; UNUSED(x, y, z); \ | |||||
| int x = 0, y = 1, z = 2; (void)x, (void)y, (void)z; \ | |||||
| return quat_toeuler_generic(q, a1, a2, a3); \ | return quat_toeuler_generic(q, a1, a2, a3); \ | ||||
| } | } | ||||
| @@ -12,6 +12,8 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <lol/base/private/string.h> // lol::format | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -20,7 +20,8 @@ | |||||
| #include <lol/math/private/ops.h> | #include <lol/math/private/ops.h> | ||||
| #include <lol/math/vector.h> | #include <lol/math/vector.h> | ||||
| #include <ostream> | |||||
| #include <ostream> // std::ostream | |||||
| #include <cmath> // std::atan2, std::sqrt | |||||
| #include "private/matrix.h" | #include "private/matrix.h" | ||||
| @@ -71,9 +72,6 @@ struct [[nodiscard]] cmplx_t : public linear_ops::base<T> | |||||
| T x, y; | T x, y; | ||||
| }; | }; | ||||
| static_assert(sizeof(cmplx) == 8, "sizeof(cmplx) == 8"); | |||||
| static_assert(sizeof(dcmplx) == 16, "sizeof(dcmplx) == 16"); | |||||
| /* | /* | ||||
| * 4-element transforms: quaternions | * 4-element transforms: quaternions | ||||
| */ | */ | ||||
| @@ -104,11 +102,13 @@ struct [[nodiscard]] quat_t : public linear_ops::base<T> | |||||
| /* Construct a unit quaternion from a pure rotation matrix */ | /* Construct a unit quaternion from a pure rotation matrix */ | ||||
| explicit quat_t(mat_t<T,3,3> const &m) | explicit quat_t(mat_t<T,3,3> const &m) | ||||
| { | { | ||||
| using std::sqrt; | |||||
| T tr = m[0][0] + m[1][1] + m[2][2]; | T tr = m[0][0] + m[1][1] + m[2][2]; | ||||
| if (tr > T(0)) | if (tr > T(0)) | ||||
| { | { | ||||
| T const p = T(0.5) * std::sqrt(T(1) + tr); | |||||
| T const p = T(0.5) * sqrt(T(1) + tr); | |||||
| T const q = T(0.25) / p; | T const q = T(0.25) / p; | ||||
| w = p; | w = p; | ||||
| @@ -123,7 +123,7 @@ struct [[nodiscard]] quat_t : public linear_ops::base<T> | |||||
| : 2; | : 2; | ||||
| int j = (i + 1) % 3, k = (i + 2) % 3; | int j = (i + 1) % 3, k = (i + 2) % 3; | ||||
| T const p = T(0.5) * lol::sqrt(T(1) - tr + m[i][i] + m[i][i]); | |||||
| T const p = T(0.5) * sqrt(T(1) - tr + m[i][i] + m[i][i]); | |||||
| T const q = T(0.25) / p; | T const q = T(0.25) / p; | ||||
| w = q * (m[j][k] - m[k][j]); | w = q * (m[j][k] - m[k][j]); | ||||
| @@ -235,11 +235,13 @@ struct [[nodiscard]] quat_t : public linear_ops::base<T> | |||||
| [[nodiscard]] inline T angle() | [[nodiscard]] inline T angle() | ||||
| { | { | ||||
| using std::atan2, std::sqrt; | |||||
| vec_t<T,3> v(x, y, z); | vec_t<T,3> v(x, y, z); | ||||
| T n2 = sqlength(v); | T n2 = sqlength(v); | ||||
| if (n2 <= (T)1e-6) | if (n2 <= (T)1e-6) | ||||
| return (T)0; | return (T)0; | ||||
| return (T)2 * lol::atan2(lol::sqrt(n2), w); | |||||
| return (T)2 * atan2(sqrt(n2), w); | |||||
| } | } | ||||
| template<typename U> | template<typename U> | ||||
| @@ -249,9 +251,6 @@ struct [[nodiscard]] quat_t : public linear_ops::base<T> | |||||
| T w, x, y, z; | T w, x, y, z; | ||||
| }; | }; | ||||
| static_assert(sizeof(quat) == 16, "sizeof(quat) == 16"); | |||||
| static_assert(sizeof(dquat) == 32, "sizeof(dquat) == 32"); | |||||
| /* | /* | ||||
| * SQT transforms: scale / rotation / translation | * SQT transforms: scale / rotation / translation | ||||
| */ | */ | ||||
| @@ -359,6 +358,7 @@ static inline T sqlength(cmplx_t<T> const &t) | |||||
| template<typename T> [[nodiscard]] | template<typename T> [[nodiscard]] | ||||
| static inline T length(cmplx_t<T> const &t) | static inline T length(cmplx_t<T> const &t) | ||||
| { | { | ||||
| using std::sqrt; | |||||
| /* FIXME: this is not very nice */ | /* FIXME: this is not very nice */ | ||||
| return (T)sqrt((double)sqlength(t)); | return (T)sqrt((double)sqlength(t)); | ||||
| } | } | ||||
| @@ -396,8 +396,9 @@ static inline T sqlength(quat_t<T> const &t) | |||||
| template<typename T> [[nodiscard]] | template<typename T> [[nodiscard]] | ||||
| static inline T length(quat_t<T> const &t) | static inline T length(quat_t<T> const &t) | ||||
| { | { | ||||
| using std::sqrt; | |||||
| /* FIXME: this is not very nice */ | /* FIXME: this is not very nice */ | ||||
| return (T)sqrt((double)sqlength(t)); | |||||
| return (T)sqrt(sqlength(t)); | |||||
| } | } | ||||
| template<typename T> [[nodiscard]] | template<typename T> [[nodiscard]] | ||||
| @@ -496,7 +497,99 @@ static inline sqt_t<T> operator /(sqt_t<T> const &x, sqt_t<T> const &y) | |||||
| return x * inverse(y); | return x * inverse(y); | ||||
| } | } | ||||
| } /* namespace lol */ | |||||
| // | |||||
| // Generic GLSL-like type names | |||||
| // | |||||
| #define T_(tleft, tright, suffix) \ | |||||
| typedef tleft half tright f16##suffix; \ | |||||
| typedef tleft float tright suffix; \ | |||||
| typedef tleft double tright d##suffix; \ | |||||
| typedef tleft ldouble tright f128##suffix; \ | |||||
| typedef tleft int8_t tright i8##suffix; \ | |||||
| typedef tleft uint8_t tright u8##suffix; \ | |||||
| typedef tleft int16_t tright i16##suffix; \ | |||||
| typedef tleft uint16_t tright u16##suffix; \ | |||||
| typedef tleft int32_t tright i##suffix; \ | |||||
| typedef tleft uint32_t tright u##suffix; \ | |||||
| typedef tleft int64_t tright i64##suffix; \ | |||||
| typedef tleft uint64_t tright u64##suffix; \ | |||||
| typedef tleft real tright r##suffix; | |||||
| /* Idiotic hack to put "," inside a macro argument */ | |||||
| #define C_ , | |||||
| T_(mat_t<, C_ 2 C_ 2>, mat2) | |||||
| T_(mat_t<, C_ 3 C_ 3>, mat3) | |||||
| T_(mat_t<, C_ 4 C_ 4>, mat4) | |||||
| T_(mat_t<, C_ 2 C_ 3>, mat2x3) | |||||
| T_(mat_t<, C_ 2 C_ 4>, mat2x4) | |||||
| T_(mat_t<, C_ 3 C_ 2>, mat3x2) | |||||
| T_(mat_t<, C_ 3 C_ 4>, mat3x4) | |||||
| T_(mat_t<, C_ 4 C_ 2>, mat4x2) | |||||
| T_(mat_t<, C_ 4 C_ 3>, mat4x3) | |||||
| T_(cmplx_t<, >, cmplx) | |||||
| T_(quat_t<, >, quat) | |||||
| T_(sqt_t<, >, sqt) | |||||
| #undef C_ | |||||
| #undef T_ | |||||
| static_assert(sizeof(cmplx) == 8, "sizeof(cmplx) == 8"); | |||||
| static_assert(sizeof(dcmplx) == 16, "sizeof(dcmplx) == 16"); | |||||
| static_assert(sizeof(quat) == 16, "sizeof(quat) == 16"); | |||||
| static_assert(sizeof(dquat) == 32, "sizeof(dquat) == 32"); | |||||
| static_assert(sizeof(imat2) == 16, "sizeof(imat2) == 16"); | |||||
| static_assert(sizeof(mat2) == 16, "sizeof(mat2) == 16"); | |||||
| static_assert(sizeof(dmat2) == 32, "sizeof(dmat2) == 32"); | |||||
| static_assert(sizeof(imat3) == 36, "sizeof(imat3) == 36"); | |||||
| static_assert(sizeof(mat3) == 36, "sizeof(mat3) == 36"); | |||||
| static_assert(sizeof(dmat3) == 72, "sizeof(dmat3) == 72"); | |||||
| static_assert(sizeof(imat4) == 64, "sizeof(imat4) == 64"); | |||||
| static_assert(sizeof(mat4) == 64, "sizeof(mat4) == 64"); | |||||
| static_assert(sizeof(dmat4) == 128, "sizeof(dmat4) == 128"); | |||||
| // | |||||
| // HLSL/Cg-compliant type names | |||||
| // | |||||
| typedef mat2 float2x2; | |||||
| typedef mat3 float3x3; | |||||
| typedef mat4 float4x4; | |||||
| typedef mat2x3 float2x3; | |||||
| typedef mat2x4 float2x4; | |||||
| typedef mat3x2 float3x2; | |||||
| typedef mat3x4 float3x4; | |||||
| typedef mat4x2 float4x2; | |||||
| typedef mat4x3 float4x3; | |||||
| typedef f16mat2 half2x2; | |||||
| typedef f16mat3 half3x3; | |||||
| typedef f16mat4 half4x4; | |||||
| typedef f16mat2x3 half2x3; | |||||
| typedef f16mat2x4 half2x4; | |||||
| typedef f16mat3x2 half3x2; | |||||
| typedef f16mat3x4 half3x4; | |||||
| typedef f16mat4x2 half4x2; | |||||
| typedef f16mat4x3 half4x3; | |||||
| typedef imat2 int2x2; | |||||
| typedef imat3 int3x3; | |||||
| typedef imat4 int4x4; | |||||
| typedef imat2x3 int2x3; | |||||
| typedef imat2x4 int2x4; | |||||
| typedef imat3x2 int3x2; | |||||
| typedef imat3x4 int3x4; | |||||
| typedef imat4x2 int4x2; | |||||
| typedef imat4x3 int4x3; | |||||
| } // namespace lol | |||||
| #include "private/matrix.ipp" | #include "private/matrix.ipp" | ||||
| #include "private/transform.ipp" | #include "private/transform.ipp" | ||||
| @@ -17,15 +17,21 @@ | |||||
| // —————————————————— | // —————————————————— | ||||
| // | // | ||||
| #include <lol/math/private/ops.h> | |||||
| #include <cassert> | #include <cassert> | ||||
| #include <ostream> // std::ostream | #include <ostream> // std::ostream | ||||
| #include <type_traits> | #include <type_traits> | ||||
| #include <cmath> // std::fabs, std::cos… | |||||
| // FIXME: get rid of this, too | |||||
| #include <../legacy/lol/base/types.h> | |||||
| #include "private/ops.h" | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| template<typename T> struct quat_t; | |||||
| /* | /* | ||||
| * Magic vector swizzling | * Magic vector swizzling | ||||
| * | * | ||||
| @@ -188,7 +194,7 @@ private: | |||||
| static inline void internal_init(T *data) | static inline void internal_init(T *data) | ||||
| { | { | ||||
| UNUSED(data); | |||||
| (void)data; | |||||
| } | } | ||||
| T m_data[count]; | T m_data[count]; | ||||
| @@ -296,14 +302,6 @@ struct [[nodiscard]] vec_t<T,2> | |||||
| }; | }; | ||||
| }; | }; | ||||
| static_assert(sizeof(i8vec2) == 2, "sizeof(i8vec2) == 2"); | |||||
| static_assert(sizeof(i16vec2) == 4, "sizeof(i16vec2) == 4"); | |||||
| static_assert(sizeof(ivec2) == 8, "sizeof(ivec2) == 8"); | |||||
| static_assert(sizeof(i64vec2) == 16, "sizeof(i64vec2) == 16"); | |||||
| static_assert(sizeof(vec2) == 8, "sizeof(vec2) == 8"); | |||||
| static_assert(sizeof(dvec2) == 16, "sizeof(dvec2) == 16"); | |||||
| /* | /* | ||||
| * 3-element vectors | * 3-element vectors | ||||
| */ | */ | ||||
| @@ -388,7 +386,9 @@ struct [[nodiscard]] vec_t<T,3> | |||||
| /* Return a vector that is orthogonal to “a” */ | /* Return a vector that is orthogonal to “a” */ | ||||
| friend inline type orthogonal(type const &a) | friend inline type orthogonal(type const &a) | ||||
| { | { | ||||
| return lol::abs(a.x) > lol::abs(a.z) | |||||
| using std::fabs; | |||||
| return fabs(a.x) > fabs(a.z) | |||||
| ? type(-a.y, a.x, T(0)) | ? type(-a.y, a.x, T(0)) | ||||
| : type(T(0), -a.z, a.y); | : type(T(0), -a.z, a.y); | ||||
| } | } | ||||
| @@ -536,14 +536,6 @@ struct [[nodiscard]] vec_t<T,3> | |||||
| }; | }; | ||||
| }; | }; | ||||
| static_assert(sizeof(i8vec3) == 3, "sizeof(i8vec3) == 3"); | |||||
| static_assert(sizeof(i16vec3) == 6, "sizeof(i16vec3) == 6"); | |||||
| static_assert(sizeof(ivec3) == 12, "sizeof(ivec3) == 12"); | |||||
| static_assert(sizeof(i64vec3) == 24, "sizeof(i64vec3) == 24"); | |||||
| static_assert(sizeof(vec3) == 12, "sizeof(vec3) == 12"); | |||||
| static_assert(sizeof(dvec3) == 24, "sizeof(dvec3) == 24"); | |||||
| /* | /* | ||||
| * 4-element vectors | * 4-element vectors | ||||
| */ | */ | ||||
| @@ -968,14 +960,6 @@ struct [[nodiscard]] vec_t<T,4> | |||||
| }; | }; | ||||
| }; | }; | ||||
| static_assert(sizeof(i8vec4) == 4, "sizeof(i8vec4) == 4"); | |||||
| static_assert(sizeof(i16vec4) == 8, "sizeof(i16vec4) == 8"); | |||||
| static_assert(sizeof(ivec4) == 16, "sizeof(ivec4) == 16"); | |||||
| static_assert(sizeof(i64vec4) == 32, "sizeof(i64vec4) == 32"); | |||||
| static_assert(sizeof(vec4) == 16, "sizeof(vec4) == 16"); | |||||
| static_assert(sizeof(dvec4) == 32, "sizeof(dvec4) == 32"); | |||||
| /* | /* | ||||
| * stdstream method implementation | * stdstream method implementation | ||||
| */ | */ | ||||
| @@ -1013,7 +997,6 @@ operator *(T const &val, vec_t<T,N,SWIZZLE> const &a) | |||||
| inline vec_t<T,N> fun(vec_t<T,N,SWIZZLE1> const &a, \ | inline vec_t<T,N> fun(vec_t<T,N,SWIZZLE1> const &a, \ | ||||
| vec_t<T,N,SWIZZLE2> const &b) \ | vec_t<T,N,SWIZZLE2> const &b) \ | ||||
| { \ | { \ | ||||
| using lol::fun; \ | |||||
| vec_t<T,N> ret; \ | vec_t<T,N> ret; \ | ||||
| for (int i = 0; i < N; ++i) \ | for (int i = 0; i < N; ++i) \ | ||||
| ret[i] = fun(a[i], b[i]); \ | ret[i] = fun(a[i], b[i]); \ | ||||
| @@ -1023,7 +1006,6 @@ operator *(T const &val, vec_t<T,N,SWIZZLE> const &a) | |||||
| template<typename T, int N, int SWIZZLE> \ | template<typename T, int N, int SWIZZLE> \ | ||||
| inline vec_t<T,N> fun(vec_t<T,N,SWIZZLE> const &a, T const &b) \ | inline vec_t<T,N> fun(vec_t<T,N,SWIZZLE> const &a, T const &b) \ | ||||
| { \ | { \ | ||||
| using lol::fun; \ | |||||
| vec_t<T,N> ret; \ | vec_t<T,N> ret; \ | ||||
| for (int i = 0; i < N; ++i) \ | for (int i = 0; i < N; ++i) \ | ||||
| ret[i] = fun(a[i], b); \ | ret[i] = fun(a[i], b); \ | ||||
| @@ -1033,7 +1015,6 @@ operator *(T const &val, vec_t<T,N,SWIZZLE> const &a) | |||||
| template<typename T, int N, int SWIZZLE> \ | template<typename T, int N, int SWIZZLE> \ | ||||
| inline vec_t<T,N> fun(T const &a, vec_t<T,N,SWIZZLE> const &b) \ | inline vec_t<T,N> fun(T const &a, vec_t<T,N,SWIZZLE> const &b) \ | ||||
| { \ | { \ | ||||
| using lol::fun; \ | |||||
| vec_t<T,N> ret; \ | vec_t<T,N> ret; \ | ||||
| for (int i = 0; i < N; ++i) \ | for (int i = 0; i < N; ++i) \ | ||||
| ret[i] = fun(a, b[i]); \ | ret[i] = fun(a, b[i]); \ | ||||
| @@ -1129,8 +1110,9 @@ static inline T sqlength(vec_t<T,N,SWIZZLE> const &a) | |||||
| template<typename T, int N, int SWIZZLE> [[nodiscard]] | template<typename T, int N, int SWIZZLE> [[nodiscard]] | ||||
| static inline T length(vec_t<T,N,SWIZZLE> const &a) | static inline T length(vec_t<T,N,SWIZZLE> const &a) | ||||
| { | { | ||||
| using std::sqrt; | |||||
| /* FIXME: this is not very nice */ | /* FIXME: this is not very nice */ | ||||
| return T(sqrt((double)sqlength(a))); | |||||
| return T(sqrt(sqlength(a))); | |||||
| } | } | ||||
| template<typename T, int N, int SWIZZLE1, int SWIZZLE2> | template<typename T, int N, int SWIZZLE1, int SWIZZLE2> | ||||
| @@ -1181,7 +1163,7 @@ static inline vec_t<T,N> abs(vec_t<T,N,SWIZZLE> const &a) | |||||
| { | { | ||||
| vec_t<T,N> ret; | vec_t<T,N> ret; | ||||
| for (int i = 0; i < N; ++i) | for (int i = 0; i < N; ++i) | ||||
| ret[i] = lol::abs(a[i]); | |||||
| ret[i] = abs(a[i]); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -1190,7 +1172,7 @@ static inline vec_t<T,N> degrees(vec_t<T,N,SWIZZLE> const &a) | |||||
| { | { | ||||
| vec_t<T,N> ret; | vec_t<T,N> ret; | ||||
| for (int i = 0; i < N; ++i) | for (int i = 0; i < N; ++i) | ||||
| ret[i] = lol::degrees(a[i]); | |||||
| ret[i] = degrees(a[i]); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -1199,7 +1181,7 @@ static inline vec_t<T, N> radians(vec_t<T, N, SWIZZLE> const &a) | |||||
| { | { | ||||
| vec_t<T, N> ret; | vec_t<T, N> ret; | ||||
| for (int i = 0; i < N; ++i) | for (int i = 0; i < N; ++i) | ||||
| ret[i] = lol::radians(a[i]); | |||||
| ret[i] = radians(a[i]); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -1207,19 +1189,23 @@ static inline vec_t<T, N> radians(vec_t<T, N, SWIZZLE> const &a) | |||||
| template<typename T, int SWIZZLE> | template<typename T, int SWIZZLE> | ||||
| static inline vec_t<T, 2> cartesian(vec_t<T, 2, SWIZZLE> const &a) | static inline vec_t<T, 2> cartesian(vec_t<T, 2, SWIZZLE> const &a) | ||||
| { | { | ||||
| using std::sin, std::cos; | |||||
| vec_t<T, 2> ret; | vec_t<T, 2> ret; | ||||
| ret.x = a[0] * lol::cos(a[1]); | |||||
| ret.y = a[0] * lol::sin(a[1]); | |||||
| ret.x = a[0] * cos(a[1]); | |||||
| ret.y = a[0] * sin(a[1]); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| template<typename T, int SWIZZLE> | template<typename T, int SWIZZLE> | ||||
| static inline vec_t<T, 3> cartesian(vec_t<T, 3, SWIZZLE> const &a) | static inline vec_t<T, 3> cartesian(vec_t<T, 3, SWIZZLE> const &a) | ||||
| { | { | ||||
| using std::sin, std::cos; | |||||
| vec_t<T, 3> ret; | vec_t<T, 3> ret; | ||||
| ret.x = a[0] * lol::sin(a[2]) * lol::cos(a[1]); | |||||
| ret.y = a[0] * lol::cos(a[2]); | |||||
| ret.z = a[0] * lol::sin(a[2]) * lol::sin(a[1]); | |||||
| ret.x = a[0] * sin(a[2]) * cos(a[1]); | |||||
| ret.y = a[0] * cos(a[2]); | |||||
| ret.z = a[0] * sin(a[2]) * sin(a[1]); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -1229,17 +1215,19 @@ static inline vec_t<T, 2> spherical(vec_t<T, 2, SWIZZLE> const &a) | |||||
| { | { | ||||
| vec_t<T, 2> ret; | vec_t<T, 2> ret; | ||||
| ret[0] = sqlength(a); | ret[0] = sqlength(a); | ||||
| ret[1] = lol::atan2(a.y, a.x); | |||||
| ret[1] = atan2(a.y, a.x); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| template<typename T, int SWIZZLE> | template<typename T, int SWIZZLE> | ||||
| static inline vec_t<T, 3> spherical(vec_t<T, 3, SWIZZLE> const &a) | static inline vec_t<T, 3> spherical(vec_t<T, 3, SWIZZLE> const &a) | ||||
| { | { | ||||
| using std::atan, std::acos; | |||||
| vec_t<T, 3> ret; | vec_t<T, 3> ret; | ||||
| ret[0] = sqlength(a); | ret[0] = sqlength(a); | ||||
| ret[1] = lol::atan(a.y / a.x); | |||||
| ret[2] = lol::acos(a.z / ret[0]); | |||||
| ret[1] = atan(a.y / a.x); | |||||
| ret[2] = acos(a.z / ret[0]); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -1334,7 +1322,100 @@ vec_t<T,4> const vec_t<T,4>::axis_z = vec_t<T,4>(T(0), T(0), T(1), T(0)); | |||||
| template<typename T> | template<typename T> | ||||
| vec_t<T,4> const vec_t<T,4>::axis_w = vec_t<T,4>(T(0), T(0), T(0), T(1)); | vec_t<T,4> const vec_t<T,4>::axis_w = vec_t<T,4>(T(0), T(0), T(0), T(1)); | ||||
| } /* namespace lol */ | |||||
| // | |||||
| // Generic GLSL-like type names | |||||
| // | |||||
| #define T_(tleft, tright, suffix) \ | |||||
| typedef tleft half tright f16##suffix; \ | |||||
| typedef tleft float tright suffix; \ | |||||
| typedef tleft double tright d##suffix; \ | |||||
| typedef tleft ldouble tright f128##suffix; \ | |||||
| typedef tleft int8_t tright i8##suffix; \ | |||||
| typedef tleft uint8_t tright u8##suffix; \ | |||||
| typedef tleft int16_t tright i16##suffix; \ | |||||
| typedef tleft uint16_t tright u16##suffix; \ | |||||
| typedef tleft int32_t tright i##suffix; \ | |||||
| typedef tleft uint32_t tright u##suffix; \ | |||||
| typedef tleft int64_t tright i64##suffix; \ | |||||
| typedef tleft uint64_t tright u64##suffix; \ | |||||
| typedef tleft real tright r##suffix; | |||||
| // Idiotic hack to put "," inside a macro argument | |||||
| #define C_ , | |||||
| T_(vec_t<, C_ 2>, vec2) | |||||
| T_(vec_t<, C_ 3>, vec3) | |||||
| T_(vec_t<, C_ 4>, vec4) | |||||
| T_(vec_t<, C_ 5>, vec5) | |||||
| T_(vec_t<, C_ 6>, vec6) | |||||
| T_(vec_t<, C_ 7>, vec7) | |||||
| T_(vec_t<, C_ 8>, vec8) | |||||
| T_(vec_t<, C_ 9>, vec9) | |||||
| T_(vec_t<, C_ 10>, vec10) | |||||
| T_(vec_t<, C_ 11>, vec11) | |||||
| T_(vec_t<, C_ 12>, vec12) | |||||
| #undef C_ | |||||
| #undef T_ | |||||
| static_assert(sizeof(i8vec2) == 2, "sizeof(i8vec2) == 2"); | |||||
| static_assert(sizeof(i16vec2) == 4, "sizeof(i16vec2) == 4"); | |||||
| static_assert(sizeof(ivec2) == 8, "sizeof(ivec2) == 8"); | |||||
| static_assert(sizeof(i64vec2) == 16, "sizeof(i64vec2) == 16"); | |||||
| static_assert(sizeof(vec2) == 8, "sizeof(vec2) == 8"); | |||||
| static_assert(sizeof(dvec2) == 16, "sizeof(dvec2) == 16"); | |||||
| static_assert(sizeof(i8vec3) == 3, "sizeof(i8vec3) == 3"); | |||||
| static_assert(sizeof(i16vec3) == 6, "sizeof(i16vec3) == 6"); | |||||
| static_assert(sizeof(ivec3) == 12, "sizeof(ivec3) == 12"); | |||||
| static_assert(sizeof(i64vec3) == 24, "sizeof(i64vec3) == 24"); | |||||
| static_assert(sizeof(vec3) == 12, "sizeof(vec3) == 12"); | |||||
| static_assert(sizeof(dvec3) == 24, "sizeof(dvec3) == 24"); | |||||
| static_assert(sizeof(i8vec4) == 4, "sizeof(i8vec4) == 4"); | |||||
| static_assert(sizeof(i16vec4) == 8, "sizeof(i16vec4) == 8"); | |||||
| static_assert(sizeof(ivec4) == 16, "sizeof(ivec4) == 16"); | |||||
| static_assert(sizeof(i64vec4) == 32, "sizeof(i64vec4) == 32"); | |||||
| static_assert(sizeof(vec4) == 16, "sizeof(vec4) == 16"); | |||||
| static_assert(sizeof(dvec4) == 32, "sizeof(dvec4) == 32"); | |||||
| // | |||||
| // HLSL/Cg-compliant type names | |||||
| // | |||||
| typedef vec2 float2; | |||||
| typedef vec3 float3; | |||||
| typedef vec4 float4; | |||||
| typedef vec5 float5; | |||||
| typedef vec6 float6; | |||||
| typedef vec7 float7; | |||||
| typedef vec8 float8; | |||||
| typedef vec9 float9; | |||||
| typedef vec10 float10; | |||||
| typedef vec11 float11; | |||||
| typedef vec12 float12; | |||||
| typedef f16vec2 half2; | |||||
| typedef f16vec3 half3; | |||||
| typedef f16vec4 half4; | |||||
| typedef ivec2 int2; | |||||
| typedef ivec3 int3; | |||||
| typedef ivec4 int4; | |||||
| typedef ivec5 int5; | |||||
| typedef ivec6 int6; | |||||
| typedef ivec7 int7; | |||||
| typedef ivec8 int8; | |||||
| typedef ivec9 int9; | |||||
| typedef ivec10 int10; | |||||
| typedef ivec11 int11; | |||||
| typedef ivec12 int12; | |||||
| } // namespace lol | |||||
| #include "private/vector.ipp" | #include "private/vector.ipp" | ||||
| @@ -21,6 +21,9 @@ | |||||
| #include <ostream> // std::ostream | #include <ostream> // std::ostream | ||||
| #include <stdint.h> // uint32_t etc. | #include <stdint.h> // uint32_t etc. | ||||
| // FIXME: get rid of this | |||||
| #include <../legacy/lol/math/functions.h> | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -41,7 +44,7 @@ public: | |||||
| inline half() {} | inline half() {} | ||||
| explicit inline half(int f) : half(float(f)) {} | explicit inline half(int f) : half(float(f)) {} | ||||
| explicit inline half(double f) : half(float(f)) {} | explicit inline half(double f) : half(float(f)) {} | ||||
| explicit inline half(ldouble f) : half(float(f)) {} | |||||
| explicit inline half(long double f) : half(float(f)) {} | |||||
| explicit inline half(float f) | explicit inline half(float f) | ||||
| { | { | ||||
| @@ -115,7 +118,7 @@ public: | |||||
| inline half &operator =(int f) { return *this = half(f); } | inline half &operator =(int f) { return *this = half(f); } | ||||
| inline half &operator =(float f) { return *this = half(f); } | inline half &operator =(float f) { return *this = half(f); } | ||||
| inline half &operator =(double f) { return *this = half(f); } | inline half &operator =(double f) { return *this = half(f); } | ||||
| inline half &operator =(ldouble f) { return *this = half(f); } | |||||
| inline half &operator =(long double f) { return *this = half(f); } | |||||
| [[nodiscard]] inline operator int8_t() const { return (int8_t)(float)*this; } | [[nodiscard]] inline operator int8_t() const { return (int8_t)(float)*this; } | ||||
| [[nodiscard]] inline operator uint8_t() const { return (uint8_t)(float)*this; } | [[nodiscard]] inline operator uint8_t() const { return (uint8_t)(float)*this; } | ||||
| [[nodiscard]] inline operator int16_t() const { return (int16_t)(float)*this; } | [[nodiscard]] inline operator int16_t() const { return (int16_t)(float)*this; } | ||||
| @@ -132,7 +135,7 @@ public: | |||||
| } | } | ||||
| [[nodiscard]] inline operator double() const { return (float)(*this); } | [[nodiscard]] inline operator double() const { return (float)(*this); } | ||||
| [[nodiscard]] inline operator ldouble() const { return (float)(*this); } | |||||
| [[nodiscard]] inline operator long double() const { return (float)(*this); } | |||||
| // Operators | // Operators | ||||
| [[nodiscard]] bool operator ==(half x) const { return (float)*this == (float)x; } | [[nodiscard]] bool operator ==(half x) const { return (float)*this == (float)x; } | ||||
| @@ -277,8 +280,8 @@ namespace half_ops | |||||
| { typedef float from; typedef TO to; }; | { typedef float from; typedef TO to; }; | ||||
| template<typename TO> struct valid<double, TO> | template<typename TO> struct valid<double, TO> | ||||
| { typedef double from; typedef TO to; }; | { typedef double from; typedef TO to; }; | ||||
| template<typename TO> struct valid<ldouble, TO> | |||||
| { typedef ldouble from; typedef TO to; }; | |||||
| template<typename TO> struct valid<long double, TO> | |||||
| { typedef long double from; typedef TO to; }; | |||||
| #define DECLARE_HALF_NUMERIC_OPS(op) \ | #define DECLARE_HALF_NUMERIC_OPS(op) \ | ||||
| /* other + half */ \ | /* other + half */ \ | ||||
| @@ -25,133 +25,5 @@ typedef real_t<uint32_t> real; | |||||
| class half; | class half; | ||||
| /* | |||||
| * Forward declaration of vec_t, mat_t, cmplx_t, quat_t, etc. | |||||
| */ | |||||
| /* HACK: if this is declared int const, Visual Studio becomes unable | |||||
| * to perform template argument deduction. */ | |||||
| #define FULL_SWIZZLE (0) | |||||
| template<typename T, int N, int SWIZZLE = FULL_SWIZZLE> struct vec_t; | |||||
| template<typename T, int N> struct box_t; | |||||
| template<typename T, int COLS, int ROWS> struct mat_t; | |||||
| template<typename T> struct cmplx_t; | |||||
| template<typename T> struct quat_t; | |||||
| template<typename T> struct dualquat_t; | |||||
| template<typename T> struct sqt_t; | |||||
| /* | |||||
| * Generic GLSL-like type names | |||||
| */ | |||||
| #define T_(tleft, tright, suffix) \ | |||||
| typedef tleft half tright f16##suffix; \ | |||||
| typedef tleft float tright suffix; \ | |||||
| typedef tleft double tright d##suffix; \ | |||||
| typedef tleft ldouble tright f128##suffix; \ | |||||
| typedef tleft int8_t tright i8##suffix; \ | |||||
| typedef tleft uint8_t tright u8##suffix; \ | |||||
| typedef tleft int16_t tright i16##suffix; \ | |||||
| typedef tleft uint16_t tright u16##suffix; \ | |||||
| typedef tleft int32_t tright i##suffix; \ | |||||
| typedef tleft uint32_t tright u##suffix; \ | |||||
| typedef tleft int64_t tright i64##suffix; \ | |||||
| typedef tleft uint64_t tright u64##suffix; \ | |||||
| typedef tleft real tright r##suffix; | |||||
| /* Idiotic hack to put "," inside a macro argument */ | |||||
| #define C_ , | |||||
| T_(vec_t<, C_ 2>, vec2) | |||||
| T_(vec_t<, C_ 3>, vec3) | |||||
| T_(vec_t<, C_ 4>, vec4) | |||||
| T_(vec_t<, C_ 5>, vec5) | |||||
| T_(vec_t<, C_ 6>, vec6) | |||||
| T_(vec_t<, C_ 7>, vec7) | |||||
| T_(vec_t<, C_ 8>, vec8) | |||||
| T_(vec_t<, C_ 9>, vec9) | |||||
| T_(vec_t<, C_ 10>, vec10) | |||||
| T_(vec_t<, C_ 11>, vec11) | |||||
| T_(vec_t<, C_ 12>, vec12) | |||||
| T_(mat_t<, C_ 2 C_ 2>, mat2) | |||||
| T_(mat_t<, C_ 3 C_ 3>, mat3) | |||||
| T_(mat_t<, C_ 4 C_ 4>, mat4) | |||||
| T_(mat_t<, C_ 2 C_ 3>, mat2x3) | |||||
| T_(mat_t<, C_ 2 C_ 4>, mat2x4) | |||||
| T_(mat_t<, C_ 3 C_ 2>, mat3x2) | |||||
| T_(mat_t<, C_ 3 C_ 4>, mat3x4) | |||||
| T_(mat_t<, C_ 4 C_ 2>, mat4x2) | |||||
| T_(mat_t<, C_ 4 C_ 3>, mat4x3) | |||||
| T_(cmplx_t<, >, cmplx) | |||||
| T_(quat_t<, >, quat) | |||||
| T_(dualquat_t<, >, dualquat) | |||||
| T_(sqt_t<, >, sqt) | |||||
| #undef C_ | |||||
| #undef T_ | |||||
| /* | |||||
| * HLSL/Cg-compliant type names | |||||
| */ | |||||
| typedef vec2 float2; | |||||
| typedef vec3 float3; | |||||
| typedef vec4 float4; | |||||
| typedef vec5 float5; | |||||
| typedef vec6 float6; | |||||
| typedef vec7 float7; | |||||
| typedef vec8 float8; | |||||
| typedef vec9 float9; | |||||
| typedef vec10 float10; | |||||
| typedef vec11 float11; | |||||
| typedef vec12 float12; | |||||
| typedef mat2 float2x2; | |||||
| typedef mat3 float3x3; | |||||
| typedef mat4 float4x4; | |||||
| typedef mat2x3 float2x3; | |||||
| typedef mat2x4 float2x4; | |||||
| typedef mat3x2 float3x2; | |||||
| typedef mat3x4 float3x4; | |||||
| typedef mat4x2 float4x2; | |||||
| typedef mat4x3 float4x3; | |||||
| typedef f16vec2 half2; | |||||
| typedef f16vec3 half3; | |||||
| typedef f16vec4 half4; | |||||
| typedef f16mat2 half2x2; | |||||
| typedef f16mat3 half3x3; | |||||
| typedef f16mat4 half4x4; | |||||
| typedef f16mat2x3 half2x3; | |||||
| typedef f16mat2x4 half2x4; | |||||
| typedef f16mat3x2 half3x2; | |||||
| typedef f16mat3x4 half3x4; | |||||
| typedef f16mat4x2 half4x2; | |||||
| typedef f16mat4x3 half4x3; | |||||
| typedef ivec2 int2; | |||||
| typedef ivec3 int3; | |||||
| typedef ivec4 int4; | |||||
| typedef ivec5 int5; | |||||
| typedef ivec6 int6; | |||||
| typedef ivec7 int7; | |||||
| typedef ivec8 int8; | |||||
| typedef ivec9 int9; | |||||
| typedef ivec10 int10; | |||||
| typedef ivec11 int11; | |||||
| typedef ivec12 int12; | |||||
| typedef imat2 int2x2; | |||||
| typedef imat3 int3x3; | |||||
| typedef imat4 int4x4; | |||||
| typedef imat2x3 int2x3; | |||||
| typedef imat2x4 int2x4; | |||||
| typedef imat3x2 int3x2; | |||||
| typedef imat3x4 int3x4; | |||||
| typedef imat4x2 int4x2; | |||||
| typedef imat4x3 int4x3; | |||||
| } /* namespace lol */ | } /* namespace lol */ | ||||
| @@ -19,7 +19,9 @@ | |||||
| // | // | ||||
| #include <lol/base/enum.h> | #include <lol/base/enum.h> | ||||
| #include <lol/math/vector.h> // vec_t | |||||
| #include <lol/math/vector.h> // vec_t | |||||
| #include <lol/math/transform.h> // mat_t | |||||
| #include <../legacy/lol/math/functions.h> // distance, clamp… | |||||
| #include <algorithm> | #include <algorithm> | ||||
| #include <map> | #include <map> | ||||
| @@ -71,26 +73,6 @@ protected: | |||||
| }; | }; | ||||
| typedef SafeEnum<DirectionBase> Direction; | typedef SafeEnum<DirectionBase> Direction; | ||||
| /* | |||||
| * Generic box type names | |||||
| */ | |||||
| #define T_(tleft, tright, suffix) \ | |||||
| typedef tleft float tright suffix; \ | |||||
| typedef tleft double tright d##suffix; \ | |||||
| typedef tleft int32_t tright i##suffix; \ | |||||
| typedef tleft uint32_t tright u##suffix; | |||||
| /* Idiotic hack to put "," inside a macro argument */ | |||||
| #define C_ , | |||||
| T_(box_t<, C_ 2>, box2) | |||||
| T_(box_t<, C_ 3>, box3) | |||||
| T_(box_t<, C_ 4>, box4) | |||||
| #undef C_ | |||||
| #undef T_ | |||||
| template<typename T, int N> | template<typename T, int N> | ||||
| struct [[nodiscard]] box_t | struct [[nodiscard]] box_t | ||||
| { | { | ||||
| @@ -172,6 +154,26 @@ struct [[nodiscard]] box_t | |||||
| vec_t<T,N> aa, bb; | vec_t<T,N> aa, bb; | ||||
| }; | }; | ||||
| // | |||||
| // Generic box type names | |||||
| // | |||||
| #define T_(tleft, tright, suffix) \ | |||||
| typedef tleft float tright suffix; \ | |||||
| typedef tleft double tright d##suffix; \ | |||||
| typedef tleft int32_t tright i##suffix; \ | |||||
| typedef tleft uint32_t tright u##suffix; | |||||
| // Idiotic hack to put "," inside a macro argument | |||||
| #define C_ , | |||||
| T_(box_t<, C_ 2>, box2) | |||||
| T_(box_t<, C_ 3>, box3) | |||||
| T_(box_t<, C_ 4>, box4) | |||||
| #undef C_ | |||||
| #undef T_ | |||||
| static_assert(sizeof(box2) == 16, "sizeof(box2) == 16"); | static_assert(sizeof(box2) == 16, "sizeof(box2) == 16"); | ||||
| static_assert(sizeof(box3) == 24, "sizeof(box3) == 24"); | static_assert(sizeof(box3) == 24, "sizeof(box3) == 24"); | ||||
| static_assert(sizeof(dbox2) == 32, "sizeof(dbox2) == 32"); | static_assert(sizeof(dbox2) == 32, "sizeof(dbox2) == 32"); | ||||
| @@ -215,8 +217,8 @@ static inline bool TestAABBVsAABB(box2 const &b1, box2 const &b2) | |||||
| vec2 e1 = 0.5f * b1.extent(); | vec2 e1 = 0.5f * b1.extent(); | ||||
| vec2 e2 = 0.5f * b2.extent(); | vec2 e2 = 0.5f * b2.extent(); | ||||
| return abs(c.x) <= e1.x + e2.x | |||||
| && abs(c.y) <= e1.y + e2.y; | |||||
| return fabs(c.x) <= e1.x + e2.x | |||||
| && fabs(c.y) <= e1.y + e2.y; | |||||
| } | } | ||||
| static inline bool TestAABBVsPoint(box2 const &b1, vec2 const &p) | static inline bool TestAABBVsPoint(box2 const &b1, vec2 const &p) | ||||
| { | { | ||||
| @@ -229,9 +231,9 @@ static inline bool TestAABBVsAABB(box3 const &b1, box3 const &b2) | |||||
| vec3 e1 = 0.5f * b1.extent(); | vec3 e1 = 0.5f * b1.extent(); | ||||
| vec3 e2 = 0.5f * b2.extent(); | vec3 e2 = 0.5f * b2.extent(); | ||||
| return abs(c.x) <= e1.x + e2.x | |||||
| && abs(c.y) <= e1.y + e2.y | |||||
| && abs(c.z) <= e1.z + e2.z; | |||||
| return fabs(c.x) <= e1.x + e2.x | |||||
| && fabs(c.y) <= e1.y + e2.y | |||||
| && fabs(c.z) <= e1.z + e2.z; | |||||
| } | } | ||||
| static inline bool TestAABBVsPoint(box3 const &b1, vec3 const &p) | static inline bool TestAABBVsPoint(box3 const &b1, vec3 const &p) | ||||
| { | { | ||||
| @@ -14,7 +14,11 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <functional> | |||||
| #include <lol/math/vector.h> // vec_t | |||||
| #include <lol/math/rand.h> // rand() | |||||
| #include <vector> // std::vector | |||||
| #include <algorithm> // std::min | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -58,22 +62,22 @@ protected: | |||||
| /* Generate 2^(N+2) random vectors, but at least 2^5 (32) and not | /* Generate 2^(N+2) random vectors, but at least 2^5 (32) and not | ||||
| * more than 2^20 (~ 1 million). */ | * more than 2^20 (~ 1 million). */ | ||||
| int const gradient_count = 1 << min(max(N + 2, 5), 20); | |||||
| int constexpr gradient_count = 1 << std::min(std::max(N + 2, 5), 20); | |||||
| static auto build_gradients = [&]() | static auto build_gradients = [&]() | ||||
| { | { | ||||
| array<vec_t<float, N>> ret; | |||||
| std::array<vec_t<float, N>, gradient_count> ret; | |||||
| for (int k = 0; k < gradient_count; ++k) | for (int k = 0; k < gradient_count; ++k) | ||||
| { | { | ||||
| vec_t<float, N> v; | vec_t<float, N> v; | ||||
| for (int i = 0; i < N; ++i) | for (int i = 0; i < N; ++i) | ||||
| v[i] = rand(-1.f, 1.f); | v[i] = rand(-1.f, 1.f); | ||||
| ret << normalize(v); | |||||
| ret[k] = normalize(v); | |||||
| } | } | ||||
| return ret; | return ret; | ||||
| }; | }; | ||||
| static array<vec_t<float, N>> const gradients = build_gradients(); | |||||
| static auto const gradients = build_gradients(); | |||||
| int idx = m_seed; | int idx = m_seed; | ||||
| for (int i = 0; i < N; ++i) | for (int i = 0; i < N; ++i) | ||||
| @@ -1,7 +1,7 @@ | |||||
| // | // | ||||
| // Lol Engine | // Lol Engine | ||||
| // | // | ||||
| // Copyright © 2010—2014 Sam Hocevar <sam@hocevar.net> | |||||
| // Copyright © 2010—2020 Sam Hocevar <sam@hocevar.net> | |||||
| // © 2013—2014 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | // © 2013—2014 Benjamin “Touky” Huet <huet.benjamin@gmail.com> | ||||
| // © 2013—2014 Guillaume Bittoun <guillaume.bittoun@gmail.com> | // © 2013—2014 Guillaume Bittoun <guillaume.bittoun@gmail.com> | ||||
| // | // | ||||
| @@ -15,6 +15,11 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <../legacy/lol/math/noise/gradient.h> | #include <../legacy/lol/math/noise/gradient.h> | ||||
| #include <lol/math/vector.h> // vec_t | |||||
| #include <lol/math/transform.h> // mat_t | |||||
| #include <vector> // std::vector | |||||
| #include <algorithm> // std::min, std::max | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -106,7 +111,6 @@ protected: | |||||
| * coordinates. */ | * coordinates. */ | ||||
| vec_t<float, N> world_corner(0.f); | vec_t<float, N> world_corner(0.f); | ||||
| float result = 0.f, sum = 0.f, special = 0.f; | float result = 0.f, sum = 0.f, special = 0.f; | ||||
| UNUSED(sum, special); | |||||
| for (int i = 0; i < N + 1; ++i) | for (int i = 0; i < N + 1; ++i) | ||||
| { | { | ||||
| @@ -137,9 +141,9 @@ protected: | |||||
| // -4.f: centre (-2.f), | // -4.f: centre (-2.f), | ||||
| // -3.f: r=0.38 sphere of influence (contribution = 1/4) | // -3.f: r=0.38 sphere of influence (contribution = 1/4) | ||||
| // -2.f: r=0.52 sphere of influence (contribution = 1/24) | // -2.f: r=0.52 sphere of influence (contribution = 1/24) | ||||
| if (d > 0.99f) special = min(special, -4.f); | |||||
| if (d > 0.7f && d < 0.72f) special = min(special, -3.f); | |||||
| if (d > 0.44f && d < 0.46f) special = min(special, -2.f); | |||||
| if (d > 0.99f) special = std::min(special, -4.f); | |||||
| if (d > 0.7f && d < 0.72f) special = std::min(special, -3.f); | |||||
| if (d > 0.44f && d < 0.46f) special = std::min(special, -2.f); | |||||
| #endif | #endif | ||||
| if (d > 0) | if (d > 0) | ||||
| @@ -168,6 +172,8 @@ protected: | |||||
| #if 0 | #if 0 | ||||
| if (special < 0.f) | if (special < 0.f) | ||||
| return special; | return special; | ||||
| #else | |||||
| (void)special; | |||||
| #endif | #endif | ||||
| return get_scale() * result; | return get_scale() * result; | ||||
| @@ -275,8 +281,8 @@ private: | |||||
| continue; | continue; | ||||
| float l = length(vertices[i] - vertices[j]); | float l = length(vertices[i] - vertices[j]); | ||||
| minlength = min(minlength, l); | |||||
| maxlength = max(maxlength, l); | |||||
| minlength = std::min(minlength, l); | |||||
| maxlength = std::max(maxlength, l); | |||||
| } | } | ||||
| printf(" · edge lengths between %f and %f\n", | printf(" · edge lengths between %f and %f\n", | ||||
| minlength, maxlength); | minlength, maxlength); | ||||
| @@ -300,7 +306,7 @@ private: | |||||
| p += k * vertices[j]; | p += k * vertices[j]; | ||||
| sum += k; | sum += k; | ||||
| } | } | ||||
| mindist = min(mindist, distance(vertices[i], p / sum)); | |||||
| mindist = std::min(mindist, distance(vertices[i], p / sum)); | |||||
| } | } | ||||
| printf(" · approx. dist. to opposite hyperplane: %f\n", mindist); | printf(" · approx. dist. to opposite hyperplane: %f\n", mindist); | ||||
| #endif | #endif | ||||
| @@ -327,7 +333,7 @@ private: | |||||
| /* Find distance from current vertex to the opposite hyperplane. | /* Find distance from current vertex to the opposite hyperplane. | ||||
| * Just use the projection theorem in N dimensions. */ | * Just use the projection theorem in N dimensions. */ | ||||
| auto w = vertices[i] - vertices[i0]; | auto w = vertices[i] - vertices[i0]; | ||||
| float dist = abs(dot(normal, w)); | |||||
| float dist = fabs(dot(normal, w)); | |||||
| printf(" · distance to opposite hyperplane: %f\n", dist); | printf(" · distance to opposite hyperplane: %f\n", dist); | ||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -345,11 +351,12 @@ private: | |||||
| /* Try to find max noise value by climbing gradient */ | /* Try to find max noise value by climbing gradient */ | ||||
| float minval = 0.f, maxval = 0.f; | float minval = 0.f, maxval = 0.f; | ||||
| array<vec_t<float, N>> deltas; | |||||
| std::vector<vec_t<float, N>> deltas; | |||||
| for (int i = 0; i < N; ++i) | for (int i = 0; i < N; ++i) | ||||
| { | { | ||||
| auto v = vec_t<float, N>::axis(i); | auto v = vec_t<float, N>::axis(i); | ||||
| deltas << v << -v; | |||||
| deltas.push_back(v); | |||||
| deltas.push_back(-v); | |||||
| } | } | ||||
| for (int run = 0; run < 1000; ++run) | for (int run = 0; run < 1000; ++run) | ||||
| { | { | ||||
| @@ -364,10 +371,10 @@ private: | |||||
| { | { | ||||
| int best_delta = -1; | int best_delta = -1; | ||||
| float best_t2 = t; | float best_t2 = t; | ||||
| for (int i = 0; i < deltas.count(); ++i) | |||||
| for (int i = 0; i < (int)deltas.size(); ++i) | |||||
| { | { | ||||
| float t2 = eval(v + e * deltas[i]); | float t2 = eval(v + e * deltas[i]); | ||||
| if (abs(t2) > abs(best_t2)) | |||||
| if (fabs(t2) > fabs(best_t2)) | |||||
| { | { | ||||
| best_delta = i; | best_delta = i; | ||||
| best_t2 = t2; | best_t2 = t2; | ||||
| @@ -381,11 +388,11 @@ private: | |||||
| t = best_t2; | t = best_t2; | ||||
| } | } | ||||
| } | } | ||||
| minval = min(t, minval); | |||||
| maxval = max(t, maxval); | |||||
| minval = std::min(t, minval); | |||||
| maxval = std::max(t, maxval); | |||||
| } | } | ||||
| printf(" - noise value min/max: %f %f\n", minval, maxval); | printf(" - noise value min/max: %f %f\n", minval, maxval); | ||||
| float newscale = 1.f / max(-minval, maxval); | |||||
| float newscale = 1.f / std::max(-minval, maxval); | |||||
| if (newscale < 1.f) | if (newscale < 1.f) | ||||
| printf(" - could replace scale %f with %f\n", | printf(" - could replace scale %f with %f\n", | ||||
| get_scale(), newscale * get_scale()); | get_scale(), newscale * get_scale()); | ||||