Skip to main content

AxisSpawnPlacer.ixx File

Spawn placer that arranges entities along an axis. More...

Included Headers

Namespaces Index

namespacehelios
namespaceengine

Main engine module aggregating core infrastructure and game systems. More...

namespaceruntime

Runtime infrastructure for game execution and lifecycle orchestration. More...

namespacespawn

Entity spawning infrastructure for the helios engine. More...

namespacebehavior

Spawn behavior strategies for positioning and initializing entities. More...

namespaceplacements

Concrete SpawnPlacer implementations. More...

Classes Index

classAxisSpawnPlacer

Spawn placer that distributes entities evenly along an axis. More...

Description

Spawn placer that arranges entities along an axis.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file AxisSpawnPlacer.ixx
3 * @brief Spawn placer that arranges entities along an axis.
4 */
5module;
6
7#include <cassert>
8#include <algorithm>
9
10export module helios.engine.runtime.spawn.behavior.placements.AxisSpawnPlacer;
11
12import helios.engine.runtime.spawn.types.SpawnPlanCursor;
13import helios.engine.runtime.spawn.types.SpawnContext;
14import helios.engine.runtime.spawn.behavior.SpawnPlacer;
15import helios.util.Random;
16import helios.math;
17import helios.engine.ecs.EntityHandle;
18
19import helios.engine.runtime.world.UpdateContext;
20
21
24
25 /**
26 * @brief Spawn placer that distributes entities evenly along an axis.
27 *
28 * @details AxisSpawnPlacer positions spawned entities along a normalized
29 * direction vector starting from an origin point. Entities are distributed
30 * evenly between the origin and the environment boundary intersection.
31 *
32 * ## Positioning Algorithm
33 *
34 * 1 Calculates where the axis intersects the environment bounds
35 * 2 Computes available length accounting for entity size
36 * 3 Distributes entities evenly along this length based on cursor position
37 *
38 * ## Use Cases
39 *
40 * - **Formation spawning:** Line formations of enemies
41 * - **Wave patterns:** Entities spawning along a direction
42 * - **Corridor spawning:** Entities placed along a path
43 *
44 * ## Usage
45 *
46 * ```cpp
47 * // Spawn entities along positive X-axis from origin
48 * auto placer = std::make_unique<AxisSpawnPlacer>(
49 * helios::math::vec3f{1.0f, 0.0f, 0.0f}, // axis (normalized)
50 * helios::math::vec3f{-100.0f, 0.0f, 0.0f} // origin
51 * );
52 *
53 * // With 5 entities: evenly spaced from origin to right boundary
54 * ```
55 *
56 * @note The axis vector must be normalized.
57 * @note The origin must be within the environment bounds.
58 *
59 * @see SpawnPlacer
60 * @see DistributedSpawnPlacer
61 */
62 class AxisSpawnPlacer final : public SpawnPlacer {
63
64 /**
65 * @brief Normalized direction vector defining the spawn axis.
66 */
68
69 /**
70 * @brief Starting point for entity placement.
71 */
72 helios::math::vec3f origin_{};
73
74 public:
75
76 /**
77 * @brief Constructs an AxisSpawnPlacer with axis and origin.
78 *
79 * @param axis Normalized direction vector for entity distribution.
80 * @param origin Starting point for the axis within environment bounds.
81 *
82 * @pre `axis` must be normalized.
83 */
84 explicit AxisSpawnPlacer(const helios::math::vec3f axis, const helios::math::vec3f origin)
85 : axis_(axis), origin_(origin) {
86 assert(axis.isNormalized() && "Axis must be normalized.");
87 }
88
89 /**
90 * @brief Calculates spawn position along the axis.
91 *
92 * @details Distributes entities evenly along the axis from origin to
93 * the environment boundary. Uses the cursor position to determine
94 * placement within the available range.
95 *
96 * @param guid Unique identifier of the entity (unused).
97 * @param gameObjectBounds Bounding box of the entity being spawned.
98 * @param environmentBounds Bounding box of the spawn environment.
99 * @param cursor Current spawn batch cursor with position and count.
100 * @param spawnContext Context for the spawn operation (unused).
101 *
102 * @return World position for the spawned entity.
103 *
104 * @pre Origin must be within environment bounds.
105 */
107 const helios::engine::ecs::EntityHandle& entityHandle,
108 const helios::math::aabbf& gameObjectBounds,
109 const helios::math::aabbf& environmentBounds,
110 const SpawnPlanCursor& cursor,
111 const SpawnContext& spawnContext
112 ) override {
113
114 assert(environmentBounds.contains(origin_) && "origin is not within bounding box");
115
116 const float top = environmentBounds.max()[1];
117 const float bottom = environmentBounds.min()[1];
118 const float left = environmentBounds.min()[0];
119 const float right = environmentBounds.max()[0];
120 const float near = environmentBounds.min()[2];
121 const float far = environmentBounds.max()[2];
122
123 const float height = std::abs(top - bottom);
124 const float width = std::abs(right - left);
125
126 float t_x = std::numeric_limits<float>::infinity();
127 if (axis_[0] < 0) {
128 t_x = ((left - origin_[0]) / axis_[0]);
129 } else if (axis_[0] > 0 ){
130 t_x = ((right - origin_[0]) / axis_[0]);
131 }
132
133 float t_y = std::numeric_limits<float>::infinity();
134 if (axis_[1] < 0) {
135 t_y = ((bottom - origin_[1]) / axis_[1]);
136 } else if (axis_[1] > 0 ){
137 t_y = ((top - origin_[1]) / axis_[1]);
138 }
139
140 float t_z =std::numeric_limits<float>::infinity();
141 if (axis_[2] < 0) {
142 t_z = ((near - origin_[2]) / axis_[2]);
143 } else if (axis_[2] > 0 ){
144 t_z = ((far - origin_[2]) / axis_[2]);
145 }
146
147 const auto t = std::min(std::min(t_x, t_y), t_z);
148
149 // compute the projection of the aaabb onto the direction vector.
150 // we use absolute values of the direction vector to make sure
151 // we effectively measure dimensions, not projections relative
152 // to the origin direction
153 const auto objectHalfSize = gameObjectBounds.size() * 0.5f;
154 const auto projection = objectHalfSize.dot(helios::math::vec3f{
155 std::abs(axis_[0]), std::abs(axis_[1]), std::abs(axis_[2])
156 });
157
158 float availableLength = t - projection;
159 availableLength = availableLength < 0 ? 0 : availableLength;
160
161 const auto pos = axis_ * availableLength *
162 (static_cast<float>(cursor.position)/static_cast<float>(
163 cursor.spawnCount > 0 ? cursor.spawnCount - 1 :1)
164 );
165
166
167 const auto center = gameObjectBounds.translate(
168 helios::math::vec3f{origin_[0] + pos[0], origin_[1] + pos[1], origin_[2] + pos[2]}
169 ).center();
170
171 return center;
172 }
173
174
175 };
176
177}

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.