MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
PhysicsOperator.hpp
Go to the documentation of this file.
1#pragma once
4
7
9
10/**
11 * @enum PhysicsParameter
12 * @brief Identifiers for physics parameters that can be set via parameter mapping
13 */
27
28/**
29 * @struct PhysicsState
30 * @brief Physics-specific data parallel to PointVertex array
31 *
32 * Stored separately to avoid polluting vertex types with
33 * physics data. Indexed in parallel with PointCollectionNode's
34 * internal vertex array.
35 */
37 glm::vec3 velocity { 0.0F };
38 glm::vec3 force { 0.0F };
39 float mass { 1.0F };
40};
41
42/**
43 * @class PhysicsOperator
44 * @brief N-body physics simulation with point rendering
45 *
46 * Delegates rendering to PointCollectionNode. Physics state
47 * (velocity, force, mass) stored in parallel array. Each frame:
48 * 1. Apply forces
49 * 2. Integrate motion
50 * 3. Update PointCollectionNode vertices
51 * 4. PointCollectionNode handles GPU upload
52 */
53class MAYAFLUX_API PhysicsOperator : public GraphicsOperator {
54public:
56 std::shared_ptr<GpuSync::PointCollectionNode> collection;
57 std::vector<PhysicsState> physics_state;
58 };
59
60 /**
61 * @enum BoundsMode
62 * @brief How particles behave at spatial bounds
63 */
64 enum class BoundsMode : uint8_t {
65 NONE, ///< No bounds checking
66 BOUNCE, ///< Reflect off boundaries with damping
67 WRAP, ///< Teleport to opposite side
68 CLAMP ///< Stop at boundary
69 };
70
72
73 /**
74 * @brief Initialize with a single physics collection
75 * @param vertices PointVertex array with position, color, size
76 */
77 void initialize(const std::vector<PointVertex>& vertices);
78
79 /**
80 * @brief Initialize multiple physics collections
81 * @param collections Vector of PointVertex vectors (one per collection)
82 */
83 void initialize_collections(
84 const std::vector<std::vector<PointVertex>>& collections);
85
86 /**
87 * @brief Add a single physics collection
88 * @param vertices PointVertex array with position, color, size
89 * @param mass_multiplier Mass multiplier for all particles in this collection
90 */
91 void add_collection(
92 const std::vector<PointVertex>& vertices,
93 float mass_multiplier = 1.0F);
94
95 void process(float dt) override;
96
97 [[nodiscard]] std::span<const uint8_t> get_vertex_data_for_collection(uint32_t idx) const override;
98 [[nodiscard]] std::span<const uint8_t> get_vertex_data() const override;
99 [[nodiscard]] Kakshya::VertexLayout get_vertex_layout() const override;
100 [[nodiscard]] size_t get_vertex_count() const override;
101 [[nodiscard]] bool is_vertex_data_dirty() const override;
102 void mark_vertex_data_clean() override;
103
104 /**
105 * @brief Extract current vertex data as PointVertex array
106 * @return Vector of PointVertex with current positions, colors, sizes
107 */
108 [[nodiscard]] std::vector<PointVertex> extract_vertices() const;
109
110 void set_parameter(std::string_view param, double value) override;
111 [[nodiscard]] std::optional<double> query_state(std::string_view query) const override;
112 [[nodiscard]] std::string_view get_type_name() const override { return "Physics"; }
113 [[nodiscard]] size_t get_point_count() const override;
114
115 /**
116 * @brief Set the gravity vector.
117 * @param gravity Gravity vector.
118 */
119 void set_gravity(const glm::vec3& gravity) { m_gravity = gravity; }
120
121 /**
122 * @brief Set the drag coefficient.
123 * @param drag Drag value.
124 */
125 void set_drag(float drag) { m_drag = drag; }
126
127 /**
128 * @brief Set the interaction radius for physics calculations.
129 * @param radius Interaction radius.
130 */
131 void set_interaction_radius(float radius) { m_interaction_radius = radius; }
132
133 /**
134 * @brief Set the spring stiffness for interactions.
135 * @param stiffness Spring stiffness value.
136 */
137 void set_spring_stiffness(float stiffness) { m_spring_stiffness = stiffness; }
138
139 /**
140 * @brief Set the simulation bounds.
141 * @param min Minimum bounds.
142 * @param max Maximum bounds.
143 */
144 void set_bounds(const glm::vec3& min, const glm::vec3& max);
145
146 /**
147 * @brief Set the rendered point size.
148 * @param size Point size.
149 */
150 void set_point_size(float size) { m_point_size = size; }
151
152 /**
153 * @brief Set the current bounds mode.
154 * @param mode Bounds mode to set.
155 */
156 void set_bounds_mode(BoundsMode mode) { m_bounds_mode = mode; }
157
158 /**
159 * @brief Enable or disable spatial interactions between particles.
160 * @param enable True to enable, false to disable.
161 */
162 void enable_spatial_interactions(bool enable) { m_spatial_interactions_enabled = enable; }
163
164 /**
165 * @brief Set the strength of repulsion between particles when spatial interactions are enabled.
166 * @param strength Repulsion strength value.
167 */
168 void set_repulsion_strength(float strength) { m_repulsion_strength = strength; }
169
170 /**
171 * @brief Set the strength of attraction towards the attraction point.
172 * @param strength Attraction strength value.
173 */
174 void set_attraction_strength(float strength) { m_attraction_strength = strength; }
175
176 /**
177 * @brief Set the strength of attraction towards the attraction point.
178 * @param strength Attraction strength value.
179 */
180 void set_turbulence_strength(float strength) { m_turbulence_strength = strength; }
181
182 /**
183 * @brief Get velocity magnitude for specific particle
184 * @param global_index Particle index across all collections
185 */
186 [[nodiscard]] std::optional<double> get_particle_velocity(size_t global_index) const;
187
188 /**
189 * @brief Get the current gravity vector.
190 * @return Gravity vector.
191 */
192 [[nodiscard]] glm::vec3 get_gravity() const { return m_gravity; }
193
194 /**
195 * @brief Get the current drag coefficient.
196 * @return Drag value.
197 */
198 [[nodiscard]] float get_drag() const { return m_drag; }
199
200 /**
201 * @brief Get the current bounds mode.
202 * @return Current bounds mode.
203 */
204 [[nodiscard]] BoundsMode get_bounds_mode() const { return m_bounds_mode; }
205
206 /**
207 * @brief Check if spatial interactions between particles are enabled.
208 * @return True if enabled, false otherwise.
209 */
210 [[nodiscard]] bool spatial_interactions_enabled() const { return m_spatial_interactions_enabled; }
211
212 /**
213 * @brief Get the current repulsion strength for spatial interactions.
214 * @return Repulsion strength value.
215 */
216 [[nodiscard]] float get_repulsion_strength() const { return m_repulsion_strength; }
217
218 void set_attraction_point(const glm::vec3& point);
219
220 void clear_attraction_point() { m_has_attraction_point = false; }
221
222 [[nodiscard]] bool has_attraction_point() const { return m_has_attraction_point; }
223
224 [[nodiscard]] glm::vec3 get_attraction_point() const { return m_attraction_point; }
225
226 /**
227 * @brief Apply impulse to all particles
228 */
229 void apply_global_impulse(const glm::vec3& impulse);
230
231 /**
232 * @brief Apply impulse to specific particle
233 */
234 void apply_impulse(size_t index, const glm::vec3& impulse);
235
236 /**
237 * @brief Add an external force field evaluated per-particle per-frame
238 * @param field VectorField: glm::vec3 (position) -> glm::vec3 (force)
239 *
240 * Fields are evaluated additively alongside existing hardcoded forces
241 * (gravity, attraction, turbulence, spatial interactions). Evaluated
242 * after gravity, before integration.
243 */
244 void add_force_field(Kinesis::VectorField field);
245
246 /**
247 * @brief Remove all external force fields
248 */
249 void clear_force_fields();
250
251 /**
252 * @brief Get number of active external force fields
253 */
254 [[nodiscard]] size_t force_field_count() const { return m_force_fields.size(); }
255
256 /**
257 * @brief Direct access to collections for advanced per-particle control
258 * @warning Only for ParticleNetwork's ONE_TO_ONE parameter mapping
259 */
260 std::vector<CollectionGroup>& get_collections() { return m_collections; }
261
262 /**
263 * @brief Apply ONE_TO_ONE parameter for physics-specific properties
264 *
265 * Supports:
266 * - "force_x/y/z": Per-particle force application
267 * - "mass": Per-particle mass
268 * - "color": Per-particle color (delegated to base)
269 * - "size": Per-particle size (delegated to base)
270 */
271 void apply_one_to_one(
272 std::string_view param,
273 const std::shared_ptr<NodeNetwork>& source) override;
274
275 const char* get_vertex_type_name() const override { return "PointVertex"; }
276
277protected:
278 void* get_data_at(size_t global_index) override;
279
280private:
281 std::vector<CollectionGroup> m_collections;
282 mutable std::vector<uint8_t> m_vertex_data_aggregate;
283 std::vector<Kinesis::VectorField> m_force_fields;
284
286
287 glm::vec3 m_gravity { 0.0F, -9.81F, 0.0F };
288 float m_drag { 0.01F };
289 float m_interaction_radius { 1.0F };
290 float m_spring_stiffness { 0.5F };
291 float m_point_size { 5.0F };
292 float m_turbulence_strength { 0.0F };
293 Kinesis::SamplerBounds m_bounds { .min = glm::vec3 { -10.0F }, .max = glm::vec3 { 10.0F } };
294 BoundsMode m_bounds_mode { BoundsMode::BOUNCE };
295 bool m_spatial_interactions_enabled {};
296 float m_repulsion_strength { 0.5F };
297
298 glm::vec3 m_attraction_point { 0.0F };
299 bool m_has_attraction_point { false };
300 float m_attraction_strength { 1.0F };
301
302 static std::optional<PhysicsParameter> string_to_parameter(std::string_view param);
303
304 void apply_forces();
305 void apply_spatial_interactions();
306 void apply_attraction_forces();
307 void apply_turbulence();
308 void integrate(float dt);
309 void handle_boundary_conditions();
310 void sync_to_point_collection();
311
312 void apply_per_particle_force(
313 std::string_view param,
314 const std::shared_ptr<NodeNetwork>& source);
315
316 void apply_per_particle_mass(
317 const std::shared_ptr<NodeNetwork>& source);
318};
319
320} // namespace MayaFlux::Nodes::Network
float max
Range radius
Range size
float min
Unified generative infrastructure for stochastic and procedural algorithms.
Operator that produces GPU-renderable geometry.
void set_repulsion_strength(float strength)
Set the strength of repulsion between particles when spatial interactions are enabled.
std::vector< CollectionGroup > m_collections
glm::vec3 get_gravity() const
Get the current gravity vector.
void set_turbulence_strength(float strength)
Set the strength of attraction towards the attraction point.
Kinesis::Stochastic::Stochastic m_random_generator
float get_drag() const
Get the current drag coefficient.
BoundsMode
How particles behave at spatial bounds.
void set_interaction_radius(float radius)
Set the interaction radius for physics calculations.
void set_drag(float drag)
Set the drag coefficient.
std::vector< Kinesis::VectorField > m_force_fields
std::vector< CollectionGroup > & get_collections()
Direct access to collections for advanced per-particle control.
void set_bounds_mode(BoundsMode mode)
Set the current bounds mode.
std::string_view get_type_name() const override
Type name for introspection.
size_t force_field_count() const
Get number of active external force fields.
void set_gravity(const glm::vec3 &gravity)
Set the gravity vector.
const char * get_vertex_type_name() const override
Get human-readable vertex type name (for validation/debugging)
void enable_spatial_interactions(bool enable)
Enable or disable spatial interactions between particles.
float get_repulsion_strength() const
Get the current repulsion strength for spatial interactions.
BoundsMode get_bounds_mode() const
Get the current bounds mode.
bool spatial_interactions_enabled() const
Check if spatial interactions between particles are enabled.
void set_point_size(float size)
Set the rendered point size.
void set_spring_stiffness(float stiffness)
Set the spring stiffness for interactions.
void set_attraction_strength(float strength)
Set the strength of attraction towards the attraction point.
N-body physics simulation with point rendering.
void initialize()
Definition main.cpp:11
PhysicsParameter
Identifiers for physics parameters that can be set via parameter mapping.
Complete description of vertex data layout in a buffer.
Spatial domain for vertex generation.
Typed, composable, stateless callable from domain D to range R.
Definition Tendency.hpp:22
std::shared_ptr< GpuSync::PointCollectionNode > collection
Physics-specific data parallel to PointVertex array.