WiP for proper support of ECS - figuring out how to use transformations in a ECS

This commit is contained in:
Hartmut Seichter 2020-12-17 23:23:08 +01:00
parent 1c5b74454f
commit a4f9308aa7
10 changed files with 107 additions and 60 deletions

View file

@ -75,6 +75,7 @@ public:
stream& operator << (const void *value); ///! pointer stream& operator << (const void *value); ///! pointer
protected: protected:
debug* _log; debug* _log;

View file

@ -70,9 +70,6 @@ struct matrix_ : matrixbase_<T, matrix_<R, C, T>>
return *this; return *this;
} }
// //! get cell count
// inline std::size_t coefficients() const { return this->size(); }
inline size_t offset(size_t r,size_t c) const { inline size_t offset(size_t r,size_t c) const {
return (RowMajor) ? r * C + c : c * R + r; return (RowMajor) ? r * C + c : c * R + r;
} }
@ -85,7 +82,7 @@ struct matrix_ : matrixbase_<T, matrix_<R, C, T>>
return data[offset(r,c)]; return data[offset(r,c)];
} }
inline const T* ptr() const { return &data[0]; } inline const T *ptr() const { return &data[0]; }
//! set identity //! set identity
inline matrix_& set_identity() inline matrix_& set_identity()
@ -201,6 +198,14 @@ struct matrix_ : matrixbase_<T, matrix_<R, C, T>>
for (size_t i = 0; i < rows; i++) c[i] = (*this)(i,col_); for (size_t i = 0; i < rows; i++) c[i] = (*this)(i,col_);
return c; 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 <> inline template <> inline

View file

