MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TopologyGeneratorNode.hpp
Go to the documentation of this file.
1#pragma once
2
5
8
10
11/**
12 * @class TopologyGeneratorNode
13 * @brief Generates dynamic mesh topology from sparse control points
14 *
15 * Core concept: Points define locations, ConnectionMode defines relationships.
16 * Every time points are added/removed/moved, topology is regenerated.
17 *
18 * Philosophy:
19 * - Points are spatial anchors
20 * - Connections emerge from geometric relationships
21 * - Topology IS the content, not decoration
22 *
23 * Extensions beyond connections:
24 * - Attractor mode: Points influence field, no lines
25 * - Gradient mode: Points define texture sampling positions
26 * - Emitter mode: Points spawn particles
27 *
28 * Usage:
29 * ```cpp
30 * auto topo = std::make_shared<TopologyGenerator>(
31 * Kinesis::ProximityMode::K_NEAREST,
32 * true // auto_connect
33 * );
34 *
35 * topo->add_point({glm::vec3(0.0f, 0.0f, 0.0f)});
36 * topo->add_point({glm::vec3(1.0f, 0.0f, 0.0f)});
37 * topo->add_point({glm::vec3(0.5f, 1.0f, 0.0f)});
38 * // Delaunay triangulation automatically computed
39 *
40 * auto buffer = std::make_shared<GeometryBuffer>(topo);
41 * buffer->setup_rendering({
42 * .target_window = window,
43 * .topology = PrimitiveTopology::LINE_LIST // or TRIANGLE_LIST
44 * });
45 * ```
46 * WARNING: Performance Characteristics
47 *
48 * Connection algorithms vary significantly in computational complexity.
49 * Topology is fully regenerated when points change.
50 *
51 * Complexity Overview:
52 * --------------------
53 * - Sequential Chain: O(n)
54 * - Radius Threshold: O(n²)
55 * - K-Nearest Neighbors: O(n² log k)
56 * - Minimum Spanning Tree: O(n² log n)
57 * - Gabriel Graph: O(n³)
58 * - Relative Neighborhood: O(n³)
59 *
60 * Practical Real-Time Guidance (approximate):
61 * -------------------------------------------
62 * - Sequential: thousands of points
63 * - Radius / KNN: a few hundred points
64 * - Gabriel / RNG: tens of points for interactive updates
65 *
66 * Batch Update Pattern for Expensive Modes:
67 * ------------------------------------------
68 * std::vector<Point> points;
69 * for (...) {
70 * points.push_back({position, color});
71 * }
72 * topo->set_points(points); // Single O(n³) rebuild
73 *
74 * Interactive Drawing Note:
75 * -------------------------
76 * When adding points continuously (e.g. mouse-move drawing),
77 * prefer SEQUENTIAL, RADIUS_THRESHOLD, or small-k K_NEAREST modes.
78 *
79 * TopologyGeneratorNode prioritizes correctness and determinism
80 * over incremental graph maintenance. Expensive modes are intended
81 * for moderate point counts or batch generation.
82 */
83class MAYAFLUX_API TopologyGeneratorNode : public GeometryWriterNode {
84public:
85 using CustomConnectionFunction = std::function<std::vector<std::pair<size_t, size_t>>(
86 const Eigen::MatrixXd&)>;
87
88 /**
89 * @brief Create topology generator
90 * @param mode Connection generation rule
91 * @param auto_connect If true, regenerate topology on every point addition
92 * @param max_points Maximum point capacity
93 */
94 explicit TopologyGeneratorNode(
95 Kinesis::ProximityMode mode = Kinesis::ProximityMode::SEQUENTIAL,
96 bool auto_connect = true,
97 size_t max_points = 256);
98
99 /**
100 * @brief Create with custom connection function
101 * @param custom_func User-provided topology generation
102 * @param auto_connect Auto-regenerate flag
103 * @param max_points Maximum capacity
104 */
106 CustomConnectionFunction custom_func,
107 bool auto_connect = true,
108 size_t max_points = 256);
109
110 /**
111 * @brief Add point to topology
112 * @param point LineVertex data
113 *
114 * If auto_connect enabled, immediately regenerates connections.
115 */
116 void add_point(const LineVertex& point);
117
118 /**
119 * @brief Remove point by index
120 * @param index Point index to remove
121 */
122 void remove_point(size_t index);
123
124 /**
125 * @brief Update point data
126 * @param index LineVertex index
127 * @param point New LineVertex data
128 */
129 void update_point(size_t index, const LineVertex& point);
130
131 /**
132 * @brief Set all points at once
133 * @param points Vector of LineVertex data
134 */
135 void set_points(const std::vector<LineVertex>& points);
136
137 /**
138 * @brief Clear all points and connections
139 */
140 void clear();
141
142 /**
143 * @brief Manually trigger connection regeneration
144 *
145 * Call this if auto_connect is false and you've made multiple changes.
146 */
147 void regenerate_topology();
148
149 /**
150 * @brief Set connection mode
151 * @param mode New connection rule
152 */
153 void set_connection_mode(Kinesis::ProximityMode mode);
154
155 /**
156 * @brief Enable/disable automatic connection regeneration
157 * @param enable Auto-connect flag
158 */
159 void set_auto_connect(bool enable);
160
161 /**
162 * @brief Set K parameter for K_NEAREST mode
163 * @param k Number of nearest neighbors
164 */
165 void set_k_neighbors(size_t k);
166
167 /**
168 * @brief Set radius for RADIUS_THRESHOLD mode
169 * @param radius Maximum connection distance
170 */
171 void set_connection_radius(float radius);
172
173 /**
174 * @brief Set line color (applied to all connections)
175 * @param color RGB color
176 * @param force_uniform Wether to ingore per vertex color and use this color for all points
177 */
178 void set_line_color(const glm::vec3& color, bool force_uniform = true);
179
180 /**
181 * @brief Get current line color
182 */
183 glm::vec3 get_line_color() const { return m_line_color; }
184
185 /**
186 * @brief Force uniform color for all vertices
187 * @param should_force If true, all vertices will use m_line_color instead of per-vertex color
188 */
189 void force_uniform_color(bool should_force);
190
191 /**
192 * @brief Check if uniform color is forced
193 */
194 bool should_force_uniform_color() const { return m_force_uniform_color; }
195
196 /**
197 * @brief Set line thickness
198 * @param thickness Line width
199 * @param force_uniform Wether to ingore per segment thickness and use this color for all points
200 */
201 void set_line_thickness(float thickness, bool force_uniform = true);
202
203 /**
204 * @brief Force uniform thickness for all vertices
205 * @param should_force If true, all vertices will use m_line_thickness instead of per-vertex thickness
206 */
207 void force_uniform_thickness(bool should_force);
208
209 /**
210 * @brief Get point count
211 */
212 [[nodiscard]] size_t get_point_count() const
213 {
214 return m_points.size();
215 }
216
217 /**
218 * @brief Get connection count (edge count)
219 */
220 [[nodiscard]] size_t get_connection_count() const
221 {
222 return m_connections.size();
223 }
224
225 /**
226 * @brief Get total vertex count (after interpolation)
227 */
228 [[nodiscard]] size_t get_vertex_count() const
229 {
230 return m_vertices.size();
231 }
232
233 /**
234 * @brief Get point by index
235 */
236 [[nodiscard]] const LineVertex& get_point(size_t index) const;
237
238 /**
239 * @brief Get all points
240 */
241 [[nodiscard]] std::vector<LineVertex> get_points() const;
242
243 /**
244 * @brief Get connection edges (pairs of point indices)
245 */
246 [[nodiscard]] const std::vector<std::pair<size_t, size_t>>& get_connections() const
247 {
248 return m_connections;
249 }
250
251 /**
252 * @brief Compute frame - generates vertex data from points and connections
253 */
254 void compute_frame() override;
255
256 /**
257 * @brief Set custom connection function (for CUSTOM mode)
258 * @param func User-provided topology generator
259 */
260 void set_path_interpolation_mode(Kinesis::InterpolationMode mode);
261
262 /**
263 * @brief Set number of samples per segment for interpolation
264 * @param samples Number of samples to generate per connection segment
265 *
266 * Higher values produce smoother curves but increase vertex count.
267 */
268 void set_samples_per_segment(size_t samples);
269
270 /**
271 * @brief Enable or disable arc-length reparameterization for interpolation
272 * @param enable If true, applies arc-length reparameterization for constant-speed traversal
273 *
274 * This can help maintain consistent visual speed along curves, especially for non-uniform point distributions.
275 */
276 void set_arc_length_reparameterization(bool enable);
277
278 /**
279 * @brief Set primitive topology for rendering
280 * @param topology Primitive topology (e.g. LINE_LIST, TRIANGLE_LIST)
281 *
282 * This determines how the vertex data is interpreted when rendered.
283 * For example, LINE_LIST treats every pair of vertices as a line segment,
284 * while TRIANGLE_LIST treats every triplet of vertices as a triangle.
285 */
286 void set_primitive_topology(Portal::Graphics::PrimitiveTopology topology) { m_primitive_topology = topology; }
287
289 {
290 return m_primitive_topology;
291 }
292
293private:
297 std::vector<LineVertex> m_vertices;
298 std::vector<std::pair<size_t, size_t>> m_connections;
299
300 Kinesis::InterpolationMode m_path_interpolation_mode { Kinesis::InterpolationMode::CATMULL_ROM };
301 Portal::Graphics::PrimitiveTopology m_primitive_topology { Portal::Graphics::PrimitiveTopology::LINE_LIST };
302 size_t m_samples_per_segment { 20 }; ///< Controls smoothness vs performance
303 bool m_use_arc_length_reparameterization {}; ///< Optional constant-speed
304
306 size_t m_k_neighbors { 3 };
307 float m_connection_radius { 1.0F };
308
309 glm::vec3 m_line_color { 1.0F, 1.0F, 1.0F };
310 float m_line_thickness { 1.0F };
311
312 bool m_force_uniform_color {}; ///< If true, all vertices use m_line_color instead of per-vertex color
313 bool m_force_uniform_thickness {}; ///< If true, all vertices use m_line_thickness instead of per-vertex thickness
314
315 void build_vertex_buffer();
316
317 void build_interpolated_path(
318 std::span<LineVertex> points,
319 size_t num_points);
320
321 void build_direct_connections(std::span<LineVertex> points, size_t num_points);
322
323 Eigen::MatrixXd points_to_eigen() const;
324};
325
326} // namespace MayaFlux::Nodes::GpuSync
History buffer for difference equations and recursive relations.
Base class for nodes that generate 3D geometry data.
const std::vector< std::pair< size_t, size_t > > & get_connections() const
Get connection edges (pairs of point indices)
std::function< std::vector< std::pair< size_t, size_t > >(const Eigen::MatrixXd &)> CustomConnectionFunction
Portal::Graphics::PrimitiveTopology get_primitive_topology() const override
Get primitive topology for rendering.
glm::vec3 get_line_color() const
Get current line color.
std::vector< std::pair< size_t, size_t > > m_connections
size_t get_connection_count() const
Get connection count (edge count)
bool should_force_uniform_color() const
Check if uniform color is forced.
size_t get_vertex_count() const
Get total vertex count (after interpolation)
void set_primitive_topology(Portal::Graphics::PrimitiveTopology topology)
Set primitive topology for rendering.
Generates dynamic mesh topology from sparse control points.
InterpolationMode
Mathematical interpolation methods.
PrimitiveTopology
Vertex assembly primitive topology.