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
|
stream& operator << (const void *value); ///! pointer
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
debug* _log;
|
debug* _log;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue