💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
7.2 KiB

  1. /*
  2. * Copyright (C) 2021 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. #include "render.hpp"
  20. #include "entity/components/transform.hpp"
  21. #include "entity/components/camera.hpp"
  22. #include "scene/point-light.hpp"
  23. #include "scene/directional-light.hpp"
  24. #include "scene/ambient-light.hpp"
  25. #include "scene/spot-light.hpp"
  26. #include <iostream>
  27. namespace entity {
  28. namespace system {
  29. render::render(entity::registry& registry):
  30. updatable(registry),
  31. t(0.0),
  32. dt(0.0),
  33. renderer(nullptr)
  34. {
  35. registry.on_construct<component::model>().connect<&render::on_model_construct>(this);
  36. registry.on_replace<component::model>().connect<&render::on_model_replace>(this);
  37. registry.on_destroy<component::model>().connect<&render::on_model_destroy>(this);
  38. registry.on_construct<component::light>().connect<&render::on_light_construct>(this);
  39. registry.on_replace<component::light>().connect<&render::on_light_replace>(this);
  40. registry.on_destroy<component::light>().connect<&render::on_light_destroy>(this);
  41. }
  42. void render::update(double t, double dt)
  43. {
  44. this->t = t;
  45. this->dt = dt;
  46. // Update model instance transforms
  47. registry.view<component::transform, component::model>().each
  48. (
  49. [this](entity::id entity_id, auto& transform, auto& model)
  50. {
  51. scene::model_instance* instance = model_instances[entity_id];
  52. instance->set_transform(transform.world);
  53. if (transform.warp)
  54. {
  55. instance->get_transform_tween().update();
  56. instance->update_tweens();
  57. transform.warp = false;
  58. }
  59. }
  60. );
  61. // Update camera transforms
  62. registry.view<component::transform, component::camera>().each
  63. (
  64. [this](entity::id entity_id, auto& transform, auto& camera)
  65. {
  66. camera.object->set_transform(transform.world);
  67. if (transform.warp)
  68. {
  69. camera.object->get_transform_tween().update();
  70. camera.object->update_tweens();
  71. transform.warp = false;
  72. }
  73. }
  74. );
  75. // Update light transforms
  76. registry.view<component::transform, component::light>().each
  77. (
  78. [this](entity::id entity_id, auto& transform, auto& light)
  79. {
  80. scene::light* light_object = lights[entity_id];
  81. light_object->set_transform(transform.world);
  82. if (transform.warp)
  83. {
  84. light_object->get_transform_tween().update();
  85. light_object->update_tweens();
  86. transform.warp = false;
  87. }
  88. }
  89. );
  90. }
  91. void render::draw(double alpha)
  92. {
  93. if (renderer)
  94. {
  95. for (const scene::collection* collection: layers)
  96. {
  97. renderer->render(static_cast<float>(t + dt * alpha), static_cast<float>(dt), static_cast<float>(alpha), *collection);
  98. }
  99. }
  100. }
  101. void render::add_layer(scene::collection* layer)
  102. {
  103. layers.push_back(layer);
  104. }
  105. void render::remove_layers()
  106. {
  107. layers.clear();
  108. }
  109. void render::set_renderer(::render::renderer* renderer)
  110. {
  111. this->renderer = renderer;
  112. }
  113. scene::model_instance* render::get_model_instance(entity::id entity_id)
  114. {
  115. if (auto it = model_instances.find(entity_id); it != model_instances.end())
  116. return it->second;
  117. return nullptr;
  118. }
  119. scene::light* render::get_light(entity::id entity_id)
  120. {
  121. if (auto it = lights.find(entity_id); it != lights.end())
  122. return it->second;
  123. return nullptr;
  124. }
  125. void render::update_model_and_materials(entity::id entity_id, component::model& model)
  126. {
  127. if (auto model_it = model_instances.find(entity_id); model_it != model_instances.end())
  128. {
  129. model_it->second->set_model(model.render_model);
  130. model_it->second->set_instanced((model.instance_count > 0), model.instance_count);
  131. for (auto material_it = model.materials.begin(); material_it != model.materials.end(); ++material_it)
  132. {
  133. model_it->second->set_material(material_it->first, material_it->second);
  134. }
  135. // Add model instance to its specified layers
  136. for (std::size_t i = 0; i < std::min<std::size_t>(layers.size(), (sizeof(model.layers) << 3)); ++i)
  137. {
  138. layers[i]->remove_object(model_it->second);
  139. if ((model.layers >> i) & 1)
  140. {
  141. layers[i]->add_object(model_it->second);
  142. }
  143. }
  144. }
  145. }
  146. void render::update_light(entity::id entity_id, entity::component::light& component)
  147. {
  148. if (auto light_it = lights.find(entity_id); light_it != lights.end())
  149. {
  150. scene::light* light = light_it->second;
  151. light->set_color(component.color);
  152. light->set_intensity(component.intensity);
  153. switch (light->get_light_type())
  154. {
  155. case scene::light_type::point:
  156. {
  157. scene::point_light* point = static_cast<scene::point_light*>(light);
  158. point->set_attenuation(component.attenuation);
  159. break;
  160. }
  161. case scene::light_type::spot:
  162. {
  163. scene::spot_light* spot = static_cast<scene::spot_light*>(light);
  164. spot->set_attenuation(component.attenuation);
  165. spot->set_cutoff(component.cutoff);
  166. break;
  167. }
  168. default:
  169. break;
  170. }
  171. }
  172. }
  173. void render::on_model_construct(entity::registry& registry, entity::id entity_id, component::model& model)
  174. {
  175. scene::model_instance* model_instance = new scene::model_instance();
  176. model_instances[entity_id] = model_instance;
  177. update_model_and_materials(entity_id, model);
  178. }
  179. void render::on_model_replace(entity::registry& registry, entity::id entity_id, component::model& model)
  180. {
  181. update_model_and_materials(entity_id, model);
  182. }
  183. void render::on_model_destroy(entity::registry& registry, entity::id entity_id)
  184. {
  185. if (auto it = model_instances.find(entity_id); it != model_instances.end())
  186. {
  187. scene::model_instance* model_instance = it->second;
  188. // Remove model instance from all layers
  189. for (scene::collection* layer: layers)
  190. layer->remove_object(model_instance);
  191. model_instances.erase(it);
  192. delete model_instance;
  193. }
  194. }
  195. void render::on_light_construct(entity::registry& registry, entity::id entity_id, component::light& component)
  196. {
  197. scene::light* light = nullptr;
  198. switch (component.type)
  199. {
  200. case scene::light_type::ambient:
  201. light = new scene::ambient_light();
  202. break;
  203. case scene::light_type::directional:
  204. light = new scene::directional_light();
  205. break;
  206. case scene::light_type::point:
  207. light = new scene::point_light();
  208. break;
  209. case scene::light_type::spot:
  210. light = new scene::spot_light();
  211. break;
  212. default:
  213. break;
  214. }
  215. if (light)
  216. {
  217. lights[entity_id] = light;
  218. for (scene::collection* layer: layers)
  219. layer->add_object(light);
  220. update_light(entity_id, component);
  221. }
  222. }
  223. void render::on_light_replace(entity::registry& registry, entity::id entity_id, component::light& light)
  224. {
  225. update_light(entity_id, light);
  226. }
  227. void render::on_light_destroy(entity::registry& registry, entity::id entity_id)
  228. {
  229. if (auto it = lights.find(entity_id); it != lights.end())
  230. {
  231. scene::light* light = it->second;
  232. for (scene::collection* layer: layers)
  233. layer->remove_object(light);
  234. lights.erase(it);
  235. delete light;
  236. }
  237. }
  238. } // namespace system
  239. } // namespace entity