compile time optimized slicing

This commit is contained in:
Hartmut Seichter 2024-07-16 23:30:29 +02:00
parent 86f45a084a
commit 2295b758b7
10 changed files with 134 additions and 72 deletions

View file

@ -23,79 +23,58 @@
#ifndef PW_CORE_AXISANGLE_HPP
#define PW_CORE_AXISANGLE_HPP
#include <pw/core/vector.hpp>
#include <pw/core/matrix.hpp>
#include <pw/core/vector.hpp>
namespace pw {
template <typename T> struct axisangle final {
template <std::floating_point Scalar> struct axisangle final {
using value_type = T;
using axis_type = vector3<T>;
using value_type = Scalar;
using axis_type = vector3<Scalar>;
axis_type axis = axis_type::basis(2);
T angle{};
Scalar angle{};
constexpr static auto from_matrix(const matrix<T, 4, 4>& m) noexcept -> axisangle {
using std::acos;
using std::sqrt;
constexpr static auto
from_matrix(const matrix<Scalar, 3, 3>& 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<T, 4, 4> {
using std::cos;
using std::sin;
constexpr auto to_matrix() const noexcept -> matrix<Scalar, 3, 3> {
// result
auto rot_mat { matrix<T,4,4>::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]
};
}
};

View file

@ -29,7 +29,7 @@
namespace pw {
template <typename Scalar> struct frustum final {
template <std::floating_point Scalar> 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,

View file

@ -23,10 +23,13 @@
#ifndef PW_CORE_MATRIX_HPP
#define PW_CORE_MATRIX_HPP
#include "vector.hpp"
#include <cstddef>
#include <pw/core/globals.hpp>
#include <pw/core/math.hpp>
#include <pw/core/vector.hpp>
#include <print>
#include <type_traits>
#include <utility>
@ -188,6 +191,38 @@ struct matrix final {
constexpr auto operator-=(const Scalar& v) noexcept {
return operator+=(-v);
}
template <std::size_t RowsSlice, std::size_t ColsSlice>
constexpr auto slice(std::size_t r = 0, std::size_t c = 0) const noexcept
-> matrix<Scalar, RowsSlice, ColsSlice> {
// clang-format off
return {
// rows in target
[&r, &c, this]<std::size_t... Rs>(std::index_sequence<Rs...>) {
// cols in target
return ([&r,&c,this]<std::size_t... Cs>(auto&& Ri,std::index_sequence<Cs...>) {
return (*this)[Ri].swizzle(std::forward<std::size_t>(Cs)...); // expand row and cols
}(std::forward<std::size_t>(Rs), std::make_index_sequence<ColsSlice>{}), ...); // fold over cols with current row
}(std::make_index_sequence<RowsSlice>{}); // rowwise expansion
};
// clang-format on
}
template <std::size_t RowsSlice, std::size_t ColsSlice>
constexpr void slice_test(std::size_t r = 0,
std::size_t c = 0) const noexcept {
// clang-format off
[&r, &c, this]<std::size_t... Rs>(std::index_sequence<Rs...>) { // rows in target
([&r,&c,this]<std::size_t... Cs>(auto&& Ri, std::index_sequence<Cs...>) { // cols in target
// (std::print("[{} {}]",Ri,Cs),...);
std::print("row:{} cols:[{} {}]",Ri,Cs...);
std::print("\n");
}(std::forward<std::size_t>(Rs), std::make_index_sequence<ColsSlice>{}), ...); // fold over cols with current row
}(std::make_index_sequence<RowsSlice>{}); // rowwise expansion
// clang-format on
}
};
template <> constexpr float matrix<float, 1, 1>::determinant() const noexcept {

View file

@ -178,6 +178,19 @@ template <std::floating_point Scalar> struct quaternion final {
std::cos(aa.angle / Scalar{2}) // w
};
}
constexpr static auto
from_matrix(const matrix<Scalar, 3, 3>& 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

View file

@ -24,12 +24,12 @@
#define PW_CORE_SERIALIZE_HPP
#include <pw/core/axisangle.hpp>
#include <pw/core/color.hpp>
#include <pw/core/matrix.hpp>
#include <pw/core/quaternion.hpp>
#include <pw/core/vector.hpp>
#include <pw/core/color.hpp>
#include <numeric>
#include <sstream>
#include <string>
@ -39,10 +39,11 @@ struct serialize {
template <typename T, auto N>
constexpr static std::string to_string(const vector<T, N>& 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 <typename T, auto R, auto C>

View file

@ -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)

View file

@ -32,7 +32,7 @@ auto main() -> int {
std::cout << "from matrix" << std::endl;
auto mrot = pw::matrix<float, 4, 4>{};
auto mrot = pw::matrix<float, 3, 3>{};
mrot[0][0] = 1;
mrot[2][1] = 1;
mrot[1][2] = -1;

View file

@ -1,9 +1,22 @@
#include <pw/core/frustum.hpp>
#include <print>
#include <vector>
auto main() -> int {
auto frustum = pw::frustum<float>::make_perspective_symmetric(
auto frustum_p = pw::frustum<float>::make_perspective_symmetric(
45.f, float{320} / 240, 0.1f, 1'000.f);
auto frustum_o = pw::frustum<float>::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);
}

View file

@ -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<float, 3, 3>::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);
}

View file

@ -4,21 +4,33 @@
// #include <pw/core/geometry.hpp>
#include <pw/core/axisangle.hpp>
#include <print>
#include <variant>
#include <vector>
#include <print>
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<vector<float, 3>> vertices{};
std::vector<std::size_t> 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 = {