@ -39,7 +39,7 @@ namespace pw {
template <typename T, typename Derived> template <typename T, typename Derived>
struct matrixbase_ { struct matrixbase_ {
typedef T value_type; using value_type = T;
Derived& derived() { return static_cast<Derived&>(*this); } Derived& derived() { return static_cast<Derived&>(*this); }
const Derived& derived() const { return static_cast<const Derived&>(*this); } const Derived& derived() const { return static_cast<const Derived&>(*this); }

View file

@ -33,12 +33,20 @@ namespace pw {
/** /**
* @brief entity relations are hidden and managed by the entity itself * @brief entity relations are hidden and managed by the entity itself
*/ */
struct relationship { struct parent {
relationship() = default; parent() = default;
relationship(const relationship&) = default; parent(const parent&) = default;
std::vector<entt::entity> children; entt::entity entity { entt::null };
entt::entity parent { entt::null };
operator bool() const { return entity != entt::null; }
};
struct children {
children() = default;
children(const children&) = default;
std::vector<entt::entity> entities;
}; };

View file

@ -9,58 +9,52 @@ namespace pw {
struct transform { struct transform {
transform() = default;
transform(const transform&) = default;
inline const matrix4x4& local() const { return _local; } inline const matrix4x4& local() const { return _local; }
void set_local(const matrix4x4 &local) void set_local(const matrix4x4 &local)
{ {
_local = local; _local = local;
update_global_from_local();
// TODO need to rebuild the transforms: both -> global down and global up
} }
inline const matrix4x4& global() const { return _global; } inline const matrix4x4& global() const { return _global; }
void set_global(const matrix4x4 &global) void set_global(const matrix4x4 &global)
{ {
matrix4x4 diff = _global.inverse() * global;
_local = _local * diff;
_global = global; _global = global;
_global_inverse = global.inverse();
update_local_from_global();
} }
inline const matrix4x4& global_inverse() const { return _global_inverse; }
inline transform& translate(const real_t &x, const real_t &y, const real_t &z) { inline transform& translate(const real_t &x, const real_t &y, const real_t &z) {
_local(0,3) += x;_local(1,3) += y;_local(2,3) += z; _local(0,3) += x;_local(1,3) += y;_local(2,3) += z;
update_global_from_local();
return *this; return *this;
} }
inline transform& set_translation(const real_t &x, const real_t &y, const real_t &z) { inline transform& set_translation(const real_t &x, const real_t &y, const real_t &z) {
_local(0,3) = x;_local(1,3) = y;_local(2,3) = z; _local(0,3) = x;_local(1,3) = y;_local(2,3) = z;
update_global_from_local();
return *this; return *this;
} }
inline transform& rotate(const quaternion& q) { inline transform& rotate(const quaternion& q) {
_local = _local * q.to_matrix(); _local = _local * q.to_matrix();
update_global_from_local();
return *this; return *this;
} }
inline transform& set_rotation(const quaternion& q) { inline transform& set_rotation(const quaternion& q) {
_local = q.to_matrix(); _local = q.to_matrix();
update_global_from_local();
return *this; return *this;
} }
inline transform& scale(const real_t &sx, const real_t &sy, const real_t &sz) { inline transform& scale(const real_t &sx, const real_t &sy, const real_t &sz) {
_local(0,0) *= sx; _local(1,1) *= sy; _local(2,2) *= sz; _local(0,0) *= sx; _local(1,1) *= sy; _local(2,2) *= sz;
update_global_from_local();
return *this; return *this;
} }
inline transform& set_scale(const real_t &sx, const real_t &sy, const real_t &sz) { inline transform& set_scale(const real_t &sx, const real_t &sy, const real_t &sz) {
_local(0,0) = sx; _local(1,1) = sy; _local(2,2) = sz; _local(0,0) = sx; _local(1,1) = sy; _local(2,2) = sz;
update_global_from_local();
return *this; return *this;
} }
@ -68,14 +62,8 @@ struct transform {
return scale(uniform_scale,uniform_scale,uniform_scale); return scale(uniform_scale,uniform_scale,uniform_scale);
} }
matrix4x4 _local; matrix4x4 _local = matrix4x4::identity();
matrix4x4 _global; matrix4x4 _global = matrix4x4::identity();
matrix4x4 _global_inverse;
void update_global_from_local();
void update_local_from_global();
}; };
} }

View file

@ -28,6 +28,7 @@
#include <pw/core/globals.hpp> #include <pw/core/globals.hpp>
#include <entt/entt.hpp> #include <entt/entt.hpp>
namespace pw { namespace pw {
class entity; class entity;

View file

@ -43,12 +43,12 @@ bool entity::add_child(entity &child)
// TODO: check circular dependencies // TODO: check circular dependencies
// declare child relationship // declare child relationship
auto& r = get_or_create_component<relationship>(); auto& c = this->get_or_create_component<children>();
r.children.push_back(child._entity); c.entities.push_back(child._entity);
// declare parent // declare parent
auto& p_r = child.get_or_create_component<relationship>(); auto& p_r = child.get_or_create_component<parent>();
p_r.parent = _entity; p_r.entity = _entity;
return true; return true;
} }
@ -62,19 +62,19 @@ bool entity::remove_child(entity& child)
} }
// both need to have a relationship component // both need to have a relationship component
if (has_component<relationship>() && if (child.has_component<parent>() &&
child.has_component<relationship>()) this->has_component<children>())
{ {
// we need to check if the child is related to the parent // we need to check if the child is related to the parent
auto r_p = child.get_component<relationship>(); auto r_p = child.get_component<parent>();
if (r_p.parent == _entity) if (r_p.entity == _entity)
{ {
// now go ahead delete parent // now go ahead delete parent
r_p.parent = entt::null; r_p.entity = entt::null;
// now remove all children // now remove all children
auto& r = this->get_component<relationship>(); auto& c = this->get_component<children>();
r.children.erase(std::remove(r.children.begin(),r.children.end(),child._entity)); c.entities.erase(std::remove(c.entities.begin(),c.entities.end(),child._entity));
// flag success // flag success
return true; return true;
@ -83,10 +83,11 @@ bool entity::remove_child(entity& child)
return false; return false;
} }
size_t entity::child_count() const size_t entity::child_count() const
{ {
return has_component<relationship>() ? return this->has_component<children>() ?
get_component<relationship>().children.size() : get_component<children>().entities.size() :
0; 0;
} }

View file

@ -2,6 +2,7 @@
#include "pw/scene/entity.hpp" #include "pw/scene/entity.hpp"
#include "pw/core/debug.hpp" #include "pw/core/debug.hpp"
#include "pw/core/serialize.hpp"
namespace pw { namespace pw {
@ -23,35 +24,67 @@ size_t scene::count_alive_enties() const
void scene::update_transforms() void scene::update_transforms()
{ {
#if 0 #if 1
auto view = _registry->view<transform,relationship>(); // search for nodes with parent and transform (only find leaf nodes)
auto view = _registry->view<transform,parent>(entt::exclude<children>);
for (auto entity : view) for (auto entity : view)
{ {
auto [t,r] = view.get<transform,relationship>(entity); debug::d() << "info for entity " << (int)entity;
} //auto [t,r] = view.get<transform,parent>(entity);
#endif // collect node path
std::vector<transform> path;
while (_registry->has<parent>(entity)) {
if (_registry->has<transform>(entity)) {
path.push_back(_registry->get<transform>(entity));
}
entity = _registry->get<parent>(entity).entity;
auto view = _registry->view<relationship>();
for (auto e : view) {
const auto& r = view.get<relationship>(e);
if (r.children.size() && r.parent == entt::null) {
debug::d() << "root";
} }
// debug::d() << __PRETTY_FUNCTION__ << " " << view.get<relationship>(e).children.size();
// if debug::d() << "\tpath length " << path.size();
std::reverse(path.begin(),path.end());
auto m = pw::matrix4x4::identity();
for (auto& transform : path) {
transform._global = transform._local * m;
m = transform._global;
debug::d() << pw::serialize::matrix(m);
}
// r = _registry->view<relationship>
} }
#else
// auto view = _registry->view<relationship>();
// for (auto e : view) {
// const auto& r = view.get<relationship>(e);
// if (r.children.size() && r.parent == entt::null) {
// debug::d() << "root '" << (int)e << "'";
// }
//// debug::d() << __PRETTY_FUNCTION__ << " " << view.get<relationship>(e).children.size();
//// if
// }
#endif
// auto vr = _registry->view<relationship>(); // auto vr = _registry->view<relationship>();
// for (auto [rel] : vr) { // for (auto [rel] : vr) {

View file

@ -43,6 +43,12 @@ void test_stack()
e2.add_component<pw::transform>(); e2.add_component<pw::transform>();
e3.add_component<pw::transform>(); e3.add_component<pw::transform>();
auto e22 = entity{s};
e22.add_component<pw::transform>().set_scale(.5,.5,.5);
e2.add_child(e22);
e2.get_component<pw::transform>().set_translation(10,20,40);
std::cout << e.child_count() << std::endl; std::cout << e.child_count() << std::endl;
s.update_transforms(); s.update_transforms();

View file

@ -26,6 +26,10 @@ struct texture::impl {
case data_layout::shape_3d: case data_layout::shape_3d:
return GL_TEXTURE_3D; return GL_TEXTURE_3D;
} }
debug::e() << __PRETTY_FUNCTION__ << " unknown texture layout";
return 0;
} }
void create() void create()