Antkeeper  0.0.1
render-system.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 Christopher J. Howard
3  *
4  * This file is part of Antkeeper source code.
5  *
6  * Antkeeper source code is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Antkeeper source code is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
23 #include <algorithm>
24 #include <execution>
25 
28  updated_scene_transforms(registry, entt::collector.update<transform_component>().where<scene_component>(entt::exclude<rigid_body_component>)),
29  t(0.0),
30  dt(0.0),
31  renderer(nullptr)
32 {
33  registry.on_construct<scene_component>().connect<&render_system::on_scene_construct>(this);
34  registry.on_update<scene_component>().connect<&render_system::on_scene_update>(this);
35  registry.on_destroy<scene_component>().connect<&render_system::on_scene_destroy>(this);
36 
37  registry.on_construct<transform_component>().connect<&render_system::on_transform_construct>(this);
38 }
39 
41 {
42  registry.on_construct<scene_component>().disconnect<&render_system::on_scene_construct>(this);
43  registry.on_update<scene_component>().disconnect<&render_system::on_scene_update>(this);
44  registry.on_destroy<scene_component>().disconnect<&render_system::on_scene_destroy>(this);
45 
46  registry.on_construct<transform_component>().disconnect<&render_system::on_transform_construct>(this);
47 }
48 
49 void render_system::update(float t, float dt)
50 {
51  this->t = t;
52  this->dt = dt;
53 
54  std::for_each
55  (
56  std::execution::par_unseq,
57  updated_scene_transforms.begin(),
58  updated_scene_transforms.end(),
59  [&](auto entity_id)
60  {
61  auto& transform = registry.get<transform_component>(entity_id);
62  const auto& scene = registry.get<scene_component>(entity_id);
63 
64  // WARNING: could potentially lead to multithreading issues with scene::object_base::transformed()
65  scene.object->set_transform(transform.world);
66  }
67  );
68  updated_scene_transforms.clear();
69 }
70 
71 void render_system::draw(float alpha)
72 {
73  if (renderer)
74  {
75  for (scene::collection* collection: layers)
76  {
77  renderer->render(t + dt * alpha, dt, alpha, *collection);
78  }
79  }
80 }
81 
83 {
84  layers.push_back(layer);
85 }
86 
88 {
89  layers.clear();
90 }
91 
93 {
94  this->renderer = renderer;
95 }
96 
97 void render_system::on_scene_construct(entity::registry& registry, entity::id entity_id)
98 {
99  const auto& component = registry.get<::scene_component>(entity_id);
100 
101  // Update scene object transform with pre-existing transform component
102  if (const auto transform = registry.try_get<transform_component>(entity_id))
103  {
104  component.object->set_transform(transform->world);
105  }
106 
107  for (std::size_t i = 0; i < layers.size(); ++i)
108  {
109  if (component.layer_mask & static_cast<std::uint8_t>(1 << i))
110  {
111  layers[i]->add_object(*component.object);
112  }
113  }
114 }
115 
116 void render_system::on_scene_update(entity::registry& registry, entity::id entity_id)
117 {
118  const auto& component = registry.get<::scene_component>(entity_id);
119 
120  for (std::size_t i = 0; i < layers.size(); ++i)
121  {
122  // Remove from layer
123  scene::collection* layer = layers[i];
124  layer->remove_object(*component.object);
125 
126  if (component.layer_mask & static_cast<std::uint8_t>(1 << i))
127  {
128  // Add to layer
129  layer->add_object(*component.object);
130  }
131  }
132 }
133 
134 void render_system::on_scene_destroy(entity::registry& registry, entity::id entity_id)
135 {
136  const auto& component = registry.get<::scene_component>(entity_id);
137 
138  for (std::size_t i = 0; i < layers.size(); ++i)
139  {
140  if (component.layer_mask & static_cast<std::uint8_t>(1 << i))
141  {
142  layers[i]->remove_object(*component.object);
143  }
144  }
145 }
146 
147 void render_system::on_transform_construct(entity::registry& registry, entity::id entity_id)
148 {
149  // Update pre-existing scene object transform withtransform component
150  if (const auto scene = registry.try_get<scene_component>(entity_id))
151  {
152  const auto& transform = registry.get<transform_component>(entity_id);
153 
154  scene->object->set_transform(transform.world);
155  }
156 }
void render(float t, float dt, float alpha, scene::collection &collection)
Renders a collection of scene objects.
Definition: renderer.cpp:48
void add_layer(scene::collection *layer)
render_system(entity::registry &registry)
void remove_layers()
void set_renderer(::render::renderer *renderer)
void draw(float alpha)
virtual void update(float t, float dt)
Perform's a system's update() function.
Collection of scene objects.
Definition: collection.hpp:33
void add_object(object_base &object)
Adds an object to the collection.
Definition: collection.cpp:24
void remove_object(const object_base &object)
Removes an object from the collection.
Definition: collection.cpp:30
void set_transform(const transform_type &transform)
Sets the transform of the object.
Definition: object.hpp:74
Abstract base class for lights, cameras, model instances, and other scene objects.
Definition: object.hpp:172
Abstract base class for updatable systems.
entity::registry & registry
Registry on which the system operate.
entt::registry registry
Component registry type.
Definition: registry.hpp:28
entt::entity id
Entity ID type.
Definition: id.hpp:28
3D scene.
Definition: context.hpp:28
std::shared_ptr< scene::object_base > object