From 2ac6ba2f3b8ece5a85826bbf908ebe41901767cf Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Sun, 9 Aug 2020 22:08:29 -0700 Subject: [PATCH] Generalize model_system to render_system and add support for specifying scene layers for model components --- src/application.cpp | 9 ++- src/application.hpp | 4 +- src/entity/components/model-component.hpp | 1 + src/entity/entity-commands.cpp | 61 ++++++++++++++++++ src/entity/entity-commands.hpp | 40 ++++++++++++ src/resources/entity-archetype-loader.cpp | 1 + src/state/play-state.cpp | 34 +++++----- .../{model-system.cpp => render-system.cpp} | 62 +++++++++++++------ .../{model-system.hpp => render-system.hpp} | 16 +++-- src/systems/terrain-system.cpp | 1 + 10 files changed, 182 insertions(+), 47 deletions(-) create mode 100644 src/entity/entity-commands.cpp create mode 100644 src/entity/entity-commands.hpp rename src/systems/{model-system.cpp => render-system.cpp} (54%) rename src/systems/{model-system.hpp => render-system.hpp} (82%) diff --git a/src/application.cpp b/src/application.cpp index 26a4a31..24225f4 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -88,7 +88,7 @@ #include "systems/camera-system.hpp" #include "systems/collision-system.hpp" #include "systems/locomotion-system.hpp" -#include "systems/model-system.hpp" +#include "systems/render-system.hpp" #include "systems/nest-system.hpp" #include "systems/placement-system.hpp" #include "systems/samara-system.hpp" @@ -574,7 +574,10 @@ application::application(int argc, char** argv): behavior_system = new ::behavior_system(ecs_registry); locomotion_system = new ::locomotion_system(ecs_registry); constraint_system = new ::constraint_system(ecs_registry); - model_system = new ::model_system(ecs_registry, overworld_scene); + + render_system = new ::render_system(ecs_registry); + render_system->add_layer(&overworld_scene); + render_system->add_layer(&underworld_scene); // Setup systems systems.push_back([this](double t, double dt){ this->overworld_scene.update_tweens(); this->underworld_scene.update_tweens(); this->ui_system->get_scene()->update_tweens(); focal_point_tween.update(); this->underworld_final_pass->get_material()->update_tweens(); }); @@ -601,7 +604,7 @@ application::application(int argc, char** argv): this->focal_point_tween[1] = orbit_cam.get_focal_point(); }); systems.push_back([this](double t, double dt){ this->ui_system->update(dt); }); - systems.push_back(std::bind(&model_system::update, model_system, std::placeholders::_1, std::placeholders::_2)); + systems.push_back(std::bind(&render_system::update, render_system, std::placeholders::_1, std::placeholders::_2)); systems.push_back([this](double t, double dt){ this->animator->animate(dt); }); systems.push_back([this](double t, double dt){ this->application_controls.update(); this->menu_controls.update(); this->camera_controls->update(); }); diff --git a/src/application.hpp b/src/application.hpp index bc263e5..4a8f821 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -109,7 +109,7 @@ class camera_system; class collision_system; class locomotion_system; - class model_system; + class render_system; class nest_system; class placement_system; class samara_system; @@ -328,7 +328,7 @@ private: camera_system* camera_system; collision_system* collision_system; locomotion_system* locomotion_system; - model_system* model_system; + render_system* render_system; nest_system* nest_system; placement_system* placement_system; samara_system* samara_system; diff --git a/src/entity/components/model-component.hpp b/src/entity/components/model-component.hpp index fb141cc..ec9a253 100644 --- a/src/entity/components/model-component.hpp +++ b/src/entity/components/model-component.hpp @@ -30,6 +30,7 @@ struct model_component model* model; std::unordered_map materials; int instance_count; + unsigned int layers; }; } // namespace ecs diff --git a/src/entity/entity-commands.cpp b/src/entity/entity-commands.cpp new file mode 100644 index 0000000..bd3c7b2 --- /dev/null +++ b/src/entity/entity-commands.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#include "entity-commands.hpp" +#include "entity/components/model-component.hpp" +#include "entity/components/transform-component.hpp" +#include "entity/components/copy-transform-component.hpp" + +namespace ecs { + +void move_to(entt::registry& registry, entt::entity entity, const float3& position) +{ + if (registry.has(entity)) + { + transform_component& transform = registry.get(entity); + transform.transform.translation = position; + } +} + +void warp_to(entt::registry& registry, entt::entity entity, const float3& position) +{ + if (registry.has(entity)) + { + transform_component& transform = registry.get(entity); + transform.warp = true; + } +} + +void assign_render_layers(entt::registry& registry, entt::entity entity, unsigned int layers) +{ + if (registry.has(entity)) + { + model_component model = registry.get(entity); + model.layers = layers; + registry.replace(entity, model); + } +} + +void bind_transform(entt::registry& registry, entt::entity entity, entt::entity target) +{ + copy_transform_component copy_transform = {target}; + registry.assign_or_replace(entity, copy_transform); +} + +} // namespace ecs diff --git a/src/entity/entity-commands.hpp b/src/entity/entity-commands.hpp new file mode 100644 index 0000000..b5197fd --- /dev/null +++ b/src/entity/entity-commands.hpp @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2020 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_ECS_ENTITY_COMMANDS_HPP +#define ANTKEEPER_ECS_ENTITY_COMMANDS_HPP + +#include +#include + +using namespace vmq; + +namespace ecs { + +void move_to(entt::registry& registry, entt::entity entity, const float3& position); +void warp_to(entt::registry& registry, entt::entity entity, const float3& position); + +void assign_render_layers(entt::registry& registry, entt::entity entity, unsigned int layers); + +void bind_transform(entt::registry& registry, entt::entity entity, entt::entity target); + +} // namespace ecs + +#endif // ANTKEEPER_ECS_ENTITY_COMMANDS_HPP + diff --git a/src/resources/entity-archetype-loader.cpp b/src/resources/entity-archetype-loader.cpp index 9688dcd..c2564e9 100644 --- a/src/resources/entity-archetype-loader.cpp +++ b/src/resources/entity-archetype-loader.cpp @@ -87,6 +87,7 @@ static bool load_model_component(archetype& archetype, resource_manager& resourc model_component component; component.model = resource_manager.load(filename); component.instance_count = 0; + component.layers = 1; if (!component.model) { std::string message = std::string("load_model_component(): Failed to load model \"") + filename + std::string("\""); diff --git a/src/state/play-state.cpp b/src/state/play-state.cpp index 23407b9..19a9027 100644 --- a/src/state/play-state.cpp +++ b/src/state/play-state.cpp @@ -37,6 +37,7 @@ #include "entity/components/copy-transform-component.hpp" #include "entity/components/copy-translation-component.hpp" #include "entity/archetype.hpp" +#include "entity/entity-commands.hpp" #include "nest.hpp" #include "math.hpp" #include "geometry/mesh-accelerator.hpp" @@ -65,7 +66,16 @@ void enter_play_state(application* app) ecs::archetype* forceps_archetype = resource_manager->load("forceps.ent"); ecs::archetype* larva_archetype = resource_manager->load("larva.ent"); ecs::archetype* pebble_archetype = resource_manager->load("pebble.ent"); + + ecs::archetype* flashlight_archetype = resource_manager->load("flashlight.ent"); + ecs::archetype* flashlight_light_cone_archetype = resource_manager->load("flashlight-light-cone.ent"); + // Create flashlight + light cone compund entity + auto flashlight = flashlight_archetype->create(ecs_registry); + auto flashlight_light_cone = flashlight_light_cone_archetype->create(ecs_registry); + ecs::bind_transform(ecs_registry, flashlight_light_cone, flashlight); + ecs::assign_render_layers(ecs_registry, flashlight, 2); + ecs::assign_render_layers(ecs_registry, flashlight_light_cone, 2); ecs::placement_component placement; @@ -164,18 +174,6 @@ void enter_play_state(application* app) ecs::tool_component forceps_tool_component; forceps_tool_component.active = true; ecs_registry.assign(forceps_entity, forceps_tool_component); - - - // Add copy transform constraint to ant-hill - ecs::copy_translation_component constraint; - constraint.target = forceps_entity; - constraint.use_x = true; - constraint.use_y = true; - constraint.use_z = true; - constraint.invert_x = true; - constraint.invert_y = false; - constraint.invert_z = true; - ecs_registry.assign(ant_hill_entity, constraint); app->get_scene().update_tweens(); @@ -233,15 +231,15 @@ void enter_play_state(application* app) */ // Place larva in chamber - /* { - auto larva_entity = larva_archetype->create(ecs_registry); - auto& transform = ecs_registry.get(larva_entity); - transform.transform = vmq::identity_transform; - transform.transform.translation = nest->get_shaft_position(*central_shaft, central_shaft->depth[1]); + auto larva = larva_archetype->create(ecs_registry); + ecs::assign_render_layers(ecs_registry, larva, 1); + //ecs::warp_to(ecs_registry, larva, {0, -20, 0}); + //auto& transform = ecs_registry.get(larva_entity); + //transform.transform = vmq::identity_transform; + //transform.transform.translation = nest->get_shaft_position(*central_shaft, central_shaft->depth[1]); //transform.transform.translation.y -= 1.0f; } - */ control_system* control_system = app->get_control_system(); control_system->update(0.0f); diff --git a/src/systems/model-system.cpp b/src/systems/render-system.cpp similarity index 54% rename from src/systems/model-system.cpp rename to src/systems/render-system.cpp index 5d478d1..c08dfa3 100644 --- a/src/systems/model-system.cpp +++ b/src/systems/render-system.cpp @@ -17,23 +17,24 @@ * along with Antkeeper source code. If not, see . */ -#include "model-system.hpp" +#include "render-system.hpp" #include "entity/components/transform-component.hpp" +#include using namespace ecs; -model_system::model_system(entt::registry& registry, ::scene& scene): - entity_system(registry), - scene(scene) +render_system::render_system(entt::registry& registry): + entity_system(registry) { - registry.on_construct().connect<&model_system::on_model_construct>(this); - registry.on_replace().connect<&model_system::on_model_replace>(this); - registry.on_destroy().connect<&model_system::on_model_destroy>(this); + registry.on_construct().connect<&render_system::on_model_construct>(this); + registry.on_replace().connect<&render_system::on_model_replace>(this); + registry.on_destroy().connect<&render_system::on_model_destroy>(this); } -void model_system::update(double t, double dt) +void render_system::update(double t, double dt) { - registry.view().each( + registry.view().each + ( [this](auto entity, auto& transform, auto& model) { model_instance* instance = model_instances[entity]; @@ -46,10 +47,21 @@ void model_system::update(double t, double dt) instance->update_tweens(); transform.warp = false; } - }); + } + ); +} + +void render_system::add_layer(::scene* layer) +{ + layers.push_back(layer); } -void model_system::update_model_and_materials(entt::entity entity, model_component& model) +void render_system::remove_layers() +{ + layers.clear(); +} + +void render_system::update_model_and_materials(entt::entity entity, model_component& model) { if (auto model_it = model_instances.find(entity); model_it != model_instances.end()) { @@ -60,28 +72,42 @@ void model_system::update_model_and_materials(entt::entity entity, model_compone { model_it->second->set_material(material_it->first, material_it->second); } + + // Add model instance to its specified layers + for (std::size_t i = 0; i < std::min(layers.size(), (sizeof(model.layers) << 3)); ++i) + { + layers[i]->remove_object(model_it->second); + + if ((model.layers >> i) & 1) + { + layers[i]->add_object(model_it->second); + } + } } } -void model_system::on_model_construct(entt::registry& registry, entt::entity entity, model_component& model) +void render_system::on_model_construct(entt::registry& registry, entt::entity entity, model_component& model) { - ::model_instance* model_instance = new ::model_instance(); - scene.add_object(model_instance); + ::model_instance* model_instance = new ::model_instance(); model_instances[entity] = model_instance; - update_model_and_materials(entity, model); } -void model_system::on_model_replace(entt::registry& registry, entt::entity entity, model_component& model) +void render_system::on_model_replace(entt::registry& registry, entt::entity entity, model_component& model) { update_model_and_materials(entity, model); } -void model_system::on_model_destroy(entt::registry& registry, entt::entity entity) +void render_system::on_model_destroy(entt::registry& registry, entt::entity entity) { if (auto it = model_instances.find(entity); it != model_instances.end()) { - scene.remove_object(it->second); + // Remove model instance from all layers + for (std::size_t i = 0; i < layers.size(); ++i) + { + layers[i]->remove_object(it->second); + } + delete it->second; model_instances.erase(it); } diff --git a/src/systems/model-system.hpp b/src/systems/render-system.hpp similarity index 82% rename from src/systems/model-system.hpp rename to src/systems/render-system.hpp index e16ed53..9c22d2f 100644 --- a/src/systems/model-system.hpp +++ b/src/systems/render-system.hpp @@ -17,20 +17,24 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_MODEL_SYSTEM_HPP -#define ANTKEEPER_MODEL_SYSTEM_HPP +#ifndef ANTKEEPER_RENDER_SYSTEM_HPP +#define ANTKEEPER_RENDER_SYSTEM_HPP #include "entity-system.hpp" #include "scene/scene.hpp" #include "scene/model-instance.hpp" #include "entity/components/model-component.hpp" #include +#include -class model_system: public entity_system +class render_system: public entity_system { public: - model_system(entt::registry& registry, ::scene& scene); + render_system(entt::registry& registry); virtual void update(double t, double dt); + + void add_layer(::scene* layer); + void remove_layers(); private: void update_model_and_materials(entt::entity entity, ecs::model_component& model); @@ -39,9 +43,9 @@ private: void on_model_replace(entt::registry& registry, entt::entity entity, ecs::model_component& model); void on_model_destroy(entt::registry& registry, entt::entity entity); - ::scene& scene; + std::vector layers; std::unordered_map model_instances; }; -#endif // ANTKEEPER_MODEL_SYSTEM_HPP +#endif // ANTKEEPER_RENDER_SYSTEM_HPP diff --git a/src/systems/terrain-system.cpp b/src/systems/terrain-system.cpp index a233be1..4612dd8 100644 --- a/src/systems/terrain-system.cpp +++ b/src/systems/terrain-system.cpp @@ -325,6 +325,7 @@ void terrain_system::on_terrain_construct(entt::registry& registry, entt::entity model_component model; model.model = terrain_model; model.instance_count = 0; + model.layers = 1; registry.assign_or_replace(entity, model); // Assign the entity a transform component