From 114f17a499991d73f9ce06c94a2c42ae78757520 Mon Sep 17 00:00:00 2001 From: Hartmut Seichter Date: Sat, 13 Jul 2024 00:29:47 +0200 Subject: [PATCH] WIP --- src/CMakeLists.txt | 2 +- src/core/CMakeLists.txt | 1 - src/core/include/pw/core/color.hpp | 44 ++- src/core/include/pw/core/matrix.hpp | 5 +- src/core/include/pw/core/matrixbase.hpp | 198 ------------- src/core/include/pw/core/quaternion.hpp | 330 +++++++++++++--------- src/core/include/pw/core/resource.hpp | 13 +- src/core/include/pw/core/serialize.hpp | 35 ++- src/core/tests/CMakeLists.txt | 14 +- src/core/tests/pwcore_test_color.cpp | 20 ++ src/core/tests/pwcore_test_matrix.cpp | 145 ++-------- src/core/tests/pwcore_test_quaternion.cpp | 37 ++- src/visual/CMakeLists.txt | 2 +- 13 files changed, 327 insertions(+), 519 deletions(-) delete mode 100644 src/core/include/pw/core/matrixbase.hpp create mode 100644 src/core/tests/pwcore_test_color.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3dd3765..ae94f15 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,5 @@ # first build dependencies -# add_subdirectory(deps) +add_subdirectory(deps) # build internal core add_subdirectory(core) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 13aef4c..bd7b93b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -8,7 +8,6 @@ set(hdrs include/pw/core/globals.hpp include/pw/core/material.hpp include/pw/core/math.hpp - include/pw/core/matrixbase.hpp include/pw/core/matrix.hpp include/pw/core/quaternion.hpp include/pw/core/image.hpp diff --git a/src/core/include/pw/core/color.hpp b/src/core/include/pw/core/color.hpp index fd2837b..0b6cb0b 100644 --- a/src/core/include/pw/core/color.hpp +++ b/src/core/include/pw/core/color.hpp @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -24,39 +24,31 @@ #define PW_CORE_COLOR_HPP #include -#include + +#include namespace pw { struct color { - vector4 rgba {0, 0, 0, 1}; + vector4f rgba{vector4f::all(1)}; - color() = default; + static constexpr auto from_rgb8888(uint8_t r8, uint8_t g8, uint8_t b8, + uint8_t a8) -> color { + return {static_cast(r8) / std::numeric_limits::max(), + static_cast(g8) / std::numeric_limits::max(), + static_cast(b8) / std::numeric_limits::max(), + static_cast(a8) / std::numeric_limits::max()}; + } - color(uint8_t r8,uint8_t g8,uint8_t b8,uint8_t a8) - : color(static_cast(r8 / std::numeric_limits::max()), - static_cast(g8 / std::numeric_limits::max()), - static_cast(b8 / std::numeric_limits::max()), - static_cast(a8 / std::numeric_limits::max())) - { - } + static constexpr auto from_rgb8888(uint32_t v) -> color { + return from_rgb8888((v & 0xff000000) >> 24, (v & 0x00ff0000) >> 16, + (v & 0x0000ff00) >> 8, (v & 0x000000ff)); + } - color(real_t r,real_t g,real_t b,real_t a) - : rgba({r,g,b,a}) - { - } - - color(const vector4& v) : rgba(v) { } - - operator vector4() const { return rgba; } - - uint32_t to_rgb8888() const { - return 0; - } + uint32_t to_rgb8888() const { return 0; } }; -} - +} // namespace pw #endif diff --git a/src/core/include/pw/core/matrix.hpp b/src/core/include/pw/core/matrix.hpp index 96260b5..ec302fa 100644 --- a/src/core/include/pw/core/matrix.hpp +++ b/src/core/include/pw/core/matrix.hpp @@ -26,9 +26,11 @@ #include #include #include + #include namespace pw { + template struct matrix final { @@ -69,8 +71,7 @@ struct matrix final { }(std::make_index_sequence{}); } - constexpr auto - column(std::unsigned_integral auto c) const noexcept -> column_type { + constexpr auto column(const unsigned int& c) const noexcept -> column_type { return [this, &c](std::index_sequence) { return column_type{(*this)[Rs][c]...}; }(std::make_index_sequence{}); diff --git a/src/core/include/pw/core/matrixbase.hpp b/src/core/include/pw/core/matrixbase.hpp deleted file mode 100644 index 5861553..0000000 --- a/src/core/include/pw/core/matrixbase.hpp +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 1999-2021 Hartmut Seichter - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ -#ifndef PW_CORE_MATRIXBASE_HPP -#define PW_CORE_MATRIXBASE_HPP - -#include -#include -#include -#include -#include - -namespace pw { - -template -struct matrixbase_ { - - using value_type = T; - using derived_type = Derived; - using iterator = value_type*; - using const_iterator = const value_type*; - - constexpr Derived& derived() noexcept { return static_cast(*this); } - constexpr const Derived& derived() const noexcept { return static_cast(*this); } - - constexpr std::size_t size() const noexcept { - return std::extent::value; - } - - constexpr Derived& fill(const T& v) noexcept { - std::fill(std::begin(derived().data), std::end(derived().data), T(v)); - return derived(); - } - - constexpr Derived& zero() { - return derived().fill(0); - } - - constexpr T squared_norm() const noexcept { - return std::accumulate(std::begin(derived().data),std::end(derived().data), T(0), - [&](const T& a,const T& b){ - return a + b * b; - }); - } - - static constexpr Derived - all(const std::convertible_to auto& v) noexcept { - Derived d; - d.fill(v); - return d; - } - - constexpr T norm() const noexcept { - return std::sqrt(squared_norm()); - } - - constexpr Derived normalized() const noexcept { - return *this / this->norm() ; - } - - constexpr void normalize() { - *this /= this->norm(); - } - - - constexpr iterator begin() { return &derived().data[0]; } - constexpr iterator end() { return &derived().data[0] + size(); } - constexpr const_iterator begin() const { return &derived().data[0]; } - constexpr const_iterator end() const { return &derived().data[0] + size(); } - - constexpr T& operator [] (std::size_t i) { - return derived().data[i]; - } - - constexpr const T& operator [] (std::size_t i) const { - return derived().data[i]; - } - - static constexpr T dot(const Derived &a,const Derived &b) noexcept - { - return std::inner_product(std::begin(a),std::end(a),std::begin(b),T(0)); - } - - static constexpr Derived lerp(const Derived &a,const Derived &b,const T& t) noexcept - { - return a + (b - a) * t; - } - - - // - // M (op) scalar - // - constexpr Derived operator*(const T& b) const { - Derived r(derived()); - for (auto& e : r) - e *= b; - return r; - } - constexpr Derived operator/(const T& b) const { - Derived r(derived()); - for (auto& e : r) - e /= b; - return r; - } - constexpr Derived operator+(const T& b) const { - Derived r(derived()); - for (auto& e : r) - e += b; - return r; - } - constexpr Derived operator-(const T& b) const { - Derived r(derived()); - for (auto& e : r) - e -= b; - return r; - } - - // - // M (op)== N - // - - constexpr void operator*=(const std::convertible_to auto& b) { - for (auto& e : derived()) - e *= b; - } - constexpr void operator/=(const std::convertible_to auto& b) { - for (auto& e : derived()) - e /= b; - } - constexpr void operator+=(const std::convertible_to auto& b) { - for (auto& e : derived()) - e += b; - } - constexpr void operator-=(const std::convertible_to auto& b) { - for (auto& e : derived()) - e -= b; - } - - // - // M (op) N - // - - /// @brief in-place addition with matrix of same size - /// @param rhs righthand-side matrix - constexpr void operator+=(const Derived& b) noexcept { - std::transform(b.cbegin(), b.cend(), (*this).cbegin(), (*this).begin(), - std::plus<>{}); - } - - /// @brief in-place subtraction with matrix of same size - /// @param rhs righthand-side matrix - constexpr void operator-=(const Derived& b) noexcept { - std::transform(b.cbegin(), b.cend(), (*this).cbegin(), (*this).begin(), - std::minus<>{}); - } - - /// @brief addition with matrix of same size - /// @param rhs righthand-side matrix - constexpr Derived operator+(const std::convertible_to auto& rhs) const noexcept { - Derived d{derived()}; - std::transform(std::begin(rhs), std::end(rhs), (d).begin(), std::plus<>{}); - return d; - } - - /// @brief subtraction with matrix of same size - /// @param rhs righthand-side matrix - constexpr Derived operator-(const Derived& rhs) const noexcept { - Derived d(derived()); - d -= rhs; - return d; - } - - -}; - -} - - -#endif diff --git a/src/core/include/pw/core/quaternion.hpp b/src/core/include/pw/core/quaternion.hpp index 8ba1d34..80254ff 100644 --- a/src/core/include/pw/core/quaternion.hpp +++ b/src/core/include/pw/core/quaternion.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2021 Hartmut Seichter + * Copyright (c) 1999-2024 Hartmut Seichter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,172 +23,241 @@ #ifndef PW_CORE_QUATERNION_HPP #define PW_CORE_QUATERNION_HPP -#include +#include #include +#include + +#include namespace pw { /** * simplified quaternion class */ -template -struct quaternion_ : vector4_ { +template struct quaternion final { - typedef vector4_ base_type; + using value_type = vector; - using typename base_type::value_type; - using base_type::base_type; - using base_type::x; - using base_type::y; - using base_type::z; - using base_type::w; - using base_type::lerp; - using base_type::xyz; -// using base_type::operator*; -// using base_type::operator/; + value_type q_{value_type::basis(3)}; // preset to identity + auto&& x(this auto&& self) { + return std::forward(self).q_.x(); + } + auto&& y(this auto&& self) { + return std::forward(self).q_.y(); + } + auto&& z(this auto&& self) { + return std::forward(self).q_.z(); + } + auto&& w(this auto&& self) { + return std::forward(self).q_.w(); + } - quaternion_(const base_type& other) : base_type(other) {} + constexpr auto + operator*(const quaternion& rhs) const noexcept -> quaternion { + return {rhs.w() * x() + rhs.x() * w() + rhs.y() * z() - rhs.z() * y(), + rhs.w() * y() - rhs.x() * z() + rhs.y() * w() + rhs.z() * x(), + rhs.w() * z() + rhs.x() * y() - rhs.y() * x() + rhs.z() * w(), + rhs.w() * w() - rhs.x() * x() - rhs.y() * y() - rhs.z() * z()}; + } - inline const quaternion_ operator * (const quaternion_& rhs) const { - return quaternion_( - rhs.w()*x() + rhs.x()*w() + rhs.y()*z() - rhs.z()*y(), - rhs.w()*y() - rhs.x()*z() + rhs.y()*w() + rhs.z()*x(), - rhs.w()*z() + rhs.x()*y() - rhs.y()*x() + rhs.z()*w(), - rhs.w()*w() - rhs.x()*x() - rhs.y()*y() - rhs.z()*z() - ); - } + constexpr auto conjugate() const noexcept -> quaternion { + return {-x(), -y(), -z(), w()}; + } - inline auto operator / (const T& rhs) const { - return quaternion_( { x() / rhs, y() / rhs, z() / rhs, w() / rhs, } ); - } + constexpr auto norm() const noexcept -> Scalar { return q_.norm(); } - //! conjugate - inline auto conjugate() const { return quaternion_( { -x(),-y(),-z(),w() } ); } + constexpr auto operator*(const Scalar& rhs) const noexcept -> quaternion { + return {.q_ = q_ * rhs}; + } - //! compute inverse - inline auto inverse() const { - return conjugate() / this->norm(); - } + constexpr auto operator/(const Scalar& rhs) const noexcept -> quaternion { + return operator*(Scalar{1} / rhs); + } - inline static auto identity() { - return quaternion_({0,0,0,1}); - } + constexpr auto normalized() const noexcept -> quaternion { + return {.q_ = q_.normalized()}; + } - const matrix4x4_ to_matrix() const { + constexpr auto inverse() const noexcept -> quaternion { + return conjugate() / this->norm(); + } - matrix4x4_ m; m.set_identity(); + constexpr auto to_matrix() const noexcept -> matrix { - T xx = x() * x(); - T xy = x() * y(); - T xz = x() * z(); - T xw = x() * w(); + const Scalar xx = x() * x(); + const Scalar xy = x() * y(); + const Scalar xz = x() * z(); + const Scalar xw = x() * w(); - T yy = y() * y(); - T yz = y() * z(); - T yw = y() * w(); + const Scalar yy = y() * y(); + const Scalar yz = y() * z(); + const Scalar yw = y() * w(); - T zz = z() * z(); - T zw = z() * w(); + const Scalar zz = z() * z(); + const Scalar zw = z() * w(); - m(0,0) = 1 - 2 * ( yy + zz ); - m(0,1) = 2 * ( xy - zw ); - m(0,2) = 2 * ( xz + yw ); + return { + vector{1 - 2 * (yy + zz), 2 * (xy - zw), 2 * (xz + yw)}, + vector{2 * (xy + zw), 1 - 2 * (xx + zz), 2 * (yz - xw)}, + vector{2 * (xz - yw), 2 * (yz + xw), 1 - 2 * (xx + yy)}, + }; + } - m(1,0) = 2 * ( xy + zw ); - m(1,1) = 1 - 2 * ( xx + zz ); - m(1,2) = 2 * ( yz - xw ); + static constexpr auto identity() noexcept -> quaternion { return {}; } - m(2,0) = 2 * ( xz - yw ); - m(2,1) = 2 * ( yz + xw ); - m(2,2) = 1 - 2 * ( xx + yy ); + static constexpr auto pi_around_x() noexcept -> quaternion { + return {Scalar{1}, Scalar{0}, Scalar{0}, Scalar{0}}; + } - return m; - } + static constexpr auto pi_around_y() noexcept -> quaternion { + return {Scalar{0}, Scalar{1}, Scalar{0}, Scalar{0}}; + } - static auto from_matrix(const matrix_<4,4,T> &m) { - using std::sqrt; - auto wtemp = sqrt(T(1) + m(0,0) + m(1,1) + m(2,2)) / T(2); - auto w4 = T(4.0) * wtemp; + static constexpr auto pi_around_z() noexcept -> quaternion { + return {Scalar{0}, Scalar{0}, Scalar{1}, Scalar{0}}; + } + + static constexpr auto lerp(const quaternion& a, const quaternion& b, + const Scalar& t) -> quaternion { + return {value_type::lerp(a.q_, b.q_, t).normalized()}; + } +}; + +// deduction guide for quaternion +template > +quaternion(T, U...) -> quaternion; + +#if 0 + constexpr quaternion_ operator*(const quaternion_& rhs) const { + return quaternion_( + rhs.w() * x() + rhs.x() * w() + rhs.y() * z() - rhs.z() * y(), + rhs.w() * y() - rhs.x() * z() + rhs.y() * w() + rhs.z() * x(), + rhs.w() * z() + rhs.x() * y() - rhs.y() * x() + rhs.z() * w(), + rhs.w() * w() - rhs.x() * x() - rhs.y() * y() - rhs.z() * z()); + } + + inline auto operator/(const T& rhs) const { return quaternion_({ - (m(2,1) - m(1,2)) / w4, - (m(0,2) - m(2,0)) / w4, - (m(1,0) - m(0,1)) / w4, - wtemp}); - } + x() / rhs, + y() / rhs, + z() / rhs, + w() / rhs, + }); + } - static auto normalized_lerp(const quaternion_ &a,const quaternion_ &b,const T &t) { - return quaternion_(lerp(a,b,t).normalized()); - } + //! conjugate + inline auto conjugate() const { + return quaternion_({-x(), -y(), -z(), w()}); + } - static auto slerp(const quaternion_& qa,const quaternion_& qb,const T& t) - { - using std::abs; - using std::sqrt; - using std::acos; + //! compute inverse + inline auto inverse() const { return conjugate() / this->norm(); } - // quaternion to return - quaternion_ qm; - // Calculate angle between them. - T cosHalfTheta = qa.w() * qb.w() + qa.x() * qb.x() + qa.y() * qb.y() + qa.z() * qb.z(); - // if qa=qb or qa=-qb then theta = 0 and we can return qa - if (abs(cosHalfTheta) >= T(1)) { - return qa; - } + inline static auto identity() { return quaternion_({0, 0, 0, 1}); } - // Calculate temporary values. - const T halfTheta = acos(cosHalfTheta); - const T sinHalfTheta = sqrt(1.0 - cosHalfTheta * cosHalfTheta); - // if theta = 180 degrees then result is not fully defined - // we could rotate around any axis normal to qa or qb - if (abs(sinHalfTheta) < 0.001){ // fabs is floating point absolute - qm.w() = (qa.w() * T(0.5) + qb.w() * T(0.5)); - qm.x() = (qa.x() * T(0.5) + qb.x() * T(0.5)); - qm.y() = (qa.y() * T(0.5) + qb.y() * T(0.5)); - qm.z() = (qa.z() * T(0.5) + qb.z() * T(0.5)); - return qm; - } - const T ratioA = sin((value_type(1) - t) * halfTheta) / sinHalfTheta; - const T ratioB = sin(t * halfTheta) / sinHalfTheta; - //calculate Quaternion. - qm.w() = (qa.w() * ratioA + qb.w() * ratioB); - qm.x() = (qa.x() * ratioA + qb.x() * ratioB); - qm.y() = (qa.y() * ratioA + qb.y() * ratioB); - qm.z() = (qa.z() * ratioA + qb.z() * ratioB); + const matrix4x4_ to_matrix() const { - return qm; - } + matrix4x4_ m; + m.set_identity(); + T xx = x() * x(); + T xy = x() * y(); + T xz = x() * z(); + T xw = x() * w(); - static auto from_axisangle(const axisangle_ &aa) { - using std::sin; - using std::cos; + T yy = y() * y(); + T yz = y() * z(); + T yw = y() * w(); - const T sinHalfAngle( sin(aa.angle * T(0.5) )); + T zz = z() * z(); + T zw = z() * w(); - return quaternion_( { aa.axis.x() * sinHalfAngle, // x - aa.axis.y() * sinHalfAngle, // y - aa.axis.z() * sinHalfAngle, // z - cos(aa.angle * T(0.5)) // w - } - ); + m(0, 0) = 1 - 2 * (yy + zz); + m(0, 1) = 2 * (xy - zw); + m(0, 2) = 2 * (xz + yw); - } + m(1, 0) = 2 * (xy + zw); + m(1, 1) = 1 - 2 * (xx + zz); + m(1, 2) = 2 * (yz - xw); + + m(2, 0) = 2 * (xz - yw); + m(2, 1) = 2 * (yz + xw); + m(2, 2) = 1 - 2 * (xx + yy); + + return m; + } + + static auto from_matrix(const matrix_<4, 4, T>& m) { + using std::sqrt; + auto wtemp = sqrt(T(1) + m(0, 0) + m(1, 1) + m(2, 2)) / T(2); + auto w4 = T(4.0) * wtemp; + return quaternion_({(m(2, 1) - m(1, 2)) / w4, (m(0, 2) - m(2, 0)) / w4, + (m(1, 0) - m(0, 1)) / w4, wtemp}); + } + + static auto normalized_lerp(const quaternion_& a, const quaternion_& b, + const T& t) { + return quaternion_(lerp(a, b, t).normalized()); + } + + static auto slerp(const quaternion_& qa, const quaternion_& qb, + const T& t) { + using std::abs; + using std::acos; + using std::sqrt; + + // quaternion to return + quaternion_ qm; + // Calculate angle between them. + T cosHalfTheta = qa.w() * qb.w() + qa.x() * qb.x() + qa.y() * qb.y() + + qa.z() * qb.z(); + // if qa=qb or qa=-qb then theta = 0 and we can return qa + if (abs(cosHalfTheta) >= T(1)) { + return qa; + } + + // Calculate temporary values. + const T halfTheta = acos(cosHalfTheta); + const T sinHalfTheta = sqrt(1.0 - cosHalfTheta * cosHalfTheta); + // if theta = 180 degrees then result is not fully defined + // we could rotate around any axis normal to qa or qb + if (abs(sinHalfTheta) < 0.001) { // fabs is floating point absolute + qm.w() = (qa.w() * T(0.5) + qb.w() * T(0.5)); + qm.x() = (qa.x() * T(0.5) + qb.x() * T(0.5)); + qm.y() = (qa.y() * T(0.5) + qb.y() * T(0.5)); + qm.z() = (qa.z() * T(0.5) + qb.z() * T(0.5)); + return qm; + } + const T ratioA = sin((value_type(1) - t) * halfTheta) / sinHalfTheta; + const T ratioB = sin(t * halfTheta) / sinHalfTheta; + // calculate Quaternion. + qm.w() = (qa.w() * ratioA + qb.w() * ratioB); + qm.x() = (qa.x() * ratioA + qb.x() * ratioB); + qm.y() = (qa.y() * ratioA + qb.y() * ratioB); + qm.z() = (qa.z() * ratioA + qb.z() * ratioB); + + return qm; + } + + static auto from_axisangle(const axisangle_& aa) { + using std::cos; + using std::sin; + + const T sinHalfAngle(sin(aa.angle * T(0.5))); + + return quaternion_({ + aa.axis.x() * sinHalfAngle, // x + aa.axis.y() * sinHalfAngle, // y + aa.axis.z() * sinHalfAngle, // z + cos(aa.angle * T(0.5)) // w + }); + } }; -// -// -// -using quaternion = quaternion_; -using quaternionf = quaternion_; -using quaterniond = quaternion_; - - - -} - - +#endif +} // namespace pw #if 0 /** @@ -412,9 +481,6 @@ const quaternion_ quaternion_::slerp(const quaternion_& qa,const quater return qm; } - - #endif - #endif diff --git a/src/core/include/pw/core/resource.hpp b/src/core/include/pw/core/resource.hpp index 42c5649..2e8d070 100644 --- a/src/core/include/pw/core/resource.hpp +++ b/src/core/include/pw/core/resource.hpp @@ -28,18 +28,15 @@ namespace pw { -class resource { -public: - using change_t = std::atomic_int_fast64_t; +struct resource final { - resource() = default; + using change_t = std::atomic_int_fast64_t; - int64_t changecount() const { return _changecount; } - void dirty() { ++_changecount; }; + constexpr int64_t changecount() const noexcept { return changecount_; } + void touch() { ++changecount_; }; protected: - - change_t _changecount; + change_t changecount_{}; }; } diff --git a/src/core/include/pw/core/serialize.hpp b/src/core/include/pw/core/serialize.hpp index ee8c851..29603c1 100644 --- a/src/core/include/pw/core/serialize.hpp +++ b/src/core/include/pw/core/serialize.hpp @@ -8,8 +8,8 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, @@ -23,38 +23,53 @@ #ifndef PW_CORE_SERIALIZE_HPP #define PW_CORE_SERIALIZE_HPP -#include "vector.hpp" +#include #include +#include +#include +#include -#include #include +#include namespace pw { struct serialize { - template + template constexpr static std::string to_string(const vector& v) { std::stringstream ss; - for(const auto& e : v) ss << e << ' '; + for (const auto& e : v) + ss << e << ' '; return ss.str(); } - template - constexpr static std::string to_string(const matrix& m) { + template + constexpr static std::string to_string(const matrix& m) { std::stringstream ss; - for (int r = 0; r < R;r++) { + for (int r = 0; r < R; r++) { ss << to_string(m[r]) << '\n'; } return ss.str(); } + template + constexpr static std::string to_string(const quaternion& v) { + std::stringstream ss; + ss << to_string(v.q_); + return ss.str(); + } + constexpr static std::string to_string(const color& v) { + std::stringstream ss; + ss << to_string(v.rgba); + return ss.str(); + } }; -} +} // namespace pw #endif diff --git a/src/core/tests/CMakeLists.txt b/src/core/tests/CMakeLists.txt index e50423a..f5b0b35 100644 --- a/src/core/tests/CMakeLists.txt +++ b/src/core/tests/CMakeLists.txt @@ -1,15 +1,13 @@ macro(make_test arg1) - add_executable(${arg1} - ${arg1}.cpp - ) - target_link_libraries(${arg1} - pwcore) + add_executable(${arg1} ${arg1}.cpp) + target_link_libraries(${arg1} pwcore) endmacro() - -# make_test(pwcore_test_matrix) make_test(pwcore_test_vector) +make_test(pwcore_test_matrix) make_test(pwcore_test_axisangle) -# make_test(pwcore_test_quaternion) +make_test(pwcore_test_quaternion) +make_test(pwcore_test_color) + # make_test(pwcore_test_transform_tools) # make_test(pwcore_test_mesh) diff --git a/src/core/tests/pwcore_test_color.cpp b/src/core/tests/pwcore_test_color.cpp new file mode 100644 index 0000000..580d208 --- /dev/null +++ b/src/core/tests/pwcore_test_color.cpp @@ -0,0 +1,20 @@ +#include +#include + +#include +#include + +auto main() -> int { + + pw::debug::d() << "pixwerx.color.test\n"; + + auto col = pw::color::from_rgb8888(255,0,0,255); + pw::debug::d() << "col -> \n" << pw::serialize::to_string(col); + + auto col_hx = pw::color::from_rgb8888(0xFF'EE'BB'AA); + pw::debug::d() << "col_hx(0xFFAABBAA) -> \n" << pw::serialize::to_string(col_hx); + + + + return 0; +} diff --git a/src/core/tests/pwcore_test_matrix.cpp b/src/core/tests/pwcore_test_matrix.cpp index 0ed0ae9..594142d 100644 --- a/src/core/tests/pwcore_test_matrix.cpp +++ b/src/core/tests/pwcore_test_matrix.cpp @@ -1,130 +1,41 @@ - - -#include -#include -#include - #include +#include +#include +#include -#include -#include +auto main() -> int { + pw::debug::d() << "pixwerx.matrix.test\n"; -int main(int argc,char **argv) { + auto m22 = pw::matrix{}; + pw::debug::d() << "matrix<2,2>{} -> \n" << pw::serialize::to_string(m22); - using namespace pw; + m22[0][0] = 1; + m22[0][1] = 2; + m22[1][0] = 3; + m22[1][1] = 4; - matrix2x2f m22; m22.zero(); + pw::debug::d() << "matrix<2,2>{1,2,3,4} -> \n" + << pw::serialize::to_string(m22); + auto m22_inv = m22.inverse(); - m22(0,0) = 1; m22(0,1) = 2; - m22(1,0) = 3; m22(1,1) = 4; + pw::debug::d() << "matrix<2,2>{1,2,3,4}.inverse() -> \n" + << pw::serialize::to_string(m22_inv); - vector2f v2; - v2[0] = 1; v2[1] = 3; + auto m22_inv_inv = m22_inv.inverse(); + pw::debug::d() << "matrix<2,2>{1,2,3,4}.inverse().inverse() -> \n" + << pw::serialize::to_string(m22_inv_inv); - vector2f v3( { 1.f,2.f } ); + auto row_1 = m22_inv[1]; + pw::debug::d() << "matrix<2,2>{1,2,3,4}.inverse()[1] -> \n" + << pw::serialize::to_string(row_1); + auto m22_tp = m22.transposed(); + pw::debug::d() << "matrix<2,2>{1,2,3,4}.transposed() -> \n" + << pw::serialize::to_string(m22_tp); - auto m22_inv = m22.inverse(); - auto m22_id = m22_inv * m22; - - auto v2_t = m22_id * v2; - auto v3_t = m22_id * v3; - - auto v2_f = m22 * v2; - auto v2_b = m22_inv * v2_f; - - vector2_ r_m22 = m22.row(0).transposed(); - vector2_ c_m22 = m22.column(1); - - auto r_m22_h = r_m22.homogenous(); - - debug::d() << "offset(0,1) col-major " << m22.offset(0,1); - debug::d() << "det " << m22.determinant(); - - std::cout << "m22 " << pw::serialize::matrix(m22) << std::endl; - std::cout << "m22-1 " << pw::serialize::matrix(m22_inv) << std::endl; - std::cout << "m22-i " << pw::serialize::matrix(m22_id) << std::endl; - std::cout << "v22_t " << pw::serialize::matrix(v2_t) << std::endl; - std::cout << "v3_t " << pw::serialize::matrix(v3_t) << std::endl; - - - std::cout << "v2_f " << pw::serialize::matrix(v2_f) << std::endl; - std::cout << "v2_b " << pw::serialize::matrix(v2_b) << std::endl; - - std::cout << "v2_b.norm " << v2_b.norm() << std::endl; - -// v2_b.normalize(); - std::cout << "v2_b.normalized " << pw::serialize::matrix(v2_b.normalized()) << std::endl; - -// std::cout << "v2_b~v3_t " << rad_to_deg(vector2f::angle_between(v2,v3)) << std::endl; - - - - - - -// vector2f v2 = m22.slice<2,1>(0,0); -// m22.set_slice<2,1>(v2,0,0); - -// v2 *= 2; -// v2 += 1; - -// m22 *= 3; - -// m22.determinant(); - -// debug::d() << sizeof(v2); - -// auto m22_i = m22.inverse(); - - - -#if 0 - - pw::matrix4x4d m; - - m.set_identity(); - - std::cout << "m = " << pw::serialize::matrix(m) << std::endl; - - std::cout << "row_stride() : " << m.row_stride() << std::endl; - std::cout << "col_stride() : " << m.col_stride() << std::endl; - std::cout << "rows() : " << m.rows() << std::endl; - std::cout << "cols() : " << m.cols() << std::endl; - std::cout << "data() : " << m.data() << std::endl; - std::cout << "data()[0] : " << m.data()[0] << std::endl; - std::cout << "at(0,0) : " << m.at(0,0) << std::endl; - std::cout << "determinant(): " << m.determinant() << std::endl; - - - pw::matrix4x4d mi = m.get_inverse(); - - std::cout << "mi.at(0,0) : " << mi.at(0,0) << std::endl; - - - pw::matrix4x4d mscale = m * 4.2; - - - std::cout << "mscale = " << pw::serialize::matrix(mscale) << std::endl; - - - pw::matrix4x4d a; - - for (int r = 0; r < m.rows(); r++) { - for (int c = 0; c < m.cols(); c++) { - a.at(r,c) = r * m.cols() + c; - } - } - std::cout << "a = " << pw::serialize::matrix(a) << std::endl; - - pw::matrix4x4d r = a * mscale; - - std::cout << "a * mscale = " << pw::serialize::matrix(r) << std::endl; - - - return 0; - -#endif + auto m22_tp_col1 = m22_tp.column(1); + pw::debug::d() << "matrix<2,2>{1,2,3,4}.transposed().column(1) -> \n" + << pw::serialize::to_string(m22_tp_col1); } diff --git a/src/core/tests/pwcore_test_quaternion.cpp b/src/core/tests/pwcore_test_quaternion.cpp index e04f906..8492549 100644 --- a/src/core/tests/pwcore_test_quaternion.cpp +++ b/src/core/tests/pwcore_test_quaternion.cpp @@ -1,29 +1,36 @@ +#include #include #include -#include +auto main() -> int { -int main(int argc,char **argv) { + pw::debug::d() << "pixwerx.quaternion.test\n"; - pw::quaternion_ qf; + auto q0 = pw::quaternion{}; + auto q1 = pw::quaternion{1.f, 2.f, 3.f, 4.f}; - std::cout << "qf = " << pw::serialize::matrix(qf) << std::endl; - std::cout << "qf.matrix() = " << pw::serialize::matrix(qf.to_matrix()) << std::endl; + pw::debug::d() << "q0 = quaternion{} -> \n" << pw::serialize::to_string(q0); + pw::debug::d() << "q1 = quaternion{1,2,3,4} -> \n" + << pw::serialize::to_string(q1); - std::cout << "qf.squared_norm() = " << qf.squared_norm() << std::endl; -// std::cout << "qf.dot(qf) = " << qf.dot(qf) << std::endl; - std::cout << "qf.conjugate() = " << pw::serialize::matrix(qf.conjugate()) << std::endl; + auto q0_x_q1 = q0 * q1; + pw::debug::d() << "q0 * q1 -> \n" << pw::serialize::to_string(q0_x_q1); - pw::quaternionf qc = qf.conjugate(); - std::cout << "qf.conjugate() (qc) = " << pw::serialize::matrix(qc.to_matrix()) << std::endl; + auto q1_conj = q1.conjugate(); + pw::debug::d() << "q1.conjugate() -> \n" + << pw::serialize::to_string(q1_conj); - pw::quaternionf qi = qf.inverse(); - std::cout << "qf.inverse() (qi) = " << pw::serialize::matrix(qi.to_matrix()) << std::endl; - - pw::quaternionf qmid = pw::quaternionf::normalized_lerp(qi,qf,0.5f); -// std::cout << "qmid.dot() (half between qf and qi) = " << pw::rad_to_deg(quaternionf::angle_between()) << std::endl; + auto q1_conj_nml = q1_conj.normalized(); + pw::debug::d() << "q1.conjugate().normalized() -> \n" + << pw::serialize::to_string(q1_conj_nml); + auto q1_conj_inv = q1_conj.inverse(); + pw::debug::d() << "q1.conjugate().inverse() -> \n" + << pw::serialize::to_string(q1_conj_inv); + auto lerp_q0_q1_half = decltype(q0)::lerp(q0, q1, 0.5f); + pw::debug::d() << "quaternion::lerp(q0,q1,0.5) -> \n" + << pw::serialize::to_string(lerp_q0_q1_half); return 0; diff --git a/src/visual/CMakeLists.txt b/src/visual/CMakeLists.txt index 36e6c8f..ce9ee81 100644 --- a/src/visual/CMakeLists.txt +++ b/src/visual/CMakeLists.txt @@ -38,4 +38,4 @@ target_include_directories( include ) -target_link_libraries(pwvisual pwscene glad) +target_link_libraries(pwvisual pwcore pwscene glad)