Primitives of dynamic dimension, part 1: make vector, point & matrix dimensions retrievable via non-static functions
This commit is contained in:
parent
5133695c6f
commit
9995f38ab0
8 changed files with 59 additions and 40 deletions
|
|
@ -482,9 +482,9 @@ void controller::randomize(RNG && rng, float amplitude)
|
||||||
|
|
||||||
auto visit_m = [&rng, &d, amplitude](auto & m)
|
auto visit_m = [&rng, &d, amplitude](auto & m)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < m.rows; ++i)
|
for (std::size_t i = 0; i < m.rows(); ++i)
|
||||||
{
|
{
|
||||||
for (std::size_t j = 0; j < m.columns; ++j)
|
for (std::size_t j = 0; j < m.columns(); ++j)
|
||||||
{
|
{
|
||||||
m[i][j] = d(rng) * amplitude;
|
m[i][j] = d(rng) * amplitude;
|
||||||
}
|
}
|
||||||
|
|
@ -493,7 +493,7 @@ void controller::randomize(RNG && rng, float amplitude)
|
||||||
|
|
||||||
auto visit_v = [&rng, &d, amplitude](auto & v)
|
auto visit_v = [&rng, &d, amplitude](auto & v)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < v.dimension; ++i)
|
for (std::size_t i = 0; i < v.dimension(); ++i)
|
||||||
{
|
{
|
||||||
v[i] = d(rng) * amplitude;
|
v[i] = d(rng) * amplitude;
|
||||||
}
|
}
|
||||||
|
|
@ -535,9 +535,9 @@ void controller::mutate(RNG && rng, float amplitude)
|
||||||
|
|
||||||
auto visit_m = [&rng, &d, amplitude](auto & m)
|
auto visit_m = [&rng, &d, amplitude](auto & m)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < m.rows; ++i)
|
for (std::size_t i = 0; i < m.rows(); ++i)
|
||||||
{
|
{
|
||||||
for (std::size_t j = 0; j < m.columns; ++j)
|
for (std::size_t j = 0; j < m.columns(); ++j)
|
||||||
{
|
{
|
||||||
m[i][j] += d(rng) * amplitude;
|
m[i][j] += d(rng) * amplitude;
|
||||||
}
|
}
|
||||||
|
|
@ -546,7 +546,7 @@ void controller::mutate(RNG && rng, float amplitude)
|
||||||
|
|
||||||
auto visit_v = [&rng, &d, amplitude](auto & v)
|
auto visit_v = [&rng, &d, amplitude](auto & v)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < v.dimension; ++i)
|
for (std::size_t i = 0; i < v.dimension(); ++i)
|
||||||
{
|
{
|
||||||
v[i] += d(rng) * amplitude;
|
v[i] += d(rng) * amplitude;
|
||||||
}
|
}
|
||||||
|
|
@ -1098,7 +1098,7 @@ float animation_2d_app::eval_score(controller const & c, random::generator rng)
|
||||||
physics.advance(dt, sel, [&c, &energy, dt](system const & physics){
|
physics.advance(dt, sel, [&c, &energy, dt](system const & physics){
|
||||||
std::vector<float> torque(physics.joints.size(), 0.f);
|
std::vector<float> torque(physics.joints.size(), 0.f);
|
||||||
auto ctrl = c.apply(physics);
|
auto ctrl = c.apply(physics);
|
||||||
for (std::size_t i = 0; i < ctrl.dimension; ++i)
|
for (std::size_t i = 0; i < ctrl.dimension(); ++i)
|
||||||
torque[i] = ctrl[i];
|
torque[i] = ctrl[i];
|
||||||
energy += geom::length(ctrl) * dt;
|
energy += geom::length(ctrl) * dt;
|
||||||
return torque;
|
return torque;
|
||||||
|
|
@ -1441,7 +1441,7 @@ void animation_2d_app::do_test()
|
||||||
physics.advance(frame_clock.restart().count(), sel, [this](system const & physics){
|
physics.advance(frame_clock.restart().count(), sel, [this](system const & physics){
|
||||||
std::vector<float> torque(physics.joints.size());
|
std::vector<float> torque(physics.joints.size());
|
||||||
auto ctrl = population[test_id].apply(physics);
|
auto ctrl = population[test_id].apply(physics);
|
||||||
for (std::size_t i = 0; i < ctrl.dimension; ++i)
|
for (std::size_t i = 0; i < ctrl.dimension(); ++i)
|
||||||
torque[i] = ctrl[i];
|
torque[i] = ctrl[i];
|
||||||
return torque;
|
return torque;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,22 @@ namespace psemek::geom
|
||||||
template <typename T, std::size_t R, std::size_t C>
|
template <typename T, std::size_t R, std::size_t C>
|
||||||
struct matrix
|
struct matrix
|
||||||
{
|
{
|
||||||
static constexpr std::size_t rows = R;
|
|
||||||
static constexpr std::size_t columns = C;
|
|
||||||
|
|
||||||
using scalar_type = T;
|
using scalar_type = T;
|
||||||
|
static constexpr std::size_t static_rows = R;
|
||||||
|
static constexpr std::size_t static_columns = C;
|
||||||
|
|
||||||
detail::array<T, R * C>::type coords;
|
detail::array<T, R * C>::type coords;
|
||||||
|
|
||||||
|
std::size_t rows() const
|
||||||
|
{
|
||||||
|
return R;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t columns() const
|
||||||
|
{
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
auto operator[](std::size_t i)
|
auto operator[](std::size_t i)
|
||||||
{
|
{
|
||||||
return coords + C * i;
|
return coords + C * i;
|
||||||
|
|
@ -251,8 +260,8 @@ namespace psemek::geom
|
||||||
vector<T, N> m[] = {v, rows...};
|
vector<T, N> m[] = {v, rows...};
|
||||||
|
|
||||||
matrix<T, sizeof...(Rows) + 1, N> result;
|
matrix<T, sizeof...(Rows) + 1, N> result;
|
||||||
for (std::size_t i = 0; i < result.rows; ++i)
|
for (std::size_t i = 0; i < result.rows(); ++i)
|
||||||
for (std::size_t j = 0; j < result.columns; ++j)
|
for (std::size_t j = 0; j < result.columns(); ++j)
|
||||||
result[i][j] = m[i][j];
|
result[i][j] = m[i][j];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -263,8 +272,8 @@ namespace psemek::geom
|
||||||
vector<T, N> m[] = {v, columns...};
|
vector<T, N> m[] = {v, columns...};
|
||||||
|
|
||||||
matrix<T, N, sizeof...(Columns) + 1> result;
|
matrix<T, N, sizeof...(Columns) + 1> result;
|
||||||
for (std::size_t i = 0; i < result.rows; ++i)
|
for (std::size_t i = 0; i < result.rows(); ++i)
|
||||||
for (std::size_t j = 0; j < result.columns; ++j)
|
for (std::size_t j = 0; j < result.columns(); ++j)
|
||||||
result[i][j] = m[j][i];
|
result[i][j] = m[j][i];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,8 @@ namespace psemek::geom
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
struct point
|
struct point
|
||||||
{
|
{
|
||||||
static constexpr std::size_t dimension = N;
|
|
||||||
|
|
||||||
using scalar_type = T;
|
using scalar_type = T;
|
||||||
|
static constexpr std::size_t static_dimension = N;
|
||||||
|
|
||||||
detail::array<T, N>::type coords;
|
detail::array<T, N>::type coords;
|
||||||
|
|
||||||
|
|
@ -30,6 +29,11 @@ namespace psemek::geom
|
||||||
static_assert(sizeof...(Args) == N);
|
static_assert(sizeof...(Args) == N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t dimension() const
|
||||||
|
{
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
T & operator[](std::size_t i)
|
T & operator[](std::size_t i)
|
||||||
{
|
{
|
||||||
return coords[i];
|
return coords[i];
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,8 @@ namespace psemek::geom
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
struct vector
|
struct vector
|
||||||
{
|
{
|
||||||
static constexpr std::size_t dimension = N;
|
|
||||||
|
|
||||||
using scalar_type = T;
|
using scalar_type = T;
|
||||||
|
static constexpr std::size_t static_dimension = N;
|
||||||
|
|
||||||
detail::array<T, N>::type coords;
|
detail::array<T, N>::type coords;
|
||||||
|
|
||||||
|
|
@ -35,6 +34,11 @@ namespace psemek::geom
|
||||||
static_assert(sizeof...(Args) == N);
|
static_assert(sizeof...(Args) == N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::size_t dimension() const
|
||||||
|
{
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
T & operator[](std::size_t i)
|
T & operator[](std::size_t i)
|
||||||
{
|
{
|
||||||
return coords[i];
|
return coords[i];
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,12 @@ test_case(geom_matrix_empty)
|
||||||
static_assert(std::is_same_v<decltype(m10)::scalar_type, int>);
|
static_assert(std::is_same_v<decltype(m10)::scalar_type, int>);
|
||||||
static_assert(std::is_same_v<decltype(m01)::scalar_type, int>);
|
static_assert(std::is_same_v<decltype(m01)::scalar_type, int>);
|
||||||
|
|
||||||
expect_equal(m00.columns, 0);
|
expect_equal(m00.columns(), 0);
|
||||||
expect_equal(m00.rows, 0);
|
expect_equal(m00.rows(), 0);
|
||||||
expect_equal(m10.columns, 0);
|
expect_equal(m10.columns(), 0);
|
||||||
expect_equal(m10.rows, 1);
|
expect_equal(m10.rows(), 1);
|
||||||
expect_equal(m01.columns, 1);
|
expect_equal(m01.columns(), 1);
|
||||||
expect_equal(m01.rows, 0);
|
expect_equal(m01.rows(), 0);
|
||||||
|
|
||||||
expect_throw(m00[0][0], detail::empty_array_exception);
|
expect_throw(m00[0][0], detail::empty_array_exception);
|
||||||
expect_throw(m10[0][0], detail::empty_array_exception);
|
expect_throw(m10[0][0], detail::empty_array_exception);
|
||||||
|
|
@ -35,6 +35,8 @@ test_case(geom_matrix_init)
|
||||||
m[1][0] = 3;
|
m[1][0] = 3;
|
||||||
m[1][1] = 4;
|
m[1][1] = 4;
|
||||||
|
|
||||||
|
expect_equal(m.columns(), 2);
|
||||||
|
expect_equal(m.rows(), 2);
|
||||||
expect_equal(m[0][0], 1);
|
expect_equal(m[0][0], 1);
|
||||||
expect_equal(m[0][1], 2);
|
expect_equal(m[0][1], 2);
|
||||||
expect_equal(m[1][0], 3);
|
expect_equal(m[1][0], 3);
|
||||||
|
|
@ -67,9 +69,9 @@ test_case(geom_matrix_zero)
|
||||||
{
|
{
|
||||||
auto m = matrix<float, 5, 5>::zero();
|
auto m = matrix<float, 5, 5>::zero();
|
||||||
|
|
||||||
for (std::size_t i = 0; i < m.rows; ++i)
|
for (std::size_t i = 0; i < m.rows(); ++i)
|
||||||
{
|
{
|
||||||
for (std::size_t j = 0; j < m.rows; ++j)
|
for (std::size_t j = 0; j < m.columns(); ++j)
|
||||||
{
|
{
|
||||||
expect_equal(m[i][j], 0.f);
|
expect_equal(m[i][j], 0.f);
|
||||||
}
|
}
|
||||||
|
|
@ -80,9 +82,9 @@ test_case(geom_matrix_identity)
|
||||||
{
|
{
|
||||||
auto m = matrix<float, 5, 5>::identity();
|
auto m = matrix<float, 5, 5>::identity();
|
||||||
|
|
||||||
for (std::size_t i = 0; i < m.rows; ++i)
|
for (std::size_t i = 0; i < m.rows(); ++i)
|
||||||
{
|
{
|
||||||
for (std::size_t j = 0; j < m.rows; ++j)
|
for (std::size_t j = 0; j < m.columns(); ++j)
|
||||||
{
|
{
|
||||||
expect_equal(m[i][j], (i == j ? 1.f : 0.f));
|
expect_equal(m[i][j], (i == j ? 1.f : 0.f));
|
||||||
}
|
}
|
||||||
|
|
@ -93,9 +95,9 @@ test_case(geom_matrix_scalar)
|
||||||
{
|
{
|
||||||
auto m = matrix<float, 5, 5>::scalar(3.f);
|
auto m = matrix<float, 5, 5>::scalar(3.f);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < m.rows; ++i)
|
for (std::size_t i = 0; i < m.rows(); ++i)
|
||||||
{
|
{
|
||||||
for (std::size_t j = 0; j < m.rows; ++j)
|
for (std::size_t j = 0; j < m.columns(); ++j)
|
||||||
{
|
{
|
||||||
expect_equal(m[i][j], (i == j ? 3.f : 0.f));
|
expect_equal(m[i][j], (i == j ? 3.f : 0.f));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ test_case(geom_point_empty)
|
||||||
static_assert(std::is_same_v<decltype(pi)::scalar_type, int>);
|
static_assert(std::is_same_v<decltype(pi)::scalar_type, int>);
|
||||||
static_assert(std::is_same_v<decltype(pf)::scalar_type, float>);
|
static_assert(std::is_same_v<decltype(pf)::scalar_type, float>);
|
||||||
|
|
||||||
expect_equal(pi.dimension, 0);
|
expect_equal(pi.dimension(), 0);
|
||||||
expect_equal(pf.dimension, 0);
|
expect_equal(pf.dimension(), 0);
|
||||||
expect_throw(pi[0], detail::empty_array_exception);
|
expect_throw(pi[0], detail::empty_array_exception);
|
||||||
expect_throw(pf[0], detail::empty_array_exception);
|
expect_throw(pf[0], detail::empty_array_exception);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ test_case(geom_vector_empty)
|
||||||
static_assert(std::is_same_v<decltype(pi)::scalar_type, int>);
|
static_assert(std::is_same_v<decltype(pi)::scalar_type, int>);
|
||||||
static_assert(std::is_same_v<decltype(pf)::scalar_type, float>);
|
static_assert(std::is_same_v<decltype(pf)::scalar_type, float>);
|
||||||
|
|
||||||
expect_equal(pi.dimension, 0);
|
expect_equal(pi.dimension(), 0);
|
||||||
expect_equal(pf.dimension, 0);
|
expect_equal(pf.dimension(), 0);
|
||||||
expect_throw(pi[0], detail::empty_array_exception);
|
expect_throw(pi[0], detail::empty_array_exception);
|
||||||
expect_throw(pf[0], detail::empty_array_exception);
|
expect_throw(pf[0], detail::empty_array_exception);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -330,9 +330,9 @@ namespace psemek::gfx
|
||||||
if constexpr (is_matrix<attr>::value)
|
if constexpr (is_matrix<attr>::value)
|
||||||
{
|
{
|
||||||
using T = typename attr::scalar_type;
|
using T = typename attr::scalar_type;
|
||||||
using traits = attrib_traits<geom::vector<T, attr::columns>>;
|
using traits = attrib_traits<geom::vector<T, attr::static_columns>>;
|
||||||
|
|
||||||
for (std::size_t row = 0; row < attr::rows; ++row)
|
for (std::size_t row = 0; row < attr::static_rows; ++row)
|
||||||
{
|
{
|
||||||
attrib_description attr;
|
attrib_description attr;
|
||||||
attr.index = index + row;
|
attr.index = index + row;
|
||||||
|
|
@ -340,13 +340,13 @@ namespace psemek::gfx
|
||||||
attr.type = traits::type;
|
attr.type = traits::type;
|
||||||
attr.normalized = traits::normalized;
|
attr.normalized = traits::normalized;
|
||||||
attr.stride = stride;
|
attr.stride = stride;
|
||||||
attr.pointer = reinterpret_cast<char const *>(offset + row * attr::columns * sizeof(T));
|
attr.pointer = reinterpret_cast<char const *>(offset + row * attr::static_columns * sizeof(T));
|
||||||
attr.divisor = Instance ? 1 : 0;
|
attr.divisor = Instance ? 1 : 0;
|
||||||
|
|
||||||
result.attribs.push_back(attr);
|
result.attribs.push_back(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::rows, offset + attr_size<Attr1>(), stride);
|
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::static_rows, offset + attr_size<Attr1>(), stride);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -373,7 +373,7 @@ namespace psemek::gfx
|
||||||
|
|
||||||
if constexpr (is_matrix<attr>::value)
|
if constexpr (is_matrix<attr>::value)
|
||||||
{
|
{
|
||||||
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::rows, offset, stride);
|
make_attribs_description_impl<Instance, Attribs...>::make_impl(result, index + attr::static_rows, offset, stride);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue