From 63135466a21c869238d6441509a7ca98bbaa17dd Mon Sep 17 00:00:00 2001 From: Hartmut Seichter Date: Thu, 11 Jul 2024 09:22:39 +0200 Subject: [PATCH] WiP --- .gitignore | 1 + .vscode/settings.json | 56 ++++- src/core/CMakeLists.txt | 4 +- src/core/include/pw/core/matrix.hpp | 206 +--------------- src/core/include/pw/core/matrix_transform.hpp | 209 ++++++++-------- src/core/include/pw/core/matrixbase.hpp | 89 ++++++- src/core/include/pw/core/vector.hpp | 233 ++++++++++-------- tests/pw_test_core.cpp | 102 +++++--- 8 files changed, 430 insertions(+), 470 deletions(-) diff --git a/.gitignore b/.gitignore index 8f971c7..118019c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ compile_commands.json *.autosave build +.cache diff --git a/.vscode/settings.json b/.vscode/settings.json index 7482615..9763060 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -50,7 +50,61 @@ "typeinfo": "cpp", "drawable": "cpp", "userdatacontainer": "cpp", - "*.txx": "cpp" + "*.txx": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwctype": "cpp", + "any": "cpp", + "atomic": "cpp", + "hash_map": "cpp", + "strstream": "cpp", + "cfenv": "cpp", + "charconv": "cpp", + "cinttypes": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "coroutine": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "forward_list": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_set": "cpp", + "algorithm": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "random": "cpp", + "ratio": "cpp", + "source_location": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "utility": "cpp", + "hash_set": "cpp", + "fstream": "cpp", + "iomanip": "cpp", + "iostream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "numbers": "cpp", + "semaphore": "cpp", + "sstream": "cpp", + "stdfloat": "cpp", + "text_encoding": "cpp", + "typeindex": "cpp", + "variant": "cpp" }, "mesonbuild.configureOnOpen": false } \ No newline at end of file diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c11b65a..bfa5ad8 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -33,8 +33,8 @@ set(misc set(srcs # src/buffer.cpp src/core.cpp - # src/image.cpp - # src/debug.cpp + src/image.cpp + src/debug.cpp # src/geometry.cpp # src/material.cpp # src/resource.cpp diff --git a/src/core/include/pw/core/matrix.hpp b/src/core/include/pw/core/matrix.hpp index 09756ef..0072d6c 100644 --- a/src/core/include/pw/core/matrix.hpp +++ b/src/core/include/pw/core/matrix.hpp @@ -25,215 +25,11 @@ #include #include -#include - -// #include -#include +#include namespace pw { -template -struct matrix_ : matrixbase_> { - using base_type = matrixbase_>; - using typename base_type::value_type; - using typename base_type::derived_type; - - static constexpr std::size_t rows{R}; - static constexpr std::size_t cols{C}; - static constexpr std::size_t coefficients{R * C}; - static constexpr std::size_t diagonal_size{std::min(R,C)}; - - using col_type = matrix_; - using row_type = matrix_<1, C, T>; - using diag_type = matrix_; - using transpose_type = matrix_; - - - value_type data[R * C]{}; - - - template - static constexpr auto make(Arguments&&... values) -> matrix_ { - static_assert(sizeof...(Arguments) == coefficients, - "Incorrect number of arguments"); - return {.data = { T(values)... } }; - } - - constexpr size_t offset(size_t r, size_t c) const noexcept { - return (RowMajor) ? r * C + c : c * R + r; - } - - constexpr T& operator()(std::size_t r, std::size_t c) noexcept { - return data[offset(r, c)]; - } - - constexpr const T& operator()(std::size_t r, std::size_t c) const noexcept { - return data[offset(r, c)]; - } - - constexpr const T* ptr() const noexcept { return &data[0]; } - - //! set identity - constexpr matrix_& set_identity() { - for (std::size_t r = 0; r < rows; r++) - for (std::size_t c = 0; c < cols; c++) - (*this)(r, c) = (c == r) ? T(1) : T(0); - return *this; - } - - constexpr matrix_& set_uniform(const T& v) { - std::fill(std::begin(data), std::end(data), v); - return *this; - } - - template - auto slice(std::size_t r, std::size_t c) const { - matrix_ s; - for (std::size_t ri = 0; ri < Rs; ri++) - for (std::size_t ci = 0; ci < Cs; ci++) - s(ri, ci) = (*this)(ri + r, ci + c); - return s; - } - - template - matrix_& set_slice(const matrix_& s, - std::size_t r, std::size_t c) { - for (std::size_t ri = 0; ri < Rs; ri++) - for (std::size_t ci = 0; ci < Cs; ci++) - (*this)(ri + r, ci + c) = s(ri, ci); - return *this; - } - - template - auto minor(std::size_t r0, std::size_t c0) const { - matrix_ m; - size_t r = 0; - for (size_t ri = 0; ri < R; ri++) { - size_t c = 0; - if (ri == r0) - continue; - for (size_t ci = 0; ci < C; ci++) { - if (ci == c0) - continue; - m(r, c) = (*this)(ri, ci); - c++; - } - r++; - } - return m; - } - - constexpr T determinant() const { - T det(0); - for (size_t c = 0; c < C; c++) - det += ((c % 2 == 0) ? (*this)(0, c) : -(*this)(0, c)) * - this->minor(0, c).determinant(); - return det; - } - - auto transposed() const { - transpose_type res; - for (size_t r = rows; r-- > 0;) - for (size_t c = cols; c-- > 0;) - res(c, r) = (*this)(r, c); - return res; - } - - auto inverse() const { - T invDet = T(1) / this->determinant(); - matrix_ inv; - for (int j = 0; j < C; j++) - for (int i = 0; i < R; i++) { - const T minorDet = - this->minor(j, i).determinant(); - const T coFactor = ((i + j) % 2 == 1) ? -minorDet : minorDet; - inv(i, j) = invDet * coFactor; - } - return inv; - } - - constexpr bool row_major() const { return RowMajor; } - - constexpr bool square() const { return R == C; } - - constexpr const matrix_ operator+(const matrix_& other) const { - matrix_ res(*this); - for (size_t r = 0; r < R; r++) - for (size_t c = 0; c < C; c++) - res(r, c) += other(r, c); - return res; - } - - constexpr const matrix_ operator-(const matrix_& other) const { - matrix_ res(*this); - for (size_t r = 0; r < R; r++) - for (size_t c = 0; c < C; c++) - res(r, c) -= other(r, c); - return res; - } - - auto row(size_t row_) const { - row_type r; - for (size_t i = 0; i < cols; i++) - r[i] = (*this)(row_, i); - return r; - } - - auto column(size_t col_) const { - col_type c; - for (size_t i = 0; i < rows; i++) - c[i] = (*this)(i, col_); - return c; - } - - static constexpr auto identity() { - matrix_ res; - for (std::size_t r = 0; r < rows; r++) - for (std::size_t c = 0; c < cols; c++) - res(r, c) = (c == r) ? T(1) : T(0); - return res; - } -}; - -template <> constexpr float matrix_<1, 1, float>::determinant() const { - return (*this)(0, 0); -} - -template <> constexpr double matrix_<1, 1, double>::determinant() const { - return (*this)(0, 0); -} - -template -auto operator*(const matrix_& A, const matrix_& B) { - matrix_ result; - result.zero(); // zero the output - for (size_t r = 0; r < R; r++) - for (size_t c = 0; c < Cb; c++) - for (size_t iI = 0; iI < R; iI++) - result(r, c) += A(r, iI) * B(iI, c); // inner product - return result; -} - -// -// common matrix types -// - -template using matrix2x2_ = matrix_<2, 2, T>; -template using matrix3x3_ = matrix_<3, 3, T>; -template using matrix4x4_ = matrix_<4, 4, T>; - -using matrix2x2f = matrix2x2_; -using matrix2x2d = matrix2x2_; -using matrix2x2 = matrix2x2_; - -using matrix3x3f = matrix3x3_; -using matrix3x3d = matrix3x3_; -using matrix3x3 = matrix3x3_; - -using matrix4x4f = matrix4x4_; -using matrix4x4d = matrix4x4_; -using matrix4x4 = matrix4x4_; } // namespace pw #endif diff --git a/src/core/include/pw/core/matrix_transform.hpp b/src/core/include/pw/core/matrix_transform.hpp index 467b54a..ffac9d8 100644 --- a/src/core/include/pw/core/matrix_transform.hpp +++ b/src/core/include/pw/core/matrix_transform.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, @@ -27,144 +27,137 @@ namespace pw { -template -struct matrix_transform { +template struct matrix_transform { - constexpr static matrix_<4,4,T> scale_matrix(const vector3_& s) noexcept - { - matrix_<4,4,T> scale; scale.zero(); - scale(0,0) = s[0]; scale(1,1) = s[1]; scale(2,2) = s[2]; scale(3,3) = T(1); + constexpr static matrix_<4, 4, T> + scale_matrix(const vector3_& s) noexcept { + matrix_<4, 4, T> scale; + scale.zero(); + scale(0, 0) = s[0]; + scale(1, 1) = s[1]; + scale(2, 2) = s[2]; + scale(3, 3) = T(1); return scale; } - inline static - matrix_<4,4,T> perspective_frustum_rh(const T &left,const T &right, - const T &bottom,const T &top, - const T &z_near,const T &z_far) - { - matrix_<4,4,T> frustum; frustum.zero(); + constexpr auto perspective_frustum_rh(const T& left, const T& right, + const T& bottom, const T& top, + const T& z_near, const T& z_far) { + matrix frustum::identity(); - frustum(0,0) = T(2) * z_near / (right - left); - frustum(1,1) = T(2) * z_near / (top - bottom); + frustum[0][0] = T(2) * z_near / (right - left); + frustum[1][1] = T(2) * z_near / (top - bottom); - frustum(0,2) = (right+left)/(right-left); //A - frustum(1,2) = (top+bottom)/(top-bottom); //B - frustum(2,2) = -(z_far+z_near)/(z_far-z_near); //C - frustum(2,3) = -T(2) * z_far*z_near/(z_far-z_near); //D + frustum[0][2] = (right + left) / (right - left); // A + frustum[1][2] = (top + bottom) / (top - bottom); // B + frustum[2][2] = -(z_far + z_near) / (z_far - z_near); // C + frustum[2][3] = -T(2) * z_far * z_near / (z_far - z_near); // D - frustum(3,2) = -T(1); + frustum[3][2] = -T(1); - return frustum; - } + return frustum; + } + // /// creates a projection from a frustum planes with a reversed depth + // mapped to [0..1] pub fn make_projection_rh_from_frustum_reversed( + // left: f32, + // right: f32, + // bottom: f32, + // top: f32, + // z_near: f32, + // z_far: f32, + // ) -> Mat4 { + // assert!(z_near > 0.0 && z_far > 0.0); -// /// creates a projection from a frustum planes with a reversed depth mapped to [0..1] -// pub fn make_projection_rh_from_frustum_reversed( -// left: f32, -// right: f32, -// bottom: f32, -// top: f32, -// z_near: f32, -// z_far: f32, -// ) -> Mat4 { -// assert!(z_near > 0.0 && z_far > 0.0); + // // info!("near {:?}", z_near); -// // info!("near {:?}", z_near); + // // + // // reversed z 0..1 projection + // // + // let a = (right + left) / (right - left); // position in frame + // horizontal let b = (top + bottom) / (top - bottom); // position in + // frame vertical -// // -// // reversed z 0..1 projection -// // -// let a = (right + left) / (right - left); // position in frame horizontal -// let b = (top + bottom) / (top - bottom); // position in frame vertical + // let c = z_near / (z_far - z_near); // lower bound + // let d = z_far * z_near / (z_far - z_near); // upper bound -// let c = z_near / (z_far - z_near); // lower bound -// let d = z_far * z_near / (z_far - z_near); // upper bound + // let sx = 2.0 * z_near / (right - left); // scale x + // let sy = 2.0 * z_near / (top - bottom); // scale y -// let sx = 2.0 * z_near / (right - left); // scale x -// let sy = 2.0 * z_near / (top - bottom); // scale y + // // reverse z 0..1 + // // -------------- + // // sx 0 a 0 + // // 0 sy b 0 + // // 0 0 c d + // // 0 0 -1 0 -// // reverse z 0..1 -// // -------------- -// // sx 0 a 0 -// // 0 sy b 0 -// // 0 0 c d -// // 0 0 -1 0 + // Mat4::from_cols( + // Vec4::new(sx, 0.0, 0.0, 0.0), + // Vec4::new(0.0, sy, 0.0, 0.0), + // Vec4::new(a, b, c, -1.0), + // Vec4::new(0.0, 0.0, d, 0.0), + // ) + // } + inline static matrix_<4, 4, T> + perspective_projection(const T& field_of_view, const T& aspect_ratio, + const T& z_near, const T& z_far) { + const auto tan_half = tan(field_of_view / T(2)); + const auto right = tan_half * z_near / aspect_ratio; + const auto left = -right; + const auto top = right / aspect_ratio; + const auto bottom = -top; -// Mat4::from_cols( -// Vec4::new(sx, 0.0, 0.0, 0.0), -// Vec4::new(0.0, sy, 0.0, 0.0), -// Vec4::new(a, b, c, -1.0), -// Vec4::new(0.0, 0.0, d, 0.0), -// ) -// } - inline static - matrix_<4,4,T> perspective_projection(const T &field_of_view, - const T &aspect_ratio, - const T &z_near,const T &z_far) - { - const auto tan_half = tan(field_of_view / T(2)); - const auto right = tan_half * z_near / aspect_ratio; - const auto left = -right; - const auto top = right / aspect_ratio; - const auto bottom = -top; + return perspective_frustum_rh(left, right, bottom, top, z_near, z_far); + } - return perspective_frustum_rh(left,right, - bottom,top, - z_near,z_far); - } + inline static matrix_<4, 4, T> + orthographic_frustum(T left, T right, T bottom, T top, T z_near, T z_far) { + matrix_<4, 4, T> ortho; + ortho.fill(0); - inline static - matrix_<4,4,T> orthographic_frustum(T left, T right, - T bottom,T top, - T z_near, T z_far) - { + ortho(0, 0) = static_cast(2) / (right - left); + ortho(1, 1) = static_cast(2) / (top - bottom); + ortho(2, 2) = -static_cast(2) / (z_far - z_near); - matrix_<4,4,T> ortho; ortho.fill(0); + ortho(3, 0) = -(right + left) / (right - left); + ortho(3, 1) = -(top + bottom) / (top - bottom); + ortho(3, 2) = -(z_far + z_near) / (z_far - z_near); - ortho(0,0) = static_cast(2) / (right-left); - ortho(1,1) = static_cast(2) / (top-bottom); - ortho(2,2) = -static_cast(2) / (z_far-z_near); - - ortho(3,0) = -(right+left)/(right-left); - ortho(3,1) = -(top+bottom)/(top-bottom); - ortho(3,2) = -(z_far+z_near)/(z_far-z_near); - - ortho(3,3) = 1; + ortho(3, 3) = 1; return ortho; } - inline static - matrix_<4,4,T> orthographic_projection(T width,T height,T z_near, T z_far) - { - return orthographic_frustum(-width / 2, width / 2, - -height / 2, height / 2, - z_near,z_far); - } + inline static matrix_<4, 4, T> orthographic_projection(T width, T height, + T z_near, T z_far) { + return orthographic_frustum(-width / 2, width / 2, -height / 2, + height / 2, z_near, z_far); + } + inline static matrix_<4, 4, T> look_at(const vector3_& position, + const vector3_& target, + const vector3_& up) { + matrix_<4, 4, T> view_matrix; + view_matrix.set_identity(); - inline static - matrix_<4,4,T> look_at(const vector3_ &position, - const vector3_ &target, - const vector3_ &up) - { - matrix_<4,4,T> view_matrix; view_matrix.set_identity(); - - const vector3_ los = (target - position).normalized(); // line of sight - const vector3_ sid = vector3_::cross(los,up).normalized(); // side vector - const vector3_ upd = vector3_::cross(sid,los).normalized(); // upvector + const vector3_ los = + (target - position).normalized(); // line of sight + const vector3_ sid = + vector3_::cross(los, up).normalized(); // side vector + const vector3_ upd = + vector3_::cross(sid, los).normalized(); // upvector // set base vectors - view_matrix.set_slice(sid, 0, 0); - view_matrix.set_slice(upd, 0, 1); - view_matrix.set_slice(los * T(-1), 0, 2); - view_matrix.set_slice(position, 0, 3); + view_matrix.set_slice(sid, 0, 0); + view_matrix.set_slice(upd, 0, 1); + view_matrix.set_slice(los * T(-1), 0, 2); + view_matrix.set_slice(position, 0, 3); - return view_matrix; + return view_matrix; } }; -} +} // namespace pw #endif diff --git a/src/core/include/pw/core/matrixbase.hpp b/src/core/include/pw/core/matrixbase.hpp index abedbcd..5861553 100644 --- a/src/core/include/pw/core/matrixbase.hpp +++ b/src/core/include/pw/core/matrixbase.hpp @@ -106,15 +106,88 @@ struct matrixbase_ { } - constexpr void operator *= (const T& b) { for (auto & e : *this) e *= b; } - constexpr void operator /= (const T& b) { for (auto & e : *this) e /= b; } - constexpr void operator += (const T& b) { for (auto & e : *this) e += b; } - constexpr void operator -= (const T& b) { for (auto & e : *this) e -= b; } + // + // 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; + } - constexpr const Derived operator * (const T& b) const { Derived r(derived()); for (auto & e : r) e *= b; return r; } - constexpr const Derived operator / (const T& b) const { Derived r(derived()); for (auto & e : r) e /= b; return r; } - constexpr const Derived operator + (const T& b) const { Derived r(derived()); for (auto & e : r) e += b; return r; } - constexpr const 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; + } }; diff --git a/src/core/include/pw/core/vector.hpp b/src/core/include/pw/core/vector.hpp index a1227a0..4f31032 100644 --- a/src/core/include/pw/core/vector.hpp +++ b/src/core/include/pw/core/vector.hpp @@ -23,137 +23,154 @@ #ifndef PW_CORE_VECTOR_HPP #define PW_CORE_VECTOR_HPP -#include - namespace pw { -/** - * Basic vector types used in pixwerx. - */ +template struct vector final { -template struct vector2_ : matrix_<2, 1, T> { + using value_type = Scalar; + static constexpr unsigned int coefficients{size}; - using base_type = matrix_<2, 1, T>; + Scalar v_[size]{}; - using base_type::base_type; - using base_type::operator=; - - vector2_(const base_type& m) : base_type(m) {} - vector2_(T x_, T y_) : base_type({x_, y_}) {} - - constexpr const T& x() const { return (*this)[0]; } - constexpr T& x() { return (*this)[0]; } - - constexpr const T& y() const { return (*this)[1]; } - constexpr T& y() { return (*this)[1]; } - - constexpr auto homogenous(T w = 1) const { - return matrix_<3, 1, T>({x(), y(), w}); + auto&& data(this auto&& self) { + return std::forward(self).v_; } - static T angle_between(const vector2_& a, const vector2_& b) { - return std::acos(dot(a.normalized(), b.normalized())); + auto&& operator[](this auto&& self, unsigned int e) { + return std::forward(self).v_[e]; } - static constexpr auto zero() { return vector2_(0, 0); } + static constexpr auto basis(const auto& d) noexcept { + return [&d](std::index_sequence) { + return vector{(d == Ss) ? Scalar(1) : Scalar(0)...}; + }(std::make_index_sequence{}); + } + + template + static constexpr auto + make(Args&&... values) noexcept -> vector { + static_assert(sizeof...(Args) == size, "incorrect number of arguments"); + return {{Scalar(values)...}}; + } + + static constexpr auto all(Scalar value) noexcept -> vector { + return [&value](std::index_sequence) { + return vector{value + Scalar(Is * 0)...}; + }(std::make_index_sequence{}); + } + + template + constexpr auto swizzle(Args&&... indices) const noexcept + -> vector { + return {{Scalar(v_[indices])...}}; + } + + constexpr auto minor(std::unsigned_integral auto d0) const noexcept { + return [this, &d0](std::index_sequence) { + return vector{ + (*this).v_[(Ss < d0) ? Ss : Ss + 1]...}; + }(std::make_index_sequence{}); + } + + static constexpr auto sequence(Scalar factor = Scalar{1}, + Scalar offset = Scalar{0}) noexcept { + return [&](std::index_sequence) { + return vector{{Scalar{Ss} * factor + offset...}}; + }(std::make_index_sequence{}); + } + + constexpr Scalar dot(const auto& other) const { + return [this, &other](std::index_sequence) { + return (... + (other[Ss] * (*this)[Ss])); + }(std::make_index_sequence{}); + } + + constexpr auto squared_norm() const noexcept { return dot(*this); } + + constexpr auto norm() const noexcept { + return std::sqrt(this->squared_norm()); + } + + constexpr vector operator*(const Scalar& v) const noexcept { + return [this, &v](std::index_sequence) { + return vector{{(*this)[Ss] * v...}}; + }(std::make_index_sequence{}); + } + + constexpr vector operator/(const Scalar& v) const noexcept { + return (*this).operator*(Scalar{1} / v); + } + + constexpr vector operator+(const vector& v) const noexcept { + return [this, &v](std::index_sequence) { + return vector{{(*this)[Ss] + v[Ss]...}}; + }(std::make_index_sequence{}); + } + + constexpr vector operator-(const vector& v) const noexcept { + return [this, &v](std::index_sequence) { + return vector{{(*this)[Ss] - v[Ss]...}}; + }(std::make_index_sequence{}); + } }; -template struct vector3_ : matrix_<3, 1, T> { +template +struct vector2 : vector { - typedef matrix_<3, 1, T> base_type; + constexpr const Scalar& x() const { return (*this)[0]; } + constexpr Scalar& x() { return (*this)[0]; } - // using base_type::base_type; - // using base_type::operator=; - - constexpr const T& x() const { return (*this)[0]; } - constexpr T& x() { return (*this)[0]; } - constexpr vector3_& set_x(T val) { - (*this)[0] = val; - return *this; - } - - constexpr const T& y() const { return (*this)[1]; } - constexpr T& y() { return (*this)[1]; } - constexpr vector3_& set_y(T val) { - (*this)[1] = val; - return *this; - } - - constexpr const T& z() const { return (*this)[2]; } - constexpr T& z() { return (*this)[2]; } - constexpr vector3_& set_z(T val) { - (*this)[2] = val; - return *this; - } - - constexpr auto xy() const { return vector2_({x(), y()}); } - constexpr auto homogenous(T w = 1) const { - return matrix_<4, 1, T>::make(x(), y(), z(), w); - } - - constexpr static vector3_ cross(const vector3_& lhs, const vector3_& rhs) { - return vector3_::make(lhs[1] * rhs[2] - rhs[1] * lhs[2], - lhs[2] * rhs[0] - rhs[2] * lhs[0], - lhs[0] * rhs[1] - rhs[0] * lhs[1]); - } - - constexpr static auto forward() { return vector3_::make(0, 0, -1); } - constexpr static auto backward() { return vector3_::make(0, 0, +1); } - constexpr static auto up() { return vector3_::make(0, +1, 0); } - constexpr static auto down() { return vector3_::make(0, -1, 0); } - constexpr static auto right() { return vector3_::make(+1, 0, 0); } - constexpr static auto left() { return vector3_::make(-1, 0, 0); } - constexpr static auto x_axis() { return vector3_::make(0, 0, +1); } - constexpr static auto y_axis() { return vector3_::make(0, 0, +1); } - constexpr static auto z_axis() { return vector3_::make(0, 0, +1); } - - static constexpr auto zero() { return vector3_(0, 0, 0); } + constexpr const Scalar& y() const { return (*this)[1]; } + constexpr Scalar& y() { return (*this)[1]; } }; -template struct vector4_ : matrix_<4, 1, T> { +template struct vector3 : vector { - using base_type = matrix_<4, 1, T>; - // using base_type::operator=; - - constexpr const T& x() const { return (*this)[0]; } - constexpr T& x() { return (*this)[0]; } - - constexpr const T& y() const { return (*this)[1]; } - constexpr T& y() { return (*this)[1]; } - - constexpr const T& z() const { return (*this)[2]; } - constexpr T& z() { return (*this)[2]; } - - constexpr const T& w() const { return (*this)[3]; } - constexpr T& w() { return (*this)[3]; } - - constexpr auto xyz() const { return vector3_::make(x(), y(), z()); } - - constexpr auto project() const { - return vector3_::make(x() / w(), y() / w(), z() / w()); + constexpr static vector3 cross(const vector3& lhs, const vector3& rhs) { + return {lhs[1] * rhs[2] - rhs[1] * lhs[2], + lhs[2] * rhs[0] - rhs[2] * lhs[0], + lhs[0] * rhs[1] - rhs[0] * lhs[1]}; } - static constexpr auto zero() { return vector2_(0, 0, 0, 0); } + constexpr static auto forward() { return {0, 0, -1}; } + constexpr static auto backward() { return {0, 0, +1}; } + constexpr static auto up() { return {0, +1, 0}; } + constexpr static auto down() { return {0, -1, 0}; } + constexpr static auto right() { return {+1, 0, 0}; } + constexpr static auto left() { return {-1, 0, 0}; } + constexpr static auto x_axis() { return {0, 0, +1}; } + constexpr static auto y_axis() { return {0, 0, +1}; } + constexpr static auto z_axis() { return {0, 0, +1}; } }; -// -// -// +template struct vector4 : vector { -using vector2f = vector2_; -using vector2d = vector2_; -using vector2i = vector2_; -using vector2 = vector2_; -using vector2_array = std::vector; + using base_type = vector; -using vector3f = vector3_; -using vector3d = vector3_; -using vector3 = vector3_; -using vector3_array = std::vector; + constexpr const Scalar& x() const { return (*this)[0]; } + constexpr Scalar& x() { return (*this)[0]; } + + constexpr const Scalar& y() const { return (*this)[1]; } + constexpr Scalar& y() { return (*this)[1]; } + + constexpr const Scalar& z() const { return (*this)[2]; } + constexpr Scalar& z() { return (*this)[2]; } + + constexpr const Scalar& w() const { return (*this)[3]; } + constexpr Scalar& w() { return (*this)[3]; } + + constexpr auto xyz() const { return base_type::swizzle(0,1,2); } +}; + + + +using vector2f = vector2; +using vector2d = vector2; +using vector2i = vector2; + +using vector3f = vector3; +using vector3d = vector3; -using vector4f = vector4_; -using vector4d = vector4_; -using vector4 = vector4_; } // namespace pw diff --git a/tests/pw_test_core.cpp b/tests/pw_test_core.cpp index 3c736e7..9222b6c 100644 --- a/tests/pw_test_core.cpp +++ b/tests/pw_test_core.cpp @@ -4,63 +4,89 @@ #include + TEST_CASE("core", "[matrix]") { - auto m44 = pw::matrix_<2, 2, float>{}; + auto m44 = pw::matrix{}; - REQUIRE(m44(0, 0) == 0); - REQUIRE(m44(0, 1) == 0); - REQUIRE(m44(1, 0) == 0); - REQUIRE(m44(1, 1) == 0); + REQUIRE(m44[0][0] == 0); + REQUIRE(m44[0][1] == 0); + REQUIRE(m44[1][0] == 0); + REQUIRE(m44[1][1] == 0); - m44 = pw::matrix2x2_::all(42.42f); + // auto m44_1 = pw::matrix<2, 2, float>{ 5, 4, 3, 2 }; - REQUIRE(m44(0, 0) == 42.42f); - REQUIRE(m44(0, 1) == 42.42f); - REQUIRE(m44(1, 0) == 42.42f); - REQUIRE(m44(1, 1) == 42.42f); + // REQUIRE(m44_1(0, 0) == 5); + // REQUIRE(m44_1(0, 1) == 3); + // REQUIRE(m44_1(1, 0) == 4); + // REQUIRE(m44_1(1, 1) == 2); - m44 *= 2; - REQUIRE(m44(0, 0) == 84.84f); - REQUIRE(m44(0, 1) == 84.84f); - REQUIRE(m44(1, 0) == 84.84f); - REQUIRE(m44(1, 1) == 84.84f); + // auto m44_2 = pw::matrix2x2_::all(42.42f); - m44.set_identity(); - REQUIRE(m44(0, 0) == 1.0f); - REQUIRE(m44(0, 1) == 0.0f); - REQUIRE(m44(1, 0) == 0.0f); - REQUIRE(m44(1, 1) == 1.0f); + // REQUIRE(m44_2(0, 0) == 42.42f); + // REQUIRE(m44_2(0, 1) == 42.42f); + // REQUIRE(m44_2(1, 0) == 42.42f); + // REQUIRE(m44_2(1, 1) == 42.42f); - auto m44_2 = pw::matrix2x2::make(0, 1, 2, 3); + // m44 *= 2; + // REQUIRE(m44(0, 0) == 84.84f); + // REQUIRE(m44(0, 1) == 84.84f); + // REQUIRE(m44(1, 0) == 84.84f); + // REQUIRE(m44(1, 1) == 84.84f); - REQUIRE(m44_2(0, 0) == 0.0f); - REQUIRE(m44_2(1, 0) == 1.0f); - REQUIRE(m44_2(0, 1) == 2.0f); - REQUIRE(m44_2(1, 1) == 3.0f); + // m44.set_identity(); + // REQUIRE(m44(0, 0) == 1.0f); + // REQUIRE(m44(0, 1) == 0.0f); + // REQUIRE(m44(1, 0) == 0.0f); + // REQUIRE(m44(1, 1) == 1.0f); + + // auto m44_2 = pw::matrix2x2::make(0, 1, 2, 3); + + // REQUIRE(m44_2(0, 0) == 0.0f); + // REQUIRE(m44_2(1, 0) == 1.0f); + // REQUIRE(m44_2(0, 1) == 2.0f); + // REQUIRE(m44_2(1, 1) == 3.0f); - pw::matrix2x2 m44_3 = {{},{1, 2, 3, 4}}; + // pw::matrix2x2 m44_3 = {{},{1, 2, 3, 4}}; - REQUIRE(m44_3(0, 0) == 1.0f); - REQUIRE(m44_3(1, 0) == 2.0f); - REQUIRE(m44_3(0, 1) == 3.0f); - REQUIRE(m44_3(1, 1) == 4.0f); + // REQUIRE(m44_3(0, 0) == 1.0f); + // REQUIRE(m44_3(1, 0) == 2.0f); + // REQUIRE(m44_3(0, 1) == 3.0f); + // REQUIRE(m44_3(1, 1) == 4.0f); + +} + + +TEST_CASE("core", "[vector.matrix]") { + + // auto vec4_1 = pw::vector4_{}; + // auto mat4_1 = pw::matrix_<4,1,float>{}; + + + // mat4_1 = vec4_1; // down is easy + + // vec4_1 = mat4_1; } TEST_CASE("core", "[vector]") { - auto vec4_1 = pw::vector4_{}; - auto vec4_2 = pw::vector4::make(1, 2, 3, 4); + // auto vec4_1 = pw::vector4_{}; + // auto vec4_2 = pw::vector4::make(1, 2, 3, 4); - auto vec4_3 = vec4_1 + vec4_2; + // pw::vector4 vec4_3 = vec4_1 + vec4_2; - REQUIRE(vec4_3[0] == 1.0f); - REQUIRE(vec4_3[1] == 2.0f); - REQUIRE(vec4_3[2] == 3.0f); - REQUIRE(vec4_3[3] == 4.0f); + // REQUIRE(vec4_3[0] == 1.0f); + // REQUIRE(vec4_3[1] == 2.0f); + // REQUIRE(vec4_3[2] == 3.0f); + // REQUIRE(vec4_3[3] == 4.0f); - + // auto vec4_4 = vec4_3 * 2; + + // REQUIRE(vec4_4[0] == 1.0f * 2); + // REQUIRE(vec4_4[1] == 2.0f * 2); + // REQUIRE(vec4_4[2] == 3.0f * 2); + // REQUIRE(vec4_4[3] == 4.0f * 2); }