Antkeeper  0.0.1
reproductive-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 
28 #include <engine/math/fract.hpp>
31 #include <engine/debug/log.hpp>
32 #include <execution>
33 
36 {}
37 
38 void reproductive_system::update(float t, float dt)
39 {
40  auto ovary_group = registry.group<ovary_component>(entt::get<ant_genome_component, rigid_body_component, scene_component, pose_component>);
41  std::for_each
42  (
43  std::execution::seq,
44  ovary_group.begin(),
45  ovary_group.end(),
46  [&](auto entity_id)
47  {
48  auto& ovary = ovary_group.get<ovary_component>(entity_id);
49 
50  // Produce eggs
51  if (ovary.egg_count < ovary.egg_capacity)
52  {
53  ovary.elapsed_egg_production_time += dt * m_time_scale;
54  if (ovary.elapsed_egg_production_time >= ovary.egg_production_duration)
55  {
56  ovary.egg_count += static_cast<std::uint16_t>(ovary.elapsed_egg_production_time / ovary.egg_production_duration);
57  ovary.egg_count = std::min(ovary.egg_count, ovary.egg_capacity);
58  ovary.elapsed_egg_production_time = math::fract(ovary.elapsed_egg_production_time);
59  }
60  }
61 
62  // Oviposit egg
63  if (ovary.ovipositor_egg_eid != entt::null || (ovary.ovipositing && ovary.egg_count))
64  {
65  // Get transform of ovipositor
66  const auto& ovipositor_rigid_body = *ovary_group.get<rigid_body_component>(entity_id).body;
67  const auto& ovipositor_pose = ovary_group.get<pose_component>(entity_id);
68  const auto ovipositor_transform = ovipositor_rigid_body.get_transform() * ovipositor_pose.current_pose.get_absolute_transform(ovary.ovipositor_bone);
69 
70  // Advance oviposition time
71  if (ovary.ovipositing)
72  {
73  ovary.elapsed_oviposition_time += dt * m_time_scale;
74  }
75  else
76  {
77  ovary.elapsed_oviposition_time -= dt * m_time_scale;
78  ovary.elapsed_oviposition_time = std::max(0.0f, ovary.elapsed_oviposition_time);
79  }
80 
81  // Determine position and orientation of egg
82  const float t = std::min(ovary.elapsed_oviposition_time / ovary.oviposition_duration, 1.0f);
83  auto egg_transform = ovipositor_transform;
84  egg_transform.translation = egg_transform * math::lerp(ovary.oviposition_path.a, ovary.oviposition_path.b, t);
85 
86  if (ovary.ovipositor_egg_eid == entt::null)
87  {
88  // Get genome of parent entity
89  const auto& parent_genome = ovary_group.get<ant_genome_component>(entity_id);
90 
91  // Get scene component of ovipositing entity
92  const auto& ovipositor_scene = ovary_group.get<scene_component>(entity_id);
93 
94 
95  // Construct egg rigid body
96  auto egg_rigid_body = std::make_unique<physics::rigid_body>();
97  egg_rigid_body->set_mass(0.0f);
98  egg_rigid_body->set_transform(egg_transform);
99  egg_rigid_body->set_previous_transform(egg_transform);
100 
101  // Construct egg scene object
102  auto egg_scene_object = std::make_shared<scene::static_mesh>(parent_genome.genome->egg->phenes.front().model);
103 
104  // Construct egg entity
105  ovary.ovipositor_egg_eid = registry.create();
106  registry.emplace<rigid_body_component>(ovary.ovipositor_egg_eid, std::move(egg_rigid_body));
107  registry.emplace<scene_component>(ovary.ovipositor_egg_eid, std::move(egg_scene_object), ovipositor_scene.layer_mask);
108  registry.emplace<ant_genome_component>(ovary.ovipositor_egg_eid, parent_genome);
109  }
110  else
111  {
112  // Update position of egg rigid body
113  auto& egg_rigid_body = *registry.get<rigid_body_component>(ovary.ovipositor_egg_eid).body;
114  egg_rigid_body.set_transform(egg_transform);
115  }
116 
117  if (ovary.elapsed_oviposition_time >= ovary.oviposition_duration)
118  {
119  // Place egg
120  auto& egg_rigid_body = *registry.get<rigid_body_component>(ovary.ovipositor_egg_eid).body;
121  const auto oviposition_ray = geom::ray<float, 3>{egg_transform.translation, egg_transform.rotation * math::fvec3{0, 0, -1}};
122  if (auto trace = m_physics_system->trace(oviposition_ray, ovary.ovipositor_egg_eid, ~std::uint32_t{0}))
123  {
124  egg_transform.translation = oviposition_ray.extrapolate(std::get<1>(*trace));
125  egg_transform.rotation = math::normalize(math::rotation(egg_transform.rotation * math::fvec3{0, 1, 0}, std::get<3>(*trace)) * egg_transform.rotation);
126  egg_rigid_body.set_transform(egg_transform);
127 
128  // Get genome of egg
129  const auto& genome = *registry.get<ant_genome_component>(ovary.ovipositor_egg_eid).genome;
130 
131  // Construct egg component
132  registry.emplace<egg_component>(ovary.ovipositor_egg_eid, genome.egg->phenes.front().incubation_period, 0.0f);
133 
134  // Oviposition complete
135  ovary.ovipositing = false;
136  ovary.elapsed_oviposition_time = 0.0f;
137  --ovary.egg_count;
138  ovary.ovipositor_egg_eid = entt::null;
139  }
140  }
141  }
142  }
143  );
144 }
std::optional< std::tuple< entity::id, float, std::uint32_t, math::fvec3 > > trace(const geom::ray< float, 3 > &ray, entity::id ignore_eid=entt::null, std::uint32_t layer_mask=~std::uint32_t{0}) const
Traces a ray to the nearest point of intersection.
void update(float t, float dt) override
Perform's a system's update() function.
reproductive_system(entity::registry &registry)
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
constexpr T trace(const matrix< T, N, N > &m) noexcept
Calculates the trace of a square matrix.
constexpr T lerp(const T &x, const T &y, S a) noexcept
Linearly interpolates between x and y.
constexpr vector< T, N > min(const vector< T, N > &x, const vector< T, N > &y)
Returns a vector containing the minimum elements of two vectors.
Definition: vector.hpp:1347
Egg incubation parameters.