diff --git a/src/core/include/pw/core/axisangle.hpp b/src/core/include/pw/core/axisangle.hpp index 4bfe7a4..46ace0d 100644 --- a/src/core/include/pw/core/axisangle.hpp +++ b/src/core/include/pw/core/axisangle.hpp @@ -23,79 +23,58 @@ #ifndef PW_CORE_AXISANGLE_HPP #define PW_CORE_AXISANGLE_HPP -#include #include +#include namespace pw { -template struct axisangle final { +template struct axisangle final { - using value_type = T; - using axis_type = vector3; + using value_type = Scalar; + using axis_type = vector3; axis_type axis = axis_type::basis(2); - T angle{}; + Scalar angle{}; - constexpr static auto from_matrix(const matrix& m) noexcept -> axisangle { - using std::acos; - using std::sqrt; + constexpr static auto + from_matrix(const matrix& m) noexcept -> axisangle { - // axisangle aa_res; - // aa_res.angle = acos((m[0][0]) + m[1][1] + m[2][2] - 1) / T{2}); - const T m2112 = m[2][1] - m[1][2]; - const T m0220 = m[0][2] - m[2][0]; - const T m1001 = m[1][0] - m[0][1]; - - // no singularity check here ... - const T mrot_denom = - sqrt(m2112 * m2112 + m0220 * m0220 + m1001 * m1001); - - // aa_res.axis.x() = m2112 / mrot_denom; - // aa_res.axis.y() = m0220 / mrot_denom; - // aa_res.axis.z() = m1001 / mrot_denom; - - return { - .axis = axis_type{ - m2112 / mrot_denom, - m0220 / mrot_denom, - m1001 / mrot_denom - }, - .angle = acos( (m[0][0] + m[1][1] + m[2][2] - 1) / T{2} ) - }; + return {.axis = axis_type{m[2][1] - m[1][2], // x + m[0][2] - m[2][0], // y + m[1][0] - m[0][1]} // z + .normalized(), + .angle = + std::acos((m[0][0] + m[1][1] + m[2][2] - 1) / Scalar{2})}; } - constexpr auto to_matrix() const noexcept -> matrix { - using std::cos; - using std::sin; + constexpr auto to_matrix() const noexcept -> matrix { - // result - auto rot_mat { matrix::identity() }; - auto axis_n = axis.normalized(); // always normalize + const auto axis_n = axis.normalized(); // always normalize - const T cos_a = cos(angle); - const T sin_a = sin(angle); - const T cos_1_a = T(1) - cos_a; + const auto cos_a = std::cos(angle); + const auto sin_a = std::sin(angle); + const auto cos_1_a = 1 - cos_a; - rot_mat[0][0] = cos_a + axis_n.x() * axis_n.x() * cos_1_a; - rot_mat[1][1] = cos_a + axis_n.y() * axis_n.y() * cos_1_a; - rot_mat[2][2] = cos_a + axis_n.z() * axis_n.z() * cos_1_a; + const auto v1_a = axis_n.x() * axis_n.y() * cos_1_a; + const auto v2_a = axis_n.z() * sin_a; - T v1 = axis_n.x() * axis_n.y() * cos_1_a; - T v2 = axis_n.z() * sin_a; - rot_mat[1][0] = v1 + v2; - rot_mat[0][1] = v1 - v2; + const auto v1_b = axis_n.x() * axis_n.z() * cos_1_a; + const auto v2_b = axis_n.y() * sin_a; - v1 = axis_n.x() * axis_n.z() * cos_1_a; - v2 = axis_n.y() * sin_a; - rot_mat[2][0] = v1 - v2; - rot_mat[0][2] = v1 + v2; + const auto v1_c = axis_n.y() * axis_n.z() * cos_1_a; + const auto v2_c = axis_n.x() * sin_a; - v1 = axis_n.y() * axis_n.z() * cos_1_a; - v2 = axis_n.x() * sin_a; - rot_mat[2][1] = v1 + v2; - rot_mat[1][2] = v1 - v2; - - return rot_mat; + return { + pw::vector{cos_a + axis_n.x() * axis_n.x() * cos_1_a, // [0,0] + v1_a - v2_a, // [0,1] + v1_b + v2_b}, // [0,2] + pw::vector{v1_a + v2_a, // [1,0] + cos_a + axis_n.y() * axis_n.y() * cos_1_a, // [1,1] + v1_c - v2_c}, // [1,2] + pw::vector{v1_b - v2_b, // [2,0] + v1_c + v2_c, // [2,1] + cos_a + axis_n.z() * axis_n.z() * cos_1_a} // [2,2] + }; } }; diff --git a/src/core/include/pw/core/frustum.hpp b/src/core/include/pw/core/frustum.hpp index 4526dea..1587894 100644 --- a/src/core/include/pw/core/frustum.hpp +++ b/src/core/include/pw/core/frustum.hpp @@ -29,7 +29,7 @@ namespace pw { -template struct frustum final { +template struct frustum final { Scalar left{-1}, right{1}, bottom{-1}, top{1}, z_near{-1}, z_far{1}; static constexpr auto make_perspective_symmetric(Scalar fov_h_deg, diff --git a/src/core/include/pw/core/matrix.hpp b/src/core/include/pw/core/matrix.hpp index 923aec1..92448a6 100644 --- a/src/core/include/pw/core/matrix.hpp +++ b/src/core/include/pw/core/matrix.hpp @@ -23,10 +23,13 @@ #ifndef PW_CORE_MATRIX_HPP #define PW_CORE_MATRIX_HPP +#include "vector.hpp" +#include #include #include #include +#include #include #include @@ -188,6 +191,38 @@ struct matrix final { constexpr auto operator-=(const Scalar& v) noexcept { return operator+=(-v); } + + template + constexpr auto slice(std::size_t r = 0, std::size_t c = 0) const noexcept + -> matrix { + // clang-format off + return { + // rows in target + [&r, &c, this](std::index_sequence) { + // cols in target + return ([&r,&c,this](auto&& Ri,std::index_sequence) { + return (*this)[Ri].swizzle(std::forward(Cs)...); // expand row and cols + }(std::forward(Rs), std::make_index_sequence{}), ...); // fold over cols with current row + }(std::make_index_sequence{}); // rowwise expansion + }; + // clang-format on + } + + template + constexpr void slice_test(std::size_t r = 0, + std::size_t c = 0) const noexcept { + // clang-format off + [&r, &c, this](std::index_sequence) { // rows in target + ([&r,&c,this](auto&& Ri, std::index_sequence) { // cols in target + + // (std::print("[{} {}]",Ri,Cs),...); + std::print("row:{} cols:[{} {}]",Ri,Cs...); + std::print("\n"); + + }(std::forward(Rs), std::make_index_sequence{}), ...); // fold over cols with current row + }(std::make_index_sequence{}); // rowwise expansion + // clang-format on + } }; template <> constexpr float matrix::determinant() const noexcept { diff --git a/src/core/include/pw/core/quaternion.hpp b/src/core/include/pw/core/quaternion.hpp index 1e5893b..083d012 100644 --- a/src/core/include/pw/core/quaternion.hpp +++ b/src/core/include/pw/core/quaternion.hpp @@ -178,6 +178,19 @@ template struct quaternion final { std::cos(aa.angle / Scalar{2}) // w }; } + + constexpr static auto + from_matrix(const matrix& m) -> quaternion { + const auto wtemp = + std::sqrt(Scalar{1} + m[0][0] + m[1][1] + m[2][2]) / Scalar{2}; + const auto w4 = Scalar{4} * wtemp; + return { + (m[2][1] - m[1][2]) / w4, // x + (m[0][2] - m[2][0]) / w4, // y + (m[1][0] - m[0][1]) / w4, // z + wtemp // w + }; + } }; // deduction guide for quaternion diff --git a/src/core/include/pw/core/serialize.hpp b/src/core/include/pw/core/serialize.hpp index 29603c1..a47f790 100644 --- a/src/core/include/pw/core/serialize.hpp +++ b/src/core/include/pw/core/serialize.hpp @@ -24,12 +24,12 @@ #define PW_CORE_SERIALIZE_HPP #include +#include #include #include #include -#include - +#include #include #include @@ -39,10 +39,11 @@ struct serialize { template constexpr static std::string to_string(const vector& v) { - std::stringstream ss; - for (const auto& e : v) - ss << e << ' '; - return ss.str(); + return std::accumulate(std::next(std::begin(v)), std::end(v), + std::string(std::to_string(v[0])), + [](const auto& str, const auto& e) { + return str + " " + std::to_string(e); + }); } template diff --git a/src/core/tests/CMakeLists.txt b/src/core/tests/CMakeLists.txt index a527a0c..44a87a2 100644 --- a/src/core/tests/CMakeLists.txt +++ b/src/core/tests/CMakeLists.txt @@ -12,3 +12,4 @@ make_test(pwcore_test_transform_tools) make_test(pwcore_test_aabb) make_test(pwcore_test_frustum) make_test(pwcore_test_mesh) +make_test(pwcore_test_serialize) diff --git a/src/core/tests/pwcore_test_axisangle.cpp b/src/core/tests/pwcore_test_axisangle.cpp index e9850a5..62d0373 100644 --- a/src/core/tests/pwcore_test_axisangle.cpp +++ b/src/core/tests/pwcore_test_axisangle.cpp @@ -32,7 +32,7 @@ auto main() -> int { std::cout << "from matrix" << std::endl; - auto mrot = pw::matrix{}; + auto mrot = pw::matrix{}; mrot[0][0] = 1; mrot[2][1] = 1; mrot[1][2] = -1; diff --git a/src/core/tests/pwcore_test_frustum.cpp b/src/core/tests/pwcore_test_frustum.cpp index 32911d6..0d230e0 100644 --- a/src/core/tests/pwcore_test_frustum.cpp +++ b/src/core/tests/pwcore_test_frustum.cpp @@ -1,9 +1,22 @@ #include + +#include #include auto main() -> int { - auto frustum = pw::frustum::make_perspective_symmetric( + auto frustum_p = pw::frustum::make_perspective_symmetric( 45.f, float{320} / 240, 0.1f, 1'000.f); + + auto frustum_o = pw::frustum::make_orthographic_symmetric( + 1.5f, float{320} / 240, 0.1f, 1'000.f); + + std::print("l:{} r:{} b:{} t:{} n:{} f:{}\n", frustum_p.left, + frustum_p.right, frustum_p.bottom, frustum_p.top, frustum_p.z_near, + frustum_p.z_far); + + std::print("l:{} r:{} b:{} t:{} n:{} f:{}\n", frustum_p.left, + frustum_o.right, frustum_o.bottom, frustum_o.top, frustum_o.z_near, + frustum_o.z_far); } diff --git a/src/core/tests/pwcore_test_matrix.cpp b/src/core/tests/pwcore_test_matrix.cpp index a63e4f7..c234d2a 100644 --- a/src/core/tests/pwcore_test_matrix.cpp +++ b/src/core/tests/pwcore_test_matrix.cpp @@ -46,4 +46,14 @@ auto main() -> int { auto& [r1_x, r1_y] = r1; std::print("r1.x:{} r1.y:{}\n", r1_x, r1_y); + + auto m33 = pw::matrix::identity(); + + m33.slice_test<2, 2>(0, 0); + + auto m22_slice = m33.slice<2, 2>(0, 0); + + pw::debug::d() << "matrix<3,3>.slice() -> \n" + << pw::serialize::to_string(m33) << "\n to \n" + << pw::serialize::to_string(m22_slice); } diff --git a/src/core/tests/pwcore_test_mesh.cpp b/src/core/tests/pwcore_test_mesh.cpp index 949a57c..8008541 100644 --- a/src/core/tests/pwcore_test_mesh.cpp +++ b/src/core/tests/pwcore_test_mesh.cpp @@ -4,21 +4,33 @@ // #include #include +#include #include #include -#include namespace pw { struct geometry_n { + + enum struct topology_type { + point_list, + line_list, + line_strip, + triange_list, + triangle_strip, + triangle_fan, + line_list_with_adjacency, + line_strip_with_adjacency, + triangle_list_with_adjacency, + triangle_strip_with_adjacency, + patch_list + }; + std::vector> vertices{}; std::vector indices{}; }; struct mesh_n { - geometry_n geometry{}; - - }; } // namespace pw @@ -31,11 +43,9 @@ auto main() -> int { .indices = {0, 1, 2}}; for (auto i : geom.indices) { - std::print("({}) ",pw::serialize::to_string(geom.vertices[i])); + std::print("({}) ", pw::serialize::to_string(geom.vertices[i])); } - - // pw::geometry geo; // pw::vector3_array vs = {