From 48256ca39eb6650c009c6f91769685ff63dfa75d Mon Sep 17 00:00:00 2001 From: turanszkij Date: Sat, 1 Sep 2018 16:16:46 +0100 Subject: [PATCH] simplified component manager, removed ref type --- Editor/CameraWindow.cpp | 12 +- Editor/Editor.cpp | 5 +- Editor/LightWindow.cpp | 6 +- WickedEngine/wiECS.h | 198 ++++++++++----------------------- WickedEngine/wiRenderer.cpp | 11 +- WickedEngine/wiRenderer.h | 4 +- WickedEngine/wiSceneSystem.cpp | 11 +- WickedEngine/wiSceneSystem.h | 16 +-- 8 files changed, 80 insertions(+), 183 deletions(-) diff --git a/Editor/CameraWindow.cpp b/Editor/CameraWindow.cpp index 13d7ea294..527caf3a0 100644 --- a/Editor/CameraWindow.cpp +++ b/Editor/CameraWindow.cpp @@ -106,13 +106,9 @@ CameraWindow::CameraWindow(wiGUI* gui) :GUI(gui) Entity proxy = CreateEntity(); - auto name_ref = scene.names.Create(proxy); - auto transform_ref = scene.transforms.Create(proxy); - auto camera_ref = scene.cameras.Create(proxy); - - auto& name = scene.names.GetComponent(name_ref); - auto& transform = scene.transforms.GetComponent(transform_ref); - auto& camera = scene.cameras.GetComponent(camera_ref); + auto& name = scene.names.Create(proxy); + auto& transform = scene.transforms.Create(proxy); + auto& camera = scene.cameras.Create(proxy); name = "cam"; camera = *wiRenderer::getCamera(); @@ -166,7 +162,7 @@ void CameraWindow::SetEntity(Entity entity) Scene& scene = wiRenderer::GetScene(); - if (scene.cameras.Find(entity)) + if (scene.cameras.GetComponent(entity) != nullptr) { followCheckBox->SetEnabled(true); followSlider->SetEnabled(true); diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index f536ea198..9a0a5fd59 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -1082,11 +1082,10 @@ void EditorComponent::Update(float dt) else { // Orbital Camera - auto parented = scene.parents.Find(wiRenderer::getCameraID()); - + ParentComponent* parented = scene.parents.GetComponent(wiRenderer::getCameraID()); TransformComponent* target_transform = scene.transforms.GetComponent(cameraWnd->target); - if (!parented) + if (parented == nullptr) { //cam->attachTo(cameraWnd->orbitalCamTarget); scene.Component_Attach(wiRenderer::getCameraID(), cameraWnd->target); diff --git a/Editor/LightWindow.cpp b/Editor/LightWindow.cpp index 322f8db8c..107bc9fe3 100644 --- a/Editor/LightWindow.cpp +++ b/Editor/LightWindow.cpp @@ -168,16 +168,14 @@ LightWindow::LightWindow(wiGUI* gui) : GUI(gui) scene.owned_entities.insert(newEntity); - auto ref_light = scene.lights.Create(newEntity); - LightComponent& light = scene.lights.GetComponent(ref_light); + LightComponent& light = scene.lights.Create(newEntity); light.energy = 2; light.range = 60; light.fov = XM_PIDIV4; light.color = XMFLOAT3(1, 1, 1); light.SetType(LightComponent::POINT); - auto ref_transform = scene.transforms.Create(newEntity); - TransformComponent& transform = scene.transforms.GetComponent(ref_transform); + TransformComponent& transform = scene.transforms.Create(newEntity); transform.Translate(XMFLOAT3(0, 3, 0)); scene.cullables.Create(newEntity); diff --git a/WickedEngine/wiECS.h b/WickedEngine/wiECS.h index 65b507e36..da637f400 100644 --- a/WickedEngine/wiECS.h +++ b/WickedEngine/wiECS.h @@ -27,183 +27,105 @@ namespace wiECS components.reserve(reservedCount); entities.reserve(reservedCount); lookup.reserve(reservedCount); - indices.reserve(reservedCount); } - // The ref is an indirection to the components. Components will be moved around to remain compacted, but ref will always be able to reference a component. - struct ref - { - size_t value = ~0; - - inline ref operator=(ref other) { value = other.value; return *this; } - inline bool operator==(ref other) const { return value == other.value; } - inline bool operator!=(ref other) const { return value != other.value; } - inline ref& operator++() { value++; return *this; } - inline ref operator++(int v) { ref temp = *this; ++*this; return temp; } - inline ref& operator--() { value--; return *this; } - inline ref operator--(int v) { ref temp = *this; --*this; return temp; } - inline operator bool() const { return value != ~0; } - }; - - // Clear the whole container, invalidate all refs + // Clear the whole container inline void Clear() { components.clear(); entities.clear(); lookup.clear(); - indices.clear(); dead.clear(); } - // Check if an ref is referencing a component or not (ref is safe but uses indirection): - inline bool IsValid(ref it) const - { - return it.value < indices.size() && indices[it.value] < components.size(); - } - - // Check if an ref is referencing a specific entity or not (ref is safe but uses indirection): - inline bool IsValid(ref it, Entity entity) const - { - assert(entities.size() == components.size()); - return IsValid(it) && entities[indices[it.value]] == entity; - } - - // Create a new component and retrieve ref (ref is safe but uses indirection): - inline ref Create(Entity entity) + // Create a new component and retrieve a reference to it: + inline T& Create(Entity entity) { // Only one of this component type per entity is allowed! - assert(!IsValid(Find(entity))); - - ref it; - - if (dead.empty()) - { - // There are no dead elements, so we must have the same amount of components as indices: - assert(components.size() == indices.size()); - - // Any new component and index will just be pushed onto the end: - it.value = components.size(); - indices.push_back(it.value); - } - else - { - // We have dead elements, which means components was popped, but indices only swapped, so there must be less components than indices: - assert(components.size() < indices.size()); - - // Essentially we pop the last dead ref and update its value to the new component (that will always be pushed to the end of components): - it = dead.back(); - dead.pop_back(); - indices[it.value] = components.size(); - } + assert(lookup.find(entity) == lookup.end()); // Entity count must always be the same as the number of coponents! assert(entities.size() == components.size()); assert(lookup.size() == components.size()); + // Update the entity lookup table: + lookup[entity] = components.size(); + // New components are always pushed to the end: components.push_back(T()); // Also push corresponding entity: entities.push_back(entity); - // Update the entity lookup table: - lookup[entity] = it; - - return it; + return components.back(); } - // Remove a component of a certain entity if it exists (referencing by Entity involves multiple indirection): + // Remove a component of a certain entity if it exists: inline void Remove(Entity entity) - { - ref it = Find(entity); - if (IsValid(it, entity)) - { - Remove(it); - } - } - - // Remove a component referenced by a certain ref (ref is safe but uses indirection): - inline void Remove(ref it) - { - // ref should be valid: - assert(IsValid(it)); - - // Directly index into components and entities array: - const size_t index = indices[it.value]; - - // Remove the corresponding entry from the lookup table: - const Entity entity = entities[index]; - lookup.erase(entity); - - // Swap out the dead element with the last one, and shrink the container: - components[index] = std::move(components.back()); // try to use move instead of copy - components.pop_back(); - entities[index] = entities.back(); - entities.pop_back(); - - // Because the last element of the container was moved to the position of the removed element, we update its ref accordingly: - indices[components.size()] = index; - - //The current ref is marked as dead: - indices[it.value] = ~0; - dead.push_back(it); - } - - // Swap two components' data that are referenced by refs (ref is safe but uses indirection): - inline void Swap(ref a, ref b) - { - const size_t index_a = indices[a.value]; - const size_t index_b = indices[b.value]; - - const size_t index_tmp = index_a; - const Entity entity_tmp = entities[index_a]; - const T component_tmp = std::move(components[index_a]); - - indices[a.value] = index_b; - entities[index_a] = entities[index_b]; - components[index_a] = std::move(components[index_b]); - - indices[b.value] = index_tmp; - entities[index_b] = entity_tmp; - components[index_b] = std::move(component_tmp); - } - - // Find a specific component of a certain entity if exists (referencing by Entity involves multiple indirection): - inline ref Find(Entity entity) const { auto it = lookup.find(entity); if (it != lookup.end()) { - return it->second; + // Directly index into components and entities array: + const size_t index = it->second; + + // Remove the corresponding entry from the lookup table: + const Entity entity = entities[index]; + lookup.erase(entity); + + if (components.size() > 1) + { + // Swap out the dead element with the last one: + components[index] = std::move(components.back()); // try to use move instead of copy + entities[index] = entities.back(); + + // Update the lookup table: + lookup[entities[index]] = index; + } + + // Shrink the container: + components.pop_back(); + entities.pop_back(); + } + } + + // Swap two components' data: + inline void Swap(Entity a, Entity b) + { + auto it_a = lookup.find(a); + auto it_b = lookup.find(b); + + if (it_a != lookup.end() && it_b != lookup.end()) + { + const size_t index_a = it_a->second; + const size_t index_b = it_b->second; + + const Entity entity_tmp = entities[index_a]; + const T component_tmp = std::move(components[index_a]); + + entities[index_a] = entities[index_b]; + components[index_a] = std::move(components[index_b]); + + entities[index_b] = entity_tmp; + components[index_b] = std::move(component_tmp); + + lookup[a] = index_b; + lookup[b] = index_a; } - return ref(); } // Retrieve a component specified by an entity (if it exists, otherwise nullptr): inline T* GetComponent(Entity entity) { - ref it = Find(entity); - if (IsValid(it, entity)) + auto it = lookup.find(entity); + if (it != lookup.end()) { - return &components[indices[it.value]]; + return &components[it->second]; } return nullptr; } - // Retrieve a component specified by an ref (ref is safe but uses indirection): - inline T& GetComponent(ref it) - { - assert(IsValid(it)); - return components[indices[it.value]]; - } - // Retrieve an entity specified by an ref (ref is safe but uses indirection): - inline Entity GetEntity(ref it) const - { - assert(IsValid(it)); - return entities[indices[it.value]]; - } - // Retrieve the number of existing entries: inline size_t GetCount() const { return components.size(); } @@ -225,11 +147,7 @@ namespace wiECS // This is a linear array of entities corresponding to each alive component: std::vector entities; // This is a lookup table for entities: - std::unordered_map lookup; - // This is the indirection of ref->component index: - std::vector indices; - // The indices will also contain dead elements, and those are saved here: - std::vector dead; + std::unordered_map lookup; }; } diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index bc6c83fa0..8ccec99f4 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -7969,7 +7969,7 @@ wiRenderer::RayIntersectWorldResult wiRenderer::RayIntersectWorld(const RAY& ray return result; } -ComponentManager::ref wiRenderer::LoadModel(const std::string& fileName, const XMMATRIX& transform) +Entity wiRenderer::LoadModel(const std::string& fileName, const XMMATRIX& transform) { //Model* model = nullptr; @@ -7991,7 +7991,7 @@ ComponentManager::ref wiRenderer::LoadModel(const std::string& f //return model; - return ComponentManager::ref(); + return INVALID_ENTITY; } void wiRenderer::LoadWorldInfo(const std::string& fileName) { @@ -8072,9 +8072,8 @@ Scene& wiRenderer::GetScene() { scene = new Scene; - auto transform_ref = scene->transforms.Create(cameraID); - auto camera_ref = scene->cameras.Create(cameraID); - scene->cameras.GetComponent(camera_ref).CreatePerspective((float)wiRenderer::GetInternalResolution().x, (float)wiRenderer::GetInternalResolution().y, 0.1f, 800); + scene->transforms.Create(cameraID); + scene->cameras.Create(cameraID).CreatePerspective((float)wiRenderer::GetInternalResolution().x, (float)wiRenderer::GetInternalResolution().y, 0.1f, 800); } return *scene; } @@ -8165,7 +8164,7 @@ void wiRenderer::PutEnvProbe(const XMFLOAT3& position) //GetScene().GetWorldNode()->environmentProbes.push_back(probe); } -void wiRenderer::CreateImpostor(ComponentManager::ref mesh_ref, GRAPHICSTHREAD threadID) +void wiRenderer::CreateImpostor(Entity entity, GRAPHICSTHREAD threadID) { //MeshComponent& mesh = GetScene().meshes.GetComponent(mesh_ref); diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index b1e704cc0..214ab9a74 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -500,12 +500,12 @@ public: static void SetOceanEnabled(bool enabled, const wiOceanParameter& params); static wiOcean* GetOcean() { return ocean; } - static wiECS::ComponentManager::ref LoadModel(const std::string& fileName, const XMMATRIX& transform = XMMatrixIdentity()); + static wiECS::Entity LoadModel(const std::string& fileName, const XMMATRIX& transform = XMMatrixIdentity()); static void LoadWorldInfo(const std::string& fileName); static void PutEnvProbe(const XMFLOAT3& position); - static void CreateImpostor(wiECS::ComponentManager::ref mesh_ref, GRAPHICSTHREAD threadID); + static void CreateImpostor(wiECS::Entity, GRAPHICSTHREAD threadID); static std::vector> renderableBoxes; // Add box to render in next frame diff --git a/WickedEngine/wiSceneSystem.cpp b/WickedEngine/wiSceneSystem.cpp index e2de7d6d6..96526aaf0 100644 --- a/WickedEngine/wiSceneSystem.cpp +++ b/WickedEngine/wiSceneSystem.cpp @@ -591,19 +591,18 @@ namespace wiSceneSystem { assert(entity != parent); - auto it = parents.Find(entity); + ParentComponent* parentcomponent = parents.GetComponent(entity); - if (!it) + if (parentcomponent == nullptr) { - it = parents.Create(entity); + parentcomponent = &parents.Create(entity); } - ParentComponent& parentcomponent = parents.GetComponent(it); TransformComponent* transformcomponent = transforms.GetComponent(parent); assert(transformcomponent != nullptr); - parentcomponent.parentID = parent; - XMStoreFloat4x4(&parentcomponent.world_parent_bind, XMMatrixInverse(nullptr, XMLoadFloat4x4(&transformcomponent->world))); + parentcomponent->parentID = parent; + XMStoreFloat4x4(&parentcomponent->world_parent_bind, XMMatrixInverse(nullptr, XMLoadFloat4x4(&transformcomponent->world))); } void Scene::Component_Detach(wiECS::Entity entity) { diff --git a/WickedEngine/wiSceneSystem.h b/WickedEngine/wiSceneSystem.h index 56ea2df41..9e0ab3f56 100644 --- a/WickedEngine/wiSceneSystem.h +++ b/WickedEngine/wiSceneSystem.h @@ -357,7 +357,7 @@ namespace wiSceneSystem struct ArmatureComponent { - std::vector::ref> boneCollection; + std::vector boneCollection; GFX_STRUCT ShaderBoneType { @@ -563,19 +563,7 @@ namespace wiSceneSystem struct ModelComponent { - - std::vector::ref> material_refs; - std::vector::ref> mesh_refs; - std::vector::ref> object_refs; - std::vector::ref> physicscomponent_refs; - std::vector::ref> cullable_refs; - std::vector::ref> bone_refs; - std::vector::ref> armature_refs; - std::vector::ref> light_refs; - std::vector::ref> probe_refs; - std::vector::ref> force_refs; - std::vector::ref> decal_refs; - std::vector::ref> camera_refs; + std::unordered_set entities; }; struct Scene