compile time optimized slicing
This commit is contained in:
parent
86f45a084a
commit
2295b758b7
10 changed files with 134 additions and 72 deletions
|
@ -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]
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue