working ECS base
This commit is contained in:
parent
f3c17f6d03
commit
4078cdea8f
8 changed files with 104 additions and 23 deletions
34
README.md
34
README.md
|
@ -1,6 +1,34 @@
|
||||||
pixwerx
|
# pixwerx
|
||||||
-------
|
|
||||||
|
pixwerx is an opinionated, academic approach to a 3D engine. It tries to mix
|
||||||
|
modern andproven methods to build a fast and portable engine beyond pure 3D.
|
||||||
|
|
||||||
|
## Design Principles
|
||||||
|
|
||||||
|
Dogdooding: pixwerx is built on the principle of dogfooding. The engine is a
|
||||||
|
full-stack system that tries to implement all necessary functions. The engine
|
||||||
|
editor is just a UI build with the engine.
|
||||||
|
|
||||||
|
Reasonable dependencies: like many engines pixwerx tries to include as much 3rd-
|
||||||
|
party code as possible and implements some of the core systems itself.
|
||||||
|
|
||||||
|
No premature optimization: pixwerx implements only very few systems with machine
|
||||||
|
code. It tries to utilize the power of the compiler as much as possible.
|
||||||
|
|
||||||
|
Computer graphics 101: pixwerx does implement graphics components and systems in
|
||||||
|
a way that makes code portable and not over-parameterized. Usability is
|
||||||
|
achieved through layers on top of the core components.
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
pixwerx is licenced under the terms of the MIT License. Please consult the
|
||||||
|
LICENSE file.
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
© 1999-2020 Hartmut Seichter
|
||||||
|
|
||||||
|
|
||||||
an academic approach to a 3D engine
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,8 @@ void register_core_function(sol::state& lua,sol::table& ns)
|
||||||
// , "line_strip", geometry::topology_type::line_strip
|
// , "line_strip", geometry::topology_type::line_strip
|
||||||
// );
|
// );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ns.new_usertype<image>("image"
|
ns.new_usertype<image>("image"
|
||||||
, sol::constructors<image()>()
|
, sol::constructors<image()>()
|
||||||
,"create",&image::create
|
,"create",&image::create
|
||||||
|
|
|
@ -26,6 +26,7 @@ void register_scene_function(sol::state&,sol::table &ns)
|
||||||
ns.new_usertype<entity>("entity"
|
ns.new_usertype<entity>("entity"
|
||||||
,sol::constructors<entity(),entity(const entity&),entity(scene&)>()
|
,sol::constructors<entity(),entity(const entity&),entity(scene&)>()
|
||||||
,"add_child",&entity::add_child
|
,"add_child",&entity::add_child
|
||||||
|
,"remove_child",&entity::remove_child
|
||||||
,"child_count",sol::readonly_property(&entity::child_count)
|
,"child_count",sol::readonly_property(&entity::child_count)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <entt/entt.hpp>
|
|
||||||
|
|
||||||
namespace pw {
|
namespace pw {
|
||||||
|
|
||||||
class entity {
|
class entity {
|
||||||
|
@ -43,46 +41,85 @@ public:
|
||||||
entity(scene& s);
|
entity(scene& s);
|
||||||
~entity();
|
~entity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* adds a component
|
||||||
|
*/
|
||||||
template <typename T,typename... Args>
|
template <typename T,typename... Args>
|
||||||
[[nodiscard]] T& add_component(Args&&... args) {
|
[[nodiscard]] T& add_component(Args&&... args) {
|
||||||
return _registry->emplace<T>(this->_entity,std::forward<Args>(args)...);
|
return _registry->emplace<T>(this->_entity,std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* removes a component
|
||||||
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void remove_component() {
|
void remove_component() {
|
||||||
_registry->remove<T>(_entity);
|
_registry->remove<T>(_entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns a component
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
[[nodiscard]] T& get_component() const {
|
[[nodiscard]] T& get_component() const {
|
||||||
return _registry->get<T>(this->_entity);
|
return _registry->get<T>(this->_entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets or creates a component
|
||||||
|
*/
|
||||||
template <typename T,typename... Args>
|
template <typename T,typename... Args>
|
||||||
T& get_or_create_component(Args&&... args) {
|
[[nodiscard]] T& get_or_create_component(Args&&... args) {
|
||||||
return _registry->get_or_emplace<T>(this->_entity,std::forward<Args>(args)...);
|
return _registry->get_or_emplace<T>(this->_entity,std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if this entity contains a component
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool has_component() const { return _registry->has<T>(_entity);}
|
bool has_component() const { return _registry->has<T>(_entity);}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief destroy
|
||||||
|
*/
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
operator bool() const { return _registry && _entity != entt::null; }
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief conversion to an entt entity
|
||||||
|
*/
|
||||||
operator std::uint32_t() const { return static_cast<std::uint32_t>(_entity); }
|
operator std::uint32_t() const { return static_cast<std::uint32_t>(_entity); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief checks if this entity is valid
|
||||||
|
* @return true of it belongs to a scene already
|
||||||
|
*/
|
||||||
bool valid() const { return _registry && _registry->valid(_entity); }
|
bool valid() const { return _registry && _registry->valid(_entity); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
operator bool() const { return _registry && _entity != entt::null; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief adds another child entity to this entity -> establishing a
|
* @brief adds another child entity to this entity -> establishing a
|
||||||
* @param child
|
* @param child
|
||||||
|
* @return true if the given child could be added to the hierarchy
|
||||||
*/
|
*/
|
||||||
bool add_child(entity &child);
|
bool add_child(entity &child);
|
||||||
|
|
||||||
void remove_child(entity &child);
|
/**
|
||||||
|
* @brief remove child entity from this parent
|
||||||
|
* @param child
|
||||||
|
* @return true if the given child could be remove from the hierarchy
|
||||||
|
*/
|
||||||
|
bool remove_child(entity &child);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief returns the number of children on this entity
|
||||||
|
* @return number of children
|
||||||
|
*/
|
||||||
size_t child_count() const;
|
size_t child_count() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -39,7 +39,10 @@ public:
|
||||||
projection(node &host);
|
projection(node &host);
|
||||||
|
|
||||||
void set_matrix(const matrix4x4 &projection);
|
void set_matrix(const matrix4x4 &projection);
|
||||||
const matrix4x4& matrix() const;
|
const matrix4x4& matrix() const
|
||||||
|
{
|
||||||
|
return _m;
|
||||||
|
}
|
||||||
|
|
||||||
void set_frustum(real_t left,
|
void set_frustum(real_t left,
|
||||||
real_t right,
|
real_t right,
|
||||||
|
|
|
@ -7,7 +7,6 @@ namespace pw {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
|
||||||
// entity relationsships are hidden
|
// entity relationsships are hidden
|
||||||
struct relationship {
|
struct relationship {
|
||||||
relationship() = default;
|
relationship() = default;
|
||||||
|
@ -25,7 +24,7 @@ entity::entity(scene &s)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool entity::add_child(entity& child)
|
bool entity::add_child(entity &child)
|
||||||
{
|
{
|
||||||
// not mixing scenes (yet)
|
// not mixing scenes (yet)
|
||||||
if (child._registry != this->_registry) {
|
if (child._registry != this->_registry) {
|
||||||
|
@ -46,12 +45,12 @@ bool entity::add_child(entity& child)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void entity::remove_child(entity& child)
|
bool entity::remove_child(entity& child)
|
||||||
{
|
{
|
||||||
// not mixing scenes (yet)
|
// not mixing scenes (yet)
|
||||||
if (child._registry != this->_registry) {
|
if (child._registry != this->_registry) {
|
||||||
debug::e() << "Cannot mix entities from different scenes";
|
debug::e() << "Cannot mix entities from different scenes";
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// both need to have a relationship component
|
// both need to have a relationship component
|
||||||
|
@ -62,13 +61,18 @@ void entity::remove_child(entity& child)
|
||||||
auto r_p = child.get_component<detail::relationship>();
|
auto r_p = child.get_component<detail::relationship>();
|
||||||
if (r_p.parent == _entity)
|
if (r_p.parent == _entity)
|
||||||
{
|
{
|
||||||
// now go ahead
|
// now go ahead delete parent
|
||||||
r_p.parent = entt::null;
|
r_p.parent = entt::null;
|
||||||
|
|
||||||
auto r = get_component<detail::relationship>();
|
// now remove all children
|
||||||
std::remove(r.children.begin(),r.children.end(),child._entity);
|
auto& r = this->get_component<detail::relationship>();
|
||||||
|
r.children.erase(std::remove(r.children.begin(),r.children.end(),child._entity));
|
||||||
|
|
||||||
|
// flag success
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t entity::child_count() const
|
size_t entity::child_count() const
|
||||||
|
|
|
@ -31,10 +31,7 @@ void projection::set_matrix(const matrix4x4 &projection)
|
||||||
// real_t fov_raw = float( atan (top / near_)) * * 2.0f;
|
// real_t fov_raw = float( atan (top / near_)) * * 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
const matrix4x4 &projection::matrix() const
|
|
||||||
{
|
|
||||||
return _m;
|
|
||||||
}
|
|
||||||
|
|
||||||
void projection::set_frustum(real_t left, real_t right, real_t top, real_t bottom)
|
void projection::set_frustum(real_t left, real_t right, real_t top, real_t bottom)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,17 +11,26 @@ local s = pw.scene.new()
|
||||||
print(s)
|
print(s)
|
||||||
|
|
||||||
local e = pw.entity.new(s)
|
local e = pw.entity.new(s)
|
||||||
c = pw.entity.new(s)
|
local c = pw.entity.new(s)
|
||||||
|
|
||||||
print(e)
|
print(e)
|
||||||
|
print(c)
|
||||||
print(e.child_count)
|
print(e.child_count)
|
||||||
|
|
||||||
-- add child
|
-- add child
|
||||||
e.add_child(c)
|
e:add_child(c)
|
||||||
|
|
||||||
|
|
||||||
print(e.child_count)
|
print(e.child_count)
|
||||||
|
|
||||||
|
if e:remove_child(c) then
|
||||||
|
print("remove_child success")
|
||||||
|
else
|
||||||
|
print("remove_child fail")
|
||||||
|
end
|
||||||
|
|
||||||
|
print(e.child_count)
|
||||||
|
|
||||||
|
|
||||||
print("bye, bye pixwerx!")
|
print("bye, bye pixwerx!")
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue