Antkeeper  0.0.1
swarm.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 
20 #include "game/ant/swarm.hpp"
28 #include <engine/config.hpp>
29 #include <cmath>
30 #include <random>
31 
32 
33 namespace ant {
34 
40 template <class T, class Generator>
41 static math::vector3<T> sphere_random(Generator& rng)
42 {
43  std::uniform_real_distribution<T> distribution(T{-1}, T{1});
44 
46  for (std::size_t i = 0; i < 3; ++i)
47  position[i] = distribution(rng);
48 
49  return math::normalize(position) * std::cbrt(distribution(rng));
50 }
51 
53 {
54  // Determine swarm properties
55  const float3 swarm_center = {0, 100, 0};
56  const float swarm_radius = 25.0f;
57  const std::size_t male_count = 50;
58  const std::size_t queen_count = 50;
59  const std::size_t alate_count = male_count + queen_count;
60 
61  const float3 male_scale = {0.5, 0.5, 0.5};
62  const float3 queen_scale = {1, 1, 1};
63 
64  // Init transform component
65  ::transform_component transform;
67  transform.world = transform.local;
68  transform.warp = true;
69 
70  // Init picking component
71  ::picking_component picking;
72  picking.sphere = {float3{0, 0, 0}, 0.5f * 2.0f};
73  std::uint32_t male_picking_flags = 0b01;
74  std::uint32_t queen_picking_flags = 0b10;
75 
76  // Create swarm entity
77  entity::id swarm_eid = ctx.entity_registry->create();
78  transform.local.translation = swarm_center;
79  transform.world = transform.local;
80  transform.warp = true;
81  ctx.entity_registry->emplace<::transform_component>(swarm_eid, transform);
82 
83  // Init male model component
84  ::model_component male_model;
85  male_model.render_model = ctx.resource_manager->load<render::model>("male-boid.mdl");
86  male_model.instance_count = 0;
87  male_model.layers = 1;
88 
89  // Init queen model component
90  ::model_component queen_model;
91  queen_model.render_model = ctx.resource_manager->load<render::model>("queen-boid.mdl");
92  queen_model.instance_count = 0;
93  queen_model.layers = 1;
94 
95  // Init steering component
96  ::steering_component steering;
97  steering.agent.mass = 1.0f;
98  steering.agent.velocity = {0, 0, 0};
99  steering.agent.acceleration = {0, 0, 0};
100  steering.agent.max_force = 4.0f;
101  steering.agent.max_speed = 5.0f;
102  steering.agent.max_speed_squared = steering.agent.max_speed * steering.agent.max_speed;
104  steering.agent.forward = steering.agent.orientation * config::global_forward;
105  steering.agent.up = steering.agent.orientation * config::global_up;
106  steering.wander_weight = 1.0f;
107  steering.wander_noise = math::radians(2000.0f);
108  steering.wander_distance = 10.0f;
109  steering.wander_radius = 8.0f;
110  steering.wander_angle = 0.0f;
111  steering.wander_angle2 = 0.0f;
112  steering.seek_weight = 0.2f;
113  steering.seek_target = swarm_center;
114  steering.flee_weight = 0.0f;
115  steering.sum_weights = steering.wander_weight + steering.seek_weight + steering.flee_weight;
116 
117  // Init queen caste component
118  ::caste_component queen_caste;
119  queen_caste.type = ::ant::caste::queen;
120 
121  // Init male caste component
122  ::caste_component male_caste;
123  male_caste.type = ::ant::caste::male;
124 
125  // Construct and seed random number generator
126  std::random_device seed;
127  std::mt19937 rng(seed());
128 
129  // Create alates
130  for (std::size_t i = 0; i < alate_count; ++i)
131  {
132  // Generate random position in swarm sphere
133  steering.agent.position = swarm_center + sphere_random<float>(rng) * swarm_radius;
134  transform.local.translation = steering.agent.position;
135 
136  entity::id alate_eid = ctx.entity_registry->create();
137  ctx.entity_registry->emplace<::steering_component>(alate_eid, steering);
138 
139  if (i < male_count)
140  {
141  // Create male
142  ctx.entity_registry->emplace<::caste_component>(alate_eid, male_caste);
143  ctx.entity_registry->emplace<::model_component>(alate_eid, male_model);
144 
145  transform.local.scale = male_scale;
146  transform.world = transform.local;
147  ctx.entity_registry->emplace<::transform_component>(alate_eid, transform);
148 
149  picking.flags = male_picking_flags;
150  ctx.entity_registry->emplace<::picking_component>(alate_eid, picking);
151  }
152  else
153  {
154  // Create queen
155  ctx.entity_registry->emplace<::caste_component>(alate_eid, queen_caste);
156  ctx.entity_registry->emplace<::model_component>(alate_eid, queen_model);
157 
158  transform.local.scale = queen_scale;
159  transform.world = transform.local;
160  ctx.entity_registry->emplace<::transform_component>(alate_eid, transform);
161 
162  picking.flags = queen_picking_flags;
163  ctx.entity_registry->emplace<::picking_component>(alate_eid, picking);
164  }
165  }
166 
167  return swarm_eid;
168 }
169 
170 void destroy_swarm(::game& ctx, entity::id swarm_eid)
171 {
172  // Destroy alates
173  auto view = ctx.entity_registry->view<::steering_component>();
174  ctx.entity_registry->destroy(view.begin(), view.end());
175 
176  // Destroy swarm
177  ctx.entity_registry->destroy(swarm_eid);
178 }
179 
180 } // namespace ant
181 
Definition: game.hpp:117
std::unique_ptr< resource_manager > resource_manager
Definition: game.hpp:148
std::unique_ptr< entity::registry > entity_registry
Definition: game.hpp:341
Definition: caste.hpp:25
void destroy_swarm(::game &ctx, entity::id swarm_eid)
Definition: swarm.cpp:170
entity::id create_swarm(::game &ctx)
Definition: swarm.cpp:52
entt::entity id
Entity ID type.
Definition: id.hpp:28
quaternion< T > normalize(const quaternion< T > &q)
Normalizes a quaternion.
Definition: quaternion.hpp:605
constexpr T radians(T degrees) noexcept
Converts an angle given in degrees to radians.
Definition: angles.hpp:48
@ position
Vertex position (vec3)
float max_force
Maximum force.
Definition: agent.hpp:47
float3 acceleration
Acceleration vector.
Definition: agent.hpp:44
float max_speed_squared
Maximum speed squared.
Definition: agent.hpp:53
float mass
Mass of the agent.
Definition: agent.hpp:35
float3 forward
Orthonormal basis forward direction vector.
Definition: agent.hpp:59
float3 velocity
Velocity vector.
Definition: agent.hpp:41
float max_speed
Maximum speed.
Definition: agent.hpp:50
float3 up
Orthonormal basis up direction vector.
Definition: agent.hpp:62
math::quaternion< float > orientation
Orientation quaternion.
Definition: agent.hpp:56
float3 position
Cartesian position vector.
Definition: agent.hpp:38
::ant::caste type
Caste type.
static constexpr quaternion identity() noexcept
Returns a rotation identity quaternion.
Definition: quaternion.hpp:193
Represents 3D TRS transformation.
vector< T, 3 > translation
Translation vector.
vector< T, 3 > scale
Scale vector.
unsigned int layers
render::model * render_model
geom::primitive::sphere< float > sphere
Picking sphere.
std::uint32_t flags
Picking flags.
float sum_weights
Sum of steering behavior weights.
ai::steering::agent agent
Steering agent.
math::transform< float > world
math::transform< float > local