WiP for proper support of ECS - figuring out how to use transformations in a ECS
This commit is contained in:
parent
1c5b74454f
commit
a4f9308aa7
10 changed files with 107 additions and 60 deletions
|
@ -75,6 +75,7 @@ public:
|
|||
|
||||
stream& operator << (const void *value); ///! pointer
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
debug* _log;
|
||||
|
|
|
@ -70,9 +70,6 @@ struct matrix_ : matrixbase_<T, matrix_<R, C, T>>
|
|||
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 {
|
||||
return (RowMajor) ? r * C + c : c * R + r;
|
||||
}
|
||||
|
@ -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_);
|
||||
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
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace pw {
|
|||
template <typename T, typename Derived>
|
||||
struct matrixbase_ {
|
||||
|
||||
typedef T value_type;
|
||||
using value_type = T;
|
||||
|
||||
Derived& derived() { return static_cast<Derived&>(*this); }
|
||||
const Derived& derived() const { return static_cast<const Derived&>(*this); }
|
||||
|
|
|
@ -33,12 +33,20 @@ namespace pw {
|
|||
/**
|
||||
* @brief entity relations are hidden and managed by the entity itself
|
||||
*/
|
||||
struct relationship {
|
||||
relationship() = default;
|
||||
relationship(const relationship&) = default;
|
||||
struct parent {
|
||||
parent() = default;
|
||||
parent(const parent&) = default;
|
||||
|
||||
std::vector<entt::entity> children;
|
||||
entt::entity parent { entt::null };
|
||||
entt::entity entity { entt::null };
|
||||
|
||||
operator bool() const { return entity != entt::null; }
|
||||
};
|
||||
|
||||
struct children {
|
||||
children() = default;
|
||||
children(const children&) = default;
|
||||
|
||||
std::vector<entt::entity> entities;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -9,58 +9,52 @@ namespace pw {
|
|||
|
||||
struct transform {
|
||||
|
||||
transform() = default;
|
||||
transform(const transform&) = default;
|
||||
|
||||
inline const matrix4x4& local() const { return _local; }
|
||||
void set_local(const matrix4x4 &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; }
|
||||
|
||||
void set_global(const matrix4x4 &global)
|
||||
{
|
||||
matrix4x4 diff = _global.inverse() * global;
|
||||
_local = _local * diff;
|
||||
|
||||
_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) {
|
||||
_local(0,3) += x;_local(1,3) += y;_local(2,3) += z;
|
||||
update_global_from_local();
|
||||
return *this;
|
||||
}
|
||||
|
||||
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;
|
||||
update_global_from_local();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline transform& rotate(const quaternion& q) {
|
||||
_local = _local * q.to_matrix();
|
||||
update_global_from_local();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline transform& set_rotation(const quaternion& q) {
|
||||
_local = q.to_matrix();
|
||||
update_global_from_local();
|
||||
return *this;
|
||||
}
|
||||
|
||||
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;
|
||||
update_global_from_local();
|
||||
return *this;
|
||||
}
|
||||
|
||||
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;
|
||||
update_global_from_local();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -68,14 +62,8 @@ struct transform {
|
|||
return scale(uniform_scale,uniform_scale,uniform_scale);
|
||||
}
|
||||
|
||||
matrix4x4 _local;
|
||||
matrix4x4 _global;
|
||||
|
||||
matrix4x4 _global_inverse;
|
||||
|
||||
void update_global_from_local();
|
||||
|
||||
void update_local_from_global();
|
||||
matrix4x4 _local = matrix4x4::identity();
|
||||
matrix4x4 _global = matrix4x4::identity();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <pw/core/globals.hpp>
|
||||
#include <entt/entt.hpp>
|
||||
|
||||
|
||||
namespace pw {
|
||||
|
||||
class entity;
|
||||
|
|
|
@ -43,12 +43,12 @@ bool entity::add_child(entity &child)
|
|||
// TODO: check circular dependencies
|
||||
|
||||
// declare child relationship
|
||||
auto& r = get_or_create_component<relationship>();
|
||||
r.children.push_back(child._entity);
|
||||
auto& c = this->get_or_create_component<children>();
|
||||
c.entities.push_back(child._entity);
|
||||
|
||||
// declare parent
|
||||
auto& p_r = child.get_or_create_component<relationship>();
|
||||
p_r.parent = _entity;
|
||||
auto& p_r = child.get_or_create_component<parent>();
|
||||
p_r.entity = _entity;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -62,19 +62,19 @@ bool entity::remove_child(entity& child)
|
|||
}
|
||||
|
||||
// both need to have a relationship component
|
||||
if (has_component<relationship>() &&
|
||||
child.has_component<relationship>())
|
||||
if (child.has_component<parent>() &&
|
||||
this->has_component<children>())
|
||||
{
|
||||
// we need to check if the child is related to the parent
|
||||
auto r_p = child.get_component<relationship>();
|
||||
if (r_p.parent == _entity)
|
||||
auto r_p = child.get_component<parent>();
|
||||
if (r_p.entity == _entity)
|
||||
{
|
||||
// now go ahead delete parent
|
||||
r_p.parent = entt::null;
|
||||
r_p.entity = entt::null;
|
||||
|
||||
// now remove all children
|
||||
auto& r = this->get_component<relationship>();
|
||||
r.children.erase(std::remove(r.children.begin(),r.children.end(),child._entity));
|
||||
auto& c = this->get_component<children>();
|
||||
c.entities.erase(std::remove(c.entities.begin(),c.entities.end(),child._entity));
|
||||
|
||||
// flag success
|
||||
return true;
|
||||
|
@ -83,10 +83,11 @@ bool entity::remove_child(entity& child)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
size_t entity::child_count() const
|
||||
{
|
||||
return has_component<relationship>() ?
|
||||
get_component<relationship>().children.size() :
|
||||
return this->has_component<children>() ?
|
||||
get_component<children>().entities.size() :
|
||||
0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "pw/scene/entity.hpp"
|
||||
|
||||
#include "pw/core/debug.hpp"
|
||||
#include "pw/core/serialize.hpp"
|
||||
|
||||
namespace pw {
|
||||
|
||||
|
@ -23,35 +24,67 @@ size_t scene::count_alive_enties() const
|
|||
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)
|
||||
{
|
||||
auto [t,r] = view.get<transform,relationship>(entity);
|
||||
debug::d() << "info for entity " << (int)entity;
|
||||
|
||||
//auto [t,r] = view.get<transform,parent>(entity);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
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 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
|
||||
}
|
||||
|
||||
// auto vr = _registry->view<relationship>();
|
||||
|
||||
// for (auto [rel] : vr) {
|
||||
|
|
|
@ -43,6 +43,12 @@ void test_stack()
|
|||
e2.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;
|
||||
|
||||
s.update_transforms();
|
||||
|
|
|
@ -26,6 +26,10 @@ struct texture::impl {
|
|||
case data_layout::shape_3d:
|
||||
return GL_TEXTURE_3D;
|
||||
}
|
||||
|
||||
debug::e() << __PRETTY_FUNCTION__ << " unknown texture layout";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void create()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue