Browse Source

Generalize model_system to render_system and add support for specifying scene layers for model components

master
C. J. Howard 4 years ago
parent
commit
2ac6ba2f3b
10 changed files with 182 additions and 47 deletions
  1. +6
    -3
      src/application.cpp
  2. +2
    -2
      src/application.hpp
  3. +1
    -0
      src/entity/components/model-component.hpp
  4. +61
    -0
      src/entity/entity-commands.cpp
  5. +40
    -0
      src/entity/entity-commands.hpp
  6. +1
    -0
      src/resources/entity-archetype-loader.cpp
  7. +16
    -18
      src/state/play-state.cpp
  8. +44
    -18
      src/systems/render-system.cpp
  9. +10
    -6
      src/systems/render-system.hpp
  10. +1
    -0
      src/systems/terrain-system.cpp

+ 6
- 3
src/application.cpp View File

@ -88,7 +88,7 @@
#include "systems/camera-system.hpp" #include "systems/camera-system.hpp"
#include "systems/collision-system.hpp" #include "systems/collision-system.hpp"
#include "systems/locomotion-system.hpp" #include "systems/locomotion-system.hpp"
#include "systems/model-system.hpp"
#include "systems/render-system.hpp"
#include "systems/nest-system.hpp" #include "systems/nest-system.hpp"
#include "systems/placement-system.hpp" #include "systems/placement-system.hpp"
#include "systems/samara-system.hpp" #include "systems/samara-system.hpp"
@ -574,7 +574,10 @@ application::application(int argc, char** argv):
behavior_system = new ::behavior_system(ecs_registry); behavior_system = new ::behavior_system(ecs_registry);
locomotion_system = new ::locomotion_system(ecs_registry); locomotion_system = new ::locomotion_system(ecs_registry);
constraint_system = new ::constraint_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 // 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(); }); 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(); 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([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->animator->animate(dt); });
systems.push_back([this](double t, double dt){ this->application_controls.update(); this->menu_controls.update(); this->camera_controls->update(); }); systems.push_back([this](double t, double dt){ this->application_controls.update(); this->menu_controls.update(); this->camera_controls->update(); });

+ 2
- 2
src/application.hpp View File

@ -109,7 +109,7 @@
class camera_system; class camera_system;
class collision_system; class collision_system;
class locomotion_system; class locomotion_system;
class model_system;
class render_system;
class nest_system; class nest_system;
class placement_system; class placement_system;
class samara_system; class samara_system;
@ -328,7 +328,7 @@ private:
camera_system* camera_system; camera_system* camera_system;
collision_system* collision_system; collision_system* collision_system;
locomotion_system* locomotion_system; locomotion_system* locomotion_system;
model_system* model_system;
render_system* render_system;
nest_system* nest_system; nest_system* nest_system;
placement_system* placement_system; placement_system* placement_system;
samara_system* samara_system; samara_system* samara_system;

+ 1
- 0
src/entity/components/model-component.hpp View File

@ -30,6 +30,7 @@ struct model_component
model* model; model* model;
std::unordered_map<int, material*> materials; std::unordered_map<int, material*> materials;
int instance_count; int instance_count;
unsigned int layers;
}; };
} // namespace ecs } // namespace ecs

+ 61
- 0
src/entity/entity-commands.cpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<transform_component>(entity))
{
transform_component& transform = registry.get<transform_component>(entity);
transform.transform.translation = position;
}
}
void warp_to(entt::registry& registry, entt::entity entity, const float3& position)
{
if (registry.has<transform_component>(entity))
{
transform_component& transform = registry.get<transform_component>(entity);
transform.warp = true;
}
}
void assign_render_layers(entt::registry& registry, entt::entity entity, unsigned int layers)
{
if (registry.has<model_component>(entity))
{
model_component model = registry.get<model_component>(entity);
model.layers = layers;
registry.replace<model_component>(entity, model);
}
}
void bind_transform(entt::registry& registry, entt::entity entity, entt::entity target)
{
copy_transform_component copy_transform = {target};
registry.assign_or_replace<copy_transform_component>(entity, copy_transform);
}
} // namespace ecs

+ 40
- 0
src/entity/entity-commands.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_ECS_ENTITY_COMMANDS_HPP
#define ANTKEEPER_ECS_ENTITY_COMMANDS_HPP
#include <entt/entt.hpp>
#include <vmq/vmq.hpp>
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

+ 1
- 0
src/resources/entity-archetype-loader.cpp View File

@ -87,6 +87,7 @@ static bool load_model_component(archetype& archetype, resource_manager& resourc
model_component component; model_component component;
component.model = resource_manager.load<model>(filename); component.model = resource_manager.load<model>(filename);
component.instance_count = 0; component.instance_count = 0;
component.layers = 1;
if (!component.model) if (!component.model)
{ {
std::string message = std::string("load_model_component(): Failed to load model \"") + filename + std::string("\""); std::string message = std::string("load_model_component(): Failed to load model \"") + filename + std::string("\"");

+ 16
- 18
src/state/play-state.cpp View File

@ -37,6 +37,7 @@
#include "entity/components/copy-transform-component.hpp" #include "entity/components/copy-transform-component.hpp"
#include "entity/components/copy-translation-component.hpp" #include "entity/components/copy-translation-component.hpp"
#include "entity/archetype.hpp" #include "entity/archetype.hpp"
#include "entity/entity-commands.hpp"
#include "nest.hpp" #include "nest.hpp"
#include "math.hpp" #include "math.hpp"
#include "geometry/mesh-accelerator.hpp" #include "geometry/mesh-accelerator.hpp"
@ -65,7 +66,16 @@ void enter_play_state(application* app)
ecs::archetype* forceps_archetype = resource_manager->load<ecs::archetype>("forceps.ent"); ecs::archetype* forceps_archetype = resource_manager->load<ecs::archetype>("forceps.ent");
ecs::archetype* larva_archetype = resource_manager->load<ecs::archetype>("larva.ent"); ecs::archetype* larva_archetype = resource_manager->load<ecs::archetype>("larva.ent");
ecs::archetype* pebble_archetype = resource_manager->load<ecs::archetype>("pebble.ent"); ecs::archetype* pebble_archetype = resource_manager->load<ecs::archetype>("pebble.ent");
ecs::archetype* flashlight_archetype = resource_manager->load<ecs::archetype>("flashlight.ent");
ecs::archetype* flashlight_light_cone_archetype = resource_manager->load<ecs::archetype>("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; ecs::placement_component placement;
@ -164,18 +174,6 @@ void enter_play_state(application* app)
ecs::tool_component forceps_tool_component; ecs::tool_component forceps_tool_component;
forceps_tool_component.active = true; forceps_tool_component.active = true;
ecs_registry.assign<ecs::tool_component>(forceps_entity, forceps_tool_component); ecs_registry.assign<ecs::tool_component>(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<ecs::copy_translation_component>(ant_hill_entity, constraint);
app->get_scene().update_tweens(); app->get_scene().update_tweens();
@ -233,15 +231,15 @@ void enter_play_state(application* app)
*/ */
// Place larva in chamber // Place larva in chamber
/*
{ {
auto larva_entity = larva_archetype->create(ecs_registry);
auto& transform = ecs_registry.get<ecs::transform_component>(larva_entity);
transform.transform = vmq::identity_transform<float>;
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<ecs::transform_component>(larva_entity);
//transform.transform = vmq::identity_transform<float>;
//transform.transform.translation = nest->get_shaft_position(*central_shaft, central_shaft->depth[1]);
//transform.transform.translation.y -= 1.0f; //transform.transform.translation.y -= 1.0f;
} }
*/
control_system* control_system = app->get_control_system(); control_system* control_system = app->get_control_system();
control_system->update(0.0f); control_system->update(0.0f);

src/systems/model-system.cpp → src/systems/render-system.cpp View File

@ -17,23 +17,24 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "model-system.hpp"
#include "render-system.hpp"
#include "entity/components/transform-component.hpp" #include "entity/components/transform-component.hpp"
#include <algorithm>
using namespace ecs; 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<model_component>().connect<&model_system::on_model_construct>(this);
registry.on_replace<model_component>().connect<&model_system::on_model_replace>(this);
registry.on_destroy<model_component>().connect<&model_system::on_model_destroy>(this);
registry.on_construct<model_component>().connect<&render_system::on_model_construct>(this);
registry.on_replace<model_component>().connect<&render_system::on_model_replace>(this);
registry.on_destroy<model_component>().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<transform_component, model_component>().each(
registry.view<transform_component, model_component>().each
(
[this](auto entity, auto& transform, auto& model) [this](auto entity, auto& transform, auto& model)
{ {
model_instance* instance = model_instances[entity]; model_instance* instance = model_instances[entity];
@ -46,10 +47,21 @@ void model_system::update(double t, double dt)
instance->update_tweens(); instance->update_tweens();
transform.warp = false; 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()) 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); 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<std::size_t>(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; model_instances[entity] = model_instance;
update_model_and_materials(entity, model); 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); 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()) 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; delete it->second;
model_instances.erase(it); model_instances.erase(it);
} }

src/systems/model-system.hpp → src/systems/render-system.hpp View File

@ -17,20 +17,24 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/ */
#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 "entity-system.hpp"
#include "scene/scene.hpp" #include "scene/scene.hpp"
#include "scene/model-instance.hpp" #include "scene/model-instance.hpp"
#include "entity/components/model-component.hpp" #include "entity/components/model-component.hpp"
#include <unordered_map> #include <unordered_map>
#include <vector>
class model_system: public entity_system
class render_system: public entity_system
{ {
public: public:
model_system(entt::registry& registry, ::scene& scene);
render_system(entt::registry& registry);
virtual void update(double t, double dt); virtual void update(double t, double dt);
void add_layer(::scene* layer);
void remove_layers();
private: private:
void update_model_and_materials(entt::entity entity, ecs::model_component& model); 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_replace(entt::registry& registry, entt::entity entity, ecs::model_component& model);
void on_model_destroy(entt::registry& registry, entt::entity entity); void on_model_destroy(entt::registry& registry, entt::entity entity);
::scene& scene;
std::vector<scene*> layers;
std::unordered_map<entt::entity, model_instance*> model_instances; std::unordered_map<entt::entity, model_instance*> model_instances;
}; };
#endif // ANTKEEPER_MODEL_SYSTEM_HPP
#endif // ANTKEEPER_RENDER_SYSTEM_HPP

+ 1
- 0
src/systems/terrain-system.cpp View File

@ -325,6 +325,7 @@ void terrain_system::on_terrain_construct(entt::registry& registry, entt::entity
model_component model; model_component model;
model.model = terrain_model; model.model = terrain_model;
model.instance_count = 0; model.instance_count = 0;
model.layers = 1;
registry.assign_or_replace<model_component>(entity, model); registry.assign_or_replace<model_component>(entity, model);
// Assign the entity a transform component // Assign the entity a transform component

Loading…
Cancel
Save