MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
ParticleNetwork.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "NodeNetwork.hpp"
4
6
8
9/**
10 * @class ParticleNetwork
11 * @brief Motion-focused point network with swappable operators
12 *
13 * Philosophy: ParticleNetwork is for MOTION. Operators define how
14 * points move (physics, flocking, fields). When you need connectivity
15 * visualization (topology, paths), use PointCloudNetwork instead.
16 *
17 * Supported operators (motion-based):
18 * - PhysicsOperator: Ballistic motion, gravity, springs, collisions
19 * - FieldOperator: Flow fields, attractors, force fields (future)
20 * - FlockingOperator: Boids, swarm intelligence (future)
21 *
22 * Unsupported operators (connectivity-based):
23 * - TopologyOperator: Technically works, but use PointCloudNetwork
24 * - PathOperator: Makes no semantic sense for particles
25 *
26 * PARAMETER MAPPING:
27 * ==================
28 * External nodes can control motion behavior:
29 *
30 * BROADCAST (one node → all particles):
31 * - "gravity_x/y/z": Gravity components
32 * - "drag": Air resistance coefficient
33 * - "turbulence": Chaos/noise strength
34 * - "interaction_radius": Spatial interaction distance
35 * - "spring_stiffness": Spring force strength
36 *
37 * USAGE:
38 * ======
39 * ```cpp
40 * auto particles = vega.ParticleNetwork(1000);
41 * auto physics = particles->create_operator<PhysicsOperator>();
42 * physics->set_gravity(glm::vec3(0, -9.81, 0));
43 * physics->set_interaction_radius(2.0F);
44 *
45 * // Audio-reactive turbulence
46 * auto chaos = vega.Random() | Audio;
47 * particles->map_parameter("turbulence", chaos, MappingMode::BROADCAST);
48 *
49 * // Runtime switch to field-driven motion
50 * auto field = particles->create_operator<FieldOperator>();
51 * field->add_attractor(glm::vec3(0, 0, 0), 5.0F);
52 * ```
53 */
54class MAYAFLUX_API ParticleNetwork : public NodeNetwork {
55public:
56 //-------------------------------------------------------------------------
57 // Construction
58 //-------------------------------------------------------------------------
59
60 /**
61 * @brief Create particle network with spatial bounds
62 * @param num_particles Number of particles
63 * @param bounds_min Minimum spatial extent
64 * @param bounds_max Maximum spatial extent
65 * @param init_mode Initialization distribution
66 */
68 size_t num_particles,
69 const glm::vec3& bounds_min = glm::vec3(-10.0F),
70 const glm::vec3& bounds_max = glm::vec3(10.0F),
71 Kinesis::SpatialDistribution init_mode = Kinesis::SpatialDistribution::RANDOM_VOLUME);
72
73 //-------------------------------------------------------------------------
74 // NodeNetwork Interface
75 //-------------------------------------------------------------------------
76
77 void initialize() override;
78 void reset() override;
79 void process_batch(unsigned int num_samples) override;
80
81 /**
82 * @brief Reinitialize particle network with new parameters
83 * @param num_particles Number of particles
84 * @param bounds_min Minimum spatial extent
85 * @param bounds_max Maximum spatial extent
86 * @param init_mode Initialization distribution
87 */
88 void reinitialize(
89 size_t num_particles,
90 const glm::vec3& bounds_min,
91 const glm::vec3& bounds_max,
93
94 /**
95 * @brief Get number of particles in network
96 *
97 * Returns total particle count across all internal collections.
98 * For ParticleNetwork, "nodes" ARE particles - each particle is
99 * a mappable entity for parameter control.
100 */
101 [[nodiscard]] size_t get_node_count() const override;
102
103 /**
104 * @brief Get point count (alias for get_node_count)
105 *
106 * Provided for clarity in graphics contexts. For ParticleNetwork,
107 * points and nodes are the same concept.
108 */
109 [[nodiscard]] size_t get_point_count() const { return get_node_count(); }
110
111 /**
112 * @brief Get output value for specific particle
113 * @param index Particle index (0 to get_node_count()-1)
114 *
115 * Returns per-particle output (e.g., velocity magnitude).
116 * Used for ONE_TO_ONE parameter mapping from this network
117 * to other networks.
118 */
119 [[nodiscard]] std::optional<double> get_node_output(size_t index) const override;
120
121 [[nodiscard]] std::unordered_map<std::string, std::string> get_metadata() const override;
122
123 //-------------------------------------------------------------------------
124 // Operator Management
125 //-------------------------------------------------------------------------
126
127 /**
128 * @brief Set active operator (runtime switching)
129 */
130 void set_operator(std::unique_ptr<NetworkOperator> op);
131
132 /**
133 * @brief Create and set operator in one call
134 */
135 template <typename OpType, typename... Args>
136 OpType* create_operator(Args&&... args)
137 {
138 auto op = std::make_unique<OpType>(std::forward<Args>(args)...);
139 auto* ptr = op.get();
140 set_operator(std::move(op));
141 return ptr;
142 }
143
144 /**
145 * @brief Get current operator with type-safe cast
146 */
147 template <typename OpType>
148 OpType* as_operator()
149 {
150 return dynamic_cast<OpType*>(m_operator.get());
151 }
152
153 template <typename OpType>
154 const OpType* as_operator() const
155 {
156 return dynamic_cast<const OpType*>(m_operator.get());
157 }
158
159 NetworkOperator* get_operator() override { return m_operator.get(); }
160 const NetworkOperator* get_operator() const override { return m_operator.get(); }
161 bool has_operator() const override { return m_operator != nullptr; }
162
163 //-------------------------------------------------------------------------
164 // Configuration
165 //-------------------------------------------------------------------------
166
167
168 void set_bounds(const glm::vec3& min, const glm::vec3& max)
169 {
170 m_bounds = Kinesis::SamplerBounds(min, max);
171 }
172
173 Kinesis::SamplerBounds get_bounds() const { return m_bounds; }
174
175 void set_topology(Topology topology) override;
176
177 /**
178 * @brief Whether initialize() fabricates a PhysicsOperator when no primary
179 * has been set.
180 *
181 * Enabled by default: a network constructed and processed with no further
182 * configuration still moves. Disable before initialize() when the primary
183 * is deliberately absent and the work happens in the operator chain.
184 */
185 void enable_default_operator(bool enabled) { m_default_operator = enabled; }
186 [[nodiscard]] bool default_operator_enabled() const { return m_default_operator; }
187
188 //-------------------------------------------------------------------------
189 // Parameter Mapping (Delegates to Operator)
190 //-------------------------------------------------------------------------
191
192 void map_parameter(
193 const std::string& param_name,
194 const std::shared_ptr<Node>& source,
195 MappingMode mode = MappingMode::BROADCAST) override;
196
197 void unmap_parameter(const std::string& param_name) override;
198
199private:
200 std::unique_ptr<NetworkOperator> m_operator;
202
204 // glm::vec3 m_bounds_min;
205 // glm::vec3 m_bounds_max;
208
209 void ensure_initialized();
210 std::vector<PointVertex> generate_initial_vertices();
211 PointVertex generate_single_vertex(Kinesis::SpatialDistribution mode, size_t index, size_t total);
212
213 /**
214 * @brief Whether an operator can serve as this network's primary.
215 *
216 * ParticleNetwork drives per-point motion, so a primary must own
217 * PointVertex storage and accept initialisation from a generated point
218 * distribution. The list is the set of operators that do, not a privilege
219 * granted to any one of them.
220 */
221 [[nodiscard]] static bool is_compatible(const NetworkOperator& op) noexcept;
222
223 bool m_default_operator { true };
224
225 //-------------------------------------------------------------------------
226 // Parameter Mapping Helpers
227 //-------------------------------------------------------------------------
228
229 /**
230 * @brief Update mapped parameters before physics step
231 */
232 void update_mapped_parameters();
233};
234
235} // namespace MayaFlux::Nodes::Network
uint32_t total
uint32_t mode
PrimitiveTopology topology
glm::ivec3 min
glm::ivec3 max
uint32_t index
Definition VKDevice.cpp:122
const uint8_t * ptr
Unified generative infrastructure for stochastic and procedural algorithms.
Domain-agnostic interpretive lens for network processing.
Abstract base class for structured collections of nodes with defined relationships.
size_t get_point_count() const
Get point count (alias for get_node_count)
Kinesis::Stochastic::Stochastic m_random_gen
Kinesis::SamplerBounds get_bounds() const
NetworkOperator * get_operator() override
OpType * create_operator(Args &&... args)
Create and set operator in one call.
OpType * as_operator()
Get current operator with type-safe cast.
const NetworkOperator * get_operator() const override
void enable_default_operator(bool enabled)
Whether initialize() fabricates a PhysicsOperator when no primary has been set.
std::unique_ptr< NetworkOperator > m_operator
void set_bounds(const glm::vec3 &min, const glm::vec3 &max)
Motion-focused point network with swappable operators.
void initialize()
Definition main.cpp:10
SpatialDistribution
Spatial distribution mode for point cloud and particle generation.
Topology
Defines the structural relationships between nodes in the network.
MappingMode
Defines how nodes map to external entities (e.g., audio channels, graphics objects)
Vertex type for point primitives (POINT_LIST topology)
Spatial domain for vertex generation.