From d05eb966657babec841907e9fa0e618643ca115f Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Tue, 3 Mar 2020 07:41:13 +0100 Subject: [PATCH] Improve standalone inclusion support. --- include/lol/base/lolunit.h | 9 +- include/lol/image/color.h | 4 +- include/lol/math/polynomial.h | 8 +- include/lol/math/private/matrix.h | 18 +-- include/lol/math/private/matrix.ipp | 15 ++- include/lol/math/private/ops.h | 7 + include/lol/math/private/transform.ipp | 46 ++++--- include/lol/math/private/vector.ipp | 2 + include/lol/math/transform.h | 117 +++++++++++++++-- include/lol/math/vector.h | 169 ++++++++++++++++++------- include/lol/types/half.h | 13 +- legacy/lol/base/types.h | 128 ------------------- legacy/lol/math/geometry.h | 54 ++++---- legacy/lol/math/noise/gradient.h | 14 +- legacy/lol/math/noise/simplex.h | 39 +++--- 15 files changed, 363 insertions(+), 280 deletions(-) diff --git a/include/lol/base/lolunit.h b/include/lol/base/lolunit.h index d44865f5..e4e9ab6b 100644 --- a/include/lol/base/lolunit.h +++ b/include/lol/base/lolunit.h @@ -17,10 +17,11 @@ // ——————————————————————— // -#include -#include -#include -#include +#include // std::cout +#include // std::setprecision +#include // std::stringstream +#include // std::string +#include // std::fabs namespace lol { diff --git a/include/lol/image/color.h b/include/lol/image/color.h index 4e18203f..54d52486 100644 --- a/include/lol/image/color.h +++ b/include/lol/image/color.h @@ -18,7 +18,9 @@ // Provides various color conversion routines. // -#include +#include <../legacy/lol/math/functions.h> // FIXME: try to remove this +#include // vec_t +#include // mat_t namespace lol { diff --git a/include/lol/math/polynomial.h b/include/lol/math/polynomial.h index 77eb6512..8f87ff2b 100644 --- a/include/lol/math/polynomial.h +++ b/include/lol/math/polynomial.h @@ -25,6 +25,7 @@ #include // std::function #include // std::tuple #include // assert() +#include // sqrt(), cbrt(), acos() namespace lol { @@ -114,6 +115,9 @@ struct [[nodiscard]] polynomial std::vector 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. */ assert(degree() >= 0 && degree() <= 3); @@ -212,8 +216,8 @@ struct [[nodiscard]] polynomial { 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; v3_angle = (n <= -sqrt_delta) ? 0 : -pi; diff --git a/include/lol/math/private/matrix.h b/include/lol/math/private/matrix.h index 9b174ff7..ca0b9bfa 100644 --- a/include/lol/math/private/matrix.h +++ b/include/lol/math/private/matrix.h @@ -117,10 +117,6 @@ private: vec_t 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 */ @@ -207,10 +203,6 @@ private: vec_t 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 */ @@ -340,10 +332,6 @@ private: vec_t 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 */ @@ -383,8 +371,6 @@ static inline mat_t transpose(mat_t const &m) template mat_t submatrix(mat_t const &m, int i, int j) { - ASSERT(i >= 0); ASSERT(j >= 0); ASSERT(i < N); ASSERT(j < N); - mat_t ret; for (int i2 = 0; i2 < N - 1; ++i2) for (int j2 = 0; j2 < N - 1; ++j2) @@ -400,7 +386,6 @@ mat_t submatrix(mat_t const &m, int i, int j) template [[nodiscard]] T cofactor(mat_t 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)); return ((i + j) & 1) ? -tmp : tmp; } @@ -409,7 +394,6 @@ template [[nodiscard]] T cofactor(mat_t const &m, int i, int j) { /* 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]; return (i ^ j) ? -tmp : tmp; } @@ -430,7 +414,7 @@ std::tuple, vec_t, int> lu_decomposition(mat_t c // Find row with the largest absolute value int best_j = k; 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; // Swap rows in result diff --git a/include/lol/math/private/matrix.ipp b/include/lol/math/private/matrix.ipp index 56ac4541..bf67d9e5 100644 --- a/include/lol/math/private/matrix.ipp +++ b/include/lol/math/private/matrix.ipp @@ -13,7 +13,8 @@ #pragma once #include -#include +#include // std::tan +#include // std::max #if _WIN32 # pragma push_macro("near") @@ -256,7 +257,9 @@ template<> inline mat4 mat4::perspective(float fov_y, float width, 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; 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 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); float dist_scr = (screen_size * screen_ratio_yx * .5f) / tan_y; 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); } diff --git a/include/lol/math/private/ops.h b/include/lol/math/private/ops.h index edafb5b4..6e16b5a0 100644 --- a/include/lol/math/private/ops.h +++ b/include/lol/math/private/ops.h @@ -20,9 +20,16 @@ #include #include +// 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 { +template struct vec_t; + /* * Utility namespaces for traits -- this file uses a combination of * ADL black magic and enable_if to ensure that only the expected type diff --git a/include/lol/math/private/transform.ipp b/include/lol/math/private/transform.ipp index b5677558..800470f6 100644 --- a/include/lol/math/private/transform.ipp +++ b/include/lol/math/private/transform.ipp @@ -12,6 +12,8 @@ #pragma once +#include // std::cos, std::sin + namespace lol { @@ -31,10 +33,10 @@ inline std::string quat::tostring() const template<> 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); - 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<> inline quat quat::rotate(vec3 const &src, vec3 const &dst) { + using std::sqrt; + /* Algorithm directly taken from Sam Hocevar's article "Quaternion from * two vectors: the final version". * 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); vec3 w; @@ -60,8 +64,7 @@ inline quat quat::rotate(vec3 const &src, vec3 const &dst) * around an arbitrary orthogonal axis. Axis normalisation * can happen later, when we normalise the quaternion. */ 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 { @@ -75,8 +78,10 @@ inline quat quat::rotate(vec3 const &src, vec3 const &dst) template<> 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 * to slerp anything, just return qa. */ @@ -84,18 +89,25 @@ inline quat slerp(quat const &qa, quat const &qb, float f) return qa; 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) */ - 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); } +static inline float sq(float x) +{ + return x * x; +} + 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); 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) { + using std::sin, std::cos; + mat3 ret; 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) { + using std::sin, std::cos; + vec3 const half_angles = v * 0.5f; float const s0 = sin(half_angles[0]), c0 = cos(half_angles[0]); 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 */ \ 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); \ } \ \ @@ -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 */ \ 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); \ } \ \ @@ -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 */ \ 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); \ } \ \ @@ -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 */ \ 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); \ } diff --git a/include/lol/math/private/vector.ipp b/include/lol/math/private/vector.ipp index ef94b152..348c20dc 100644 --- a/include/lol/math/private/vector.ipp +++ b/include/lol/math/private/vector.ipp @@ -12,6 +12,8 @@ #pragma once +#include // lol::format + namespace lol { diff --git a/include/lol/math/transform.h b/include/lol/math/transform.h index 4927a731..67a36f68 100644 --- a/include/lol/math/transform.h +++ b/include/lol/math/transform.h @@ -20,7 +20,8 @@ #include #include -#include +#include // std::ostream +#include // std::atan2, std::sqrt #include "private/matrix.h" @@ -71,9 +72,6 @@ struct [[nodiscard]] cmplx_t : public linear_ops::base T x, y; }; -static_assert(sizeof(cmplx) == 8, "sizeof(cmplx) == 8"); -static_assert(sizeof(dcmplx) == 16, "sizeof(dcmplx) == 16"); - /* * 4-element transforms: quaternions */ @@ -104,11 +102,13 @@ struct [[nodiscard]] quat_t : public linear_ops::base /* Construct a unit quaternion from a pure rotation matrix */ explicit quat_t(mat_t const &m) { + using std::sqrt; + T tr = m[0][0] + m[1][1] + m[2][2]; 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; w = p; @@ -123,7 +123,7 @@ struct [[nodiscard]] quat_t : public linear_ops::base : 2; 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; w = q * (m[j][k] - m[k][j]); @@ -235,11 +235,13 @@ struct [[nodiscard]] quat_t : public linear_ops::base [[nodiscard]] inline T angle() { + using std::atan2, std::sqrt; + vec_t v(x, y, z); T n2 = sqlength(v); if (n2 <= (T)1e-6) return (T)0; - return (T)2 * lol::atan2(lol::sqrt(n2), w); + return (T)2 * atan2(sqrt(n2), w); } template @@ -249,9 +251,6 @@ struct [[nodiscard]] quat_t : public linear_ops::base 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 */ @@ -359,6 +358,7 @@ static inline T sqlength(cmplx_t const &t) template [[nodiscard]] static inline T length(cmplx_t const &t) { + using std::sqrt; /* FIXME: this is not very nice */ return (T)sqrt((double)sqlength(t)); } @@ -396,8 +396,9 @@ static inline T sqlength(quat_t const &t) template [[nodiscard]] static inline T length(quat_t const &t) { + using std::sqrt; /* FIXME: this is not very nice */ - return (T)sqrt((double)sqlength(t)); + return (T)sqrt(sqlength(t)); } template [[nodiscard]] @@ -496,7 +497,99 @@ static inline sqt_t operator /(sqt_t const &x, sqt_t const &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/transform.ipp" diff --git a/include/lol/math/vector.h b/include/lol/math/vector.h index 5079bc51..8ca5a699 100644 --- a/include/lol/math/vector.h +++ b/include/lol/math/vector.h @@ -17,15 +17,21 @@ // —————————————————— // -#include - #include #include // std::ostream #include +#include // std::fabs, std::cos… + +// FIXME: get rid of this, too +#include <../legacy/lol/base/types.h> + +#include "private/ops.h" namespace lol { +template struct quat_t; + /* * Magic vector swizzling * @@ -188,7 +194,7 @@ private: static inline void internal_init(T *data) { - UNUSED(data); + (void)data; } T m_data[count]; @@ -296,14 +302,6 @@ struct [[nodiscard]] vec_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"); - /* * 3-element vectors */ @@ -388,7 +386,9 @@ struct [[nodiscard]] vec_t /* Return a vector that is orthogonal to “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(T(0), -a.z, a.y); } @@ -536,14 +536,6 @@ struct [[nodiscard]] vec_t }; }; -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 */ @@ -968,14 +960,6 @@ struct [[nodiscard]] vec_t }; }; -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 */ @@ -1013,7 +997,6 @@ operator *(T const &val, vec_t const &a) inline vec_t fun(vec_t const &a, \ vec_t const &b) \ { \ - using lol::fun; \ vec_t ret; \ for (int i = 0; i < N; ++i) \ ret[i] = fun(a[i], b[i]); \ @@ -1023,7 +1006,6 @@ operator *(T const &val, vec_t const &a) template \ inline vec_t fun(vec_t const &a, T const &b) \ { \ - using lol::fun; \ vec_t ret; \ for (int i = 0; i < N; ++i) \ ret[i] = fun(a[i], b); \ @@ -1033,7 +1015,6 @@ operator *(T const &val, vec_t const &a) template \ inline vec_t fun(T const &a, vec_t const &b) \ { \ - using lol::fun; \ vec_t ret; \ for (int i = 0; i < N; ++i) \ ret[i] = fun(a, b[i]); \ @@ -1129,8 +1110,9 @@ static inline T sqlength(vec_t const &a) template [[nodiscard]] static inline T length(vec_t const &a) { + using std::sqrt; /* FIXME: this is not very nice */ - return T(sqrt((double)sqlength(a))); + return T(sqrt(sqlength(a))); } template @@ -1181,7 +1163,7 @@ static inline vec_t abs(vec_t const &a) { vec_t ret; for (int i = 0; i < N; ++i) - ret[i] = lol::abs(a[i]); + ret[i] = abs(a[i]); return ret; } @@ -1190,7 +1172,7 @@ static inline vec_t degrees(vec_t const &a) { vec_t ret; for (int i = 0; i < N; ++i) - ret[i] = lol::degrees(a[i]); + ret[i] = degrees(a[i]); return ret; } @@ -1199,7 +1181,7 @@ static inline vec_t radians(vec_t const &a) { vec_t ret; for (int i = 0; i < N; ++i) - ret[i] = lol::radians(a[i]); + ret[i] = radians(a[i]); return ret; } @@ -1207,19 +1189,23 @@ static inline vec_t radians(vec_t const &a) template static inline vec_t cartesian(vec_t const &a) { + using std::sin, std::cos; + vec_t 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; } template static inline vec_t cartesian(vec_t const &a) { + using std::sin, std::cos; + vec_t 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; } @@ -1229,17 +1215,19 @@ static inline vec_t spherical(vec_t const &a) { vec_t ret; ret[0] = sqlength(a); - ret[1] = lol::atan2(a.y, a.x); + ret[1] = atan2(a.y, a.x); return ret; } template static inline vec_t spherical(vec_t const &a) { + using std::atan, std::acos; + vec_t ret; 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; } @@ -1334,7 +1322,100 @@ vec_t const vec_t::axis_z = vec_t(T(0), T(0), T(1), T(0)); template vec_t const vec_t::axis_w = vec_t(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" diff --git a/include/lol/types/half.h b/include/lol/types/half.h index ee5373d1..1ca1dc59 100644 --- a/include/lol/types/half.h +++ b/include/lol/types/half.h @@ -21,6 +21,9 @@ #include // std::ostream #include // uint32_t etc. +// FIXME: get rid of this +#include <../legacy/lol/math/functions.h> + namespace lol { @@ -41,7 +44,7 @@ public: inline half() {} explicit inline half(int 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) { @@ -115,7 +118,7 @@ public: inline half &operator =(int 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 =(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 uint8_t() const { return (uint8_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 ldouble() const { return (float)(*this); } + [[nodiscard]] inline operator long double() const { return (float)(*this); } // Operators [[nodiscard]] bool operator ==(half x) const { return (float)*this == (float)x; } @@ -277,8 +280,8 @@ namespace half_ops { typedef float from; typedef TO to; }; template struct valid { typedef double from; typedef TO to; }; - template struct valid - { typedef ldouble from; typedef TO to; }; + template struct valid + { typedef long double from; typedef TO to; }; #define DECLARE_HALF_NUMERIC_OPS(op) \ /* other + half */ \ diff --git a/legacy/lol/base/types.h b/legacy/lol/base/types.h index a90e793f..fe947e98 100644 --- a/legacy/lol/base/types.h +++ b/legacy/lol/base/types.h @@ -25,133 +25,5 @@ typedef real_t real; 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 struct vec_t; -template struct box_t; -template struct mat_t; -template struct cmplx_t; -template struct quat_t; -template struct dualquat_t; -template 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 */ diff --git a/legacy/lol/math/geometry.h b/legacy/lol/math/geometry.h index b18a37b4..94641443 100644 --- a/legacy/lol/math/geometry.h +++ b/legacy/lol/math/geometry.h @@ -19,7 +19,9 @@ // #include -#include // vec_t +#include // vec_t +#include // mat_t +#include <../legacy/lol/math/functions.h> // distance, clamp… #include #include @@ -71,26 +73,6 @@ protected: }; typedef SafeEnum 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 struct [[nodiscard]] box_t { @@ -172,6 +154,26 @@ struct [[nodiscard]] box_t vec_t 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(box3) == 24, "sizeof(box3) == 24"); 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 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) { @@ -229,9 +231,9 @@ static inline bool TestAABBVsAABB(box3 const &b1, box3 const &b2) vec3 e1 = 0.5f * b1.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) { diff --git a/legacy/lol/math/noise/gradient.h b/legacy/lol/math/noise/gradient.h index 15788d6d..efa7556a 100644 --- a/legacy/lol/math/noise/gradient.h +++ b/legacy/lol/math/noise/gradient.h @@ -14,7 +14,11 @@ #pragma once -#include +#include // vec_t +#include // rand() + +#include // std::vector +#include // std::min namespace lol { @@ -58,22 +62,22 @@ protected: /* Generate 2^(N+2) random vectors, but at least 2^5 (32) and not * 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 = [&]() { - array> ret; + std::array, gradient_count> ret; for (int k = 0; k < gradient_count; ++k) { vec_t v; for (int i = 0; i < N; ++i) v[i] = rand(-1.f, 1.f); - ret << normalize(v); + ret[k] = normalize(v); } return ret; }; - static array> const gradients = build_gradients(); + static auto const gradients = build_gradients(); int idx = m_seed; for (int i = 0; i < N; ++i) diff --git a/legacy/lol/math/noise/simplex.h b/legacy/lol/math/noise/simplex.h index 54ba3b72..b234b9c7 100644 --- a/legacy/lol/math/noise/simplex.h +++ b/legacy/lol/math/noise/simplex.h @@ -1,7 +1,7 @@ // // Lol Engine // -// Copyright © 2010—2014 Sam Hocevar +// Copyright © 2010—2020 Sam Hocevar // © 2013—2014 Benjamin “Touky” Huet // © 2013—2014 Guillaume Bittoun // @@ -15,6 +15,11 @@ #pragma once #include <../legacy/lol/math/noise/gradient.h> +#include // vec_t +#include // mat_t + +#include // std::vector +#include // std::min, std::max namespace lol { @@ -106,7 +111,6 @@ protected: * coordinates. */ vec_t world_corner(0.f); float result = 0.f, sum = 0.f, special = 0.f; - UNUSED(sum, special); for (int i = 0; i < N + 1; ++i) { @@ -137,9 +141,9 @@ protected: // -4.f: centre (-2.f), // -3.f: r=0.38 sphere of influence (contribution = 1/4) // -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 if (d > 0) @@ -168,6 +172,8 @@ protected: #if 0 if (special < 0.f) return special; +#else + (void)special; #endif return get_scale() * result; @@ -275,8 +281,8 @@ private: continue; 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", minlength, maxlength); @@ -300,7 +306,7 @@ private: p += k * vertices[j]; 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); #endif @@ -327,7 +333,7 @@ private: /* Find distance from current vertex to the opposite hyperplane. * Just use the projection theorem in N dimensions. */ 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); #endif } @@ -345,11 +351,12 @@ private: /* Try to find max noise value by climbing gradient */ float minval = 0.f, maxval = 0.f; - array> deltas; + std::vector> deltas; for (int i = 0; i < N; ++i) { auto v = vec_t::axis(i); - deltas << v << -v; + deltas.push_back(v); + deltas.push_back(-v); } for (int run = 0; run < 1000; ++run) { @@ -364,10 +371,10 @@ private: { int best_delta = -1; 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]); - if (abs(t2) > abs(best_t2)) + if (fabs(t2) > fabs(best_t2)) { best_delta = i; best_t2 = t2; @@ -381,11 +388,11 @@ private: 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); - float newscale = 1.f / max(-minval, maxval); + float newscale = 1.f / std::max(-minval, maxval); if (newscale < 1.f) printf(" - could replace scale %f with %f\n", get_scale(), newscale * get_scale());