MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
TopologyOperator.cpp
Go to the documentation of this file.
3
5
6//-----------------------------------------------------------------------------
7// Construction
8//-----------------------------------------------------------------------------
9
11 : m_default_mode(mode)
12{
14 "TopologyOperator created with mode {}", static_cast<int>(mode));
15}
16
17//-----------------------------------------------------------------------------
18// GraphicsOperator Interface (Simple Initialization)
19//-----------------------------------------------------------------------------
20
21void TopologyOperator::initialize(const std::vector<LineVertex>& vertices)
22{
23 if (vertices.empty()) {
25 "Cannot initialize topology with zero vertices");
26 return;
27 }
28
29 m_topologies.clear();
31
33 "TopologyOperator initialized with {} points in 1 topology",
34 vertices.size());
35}
36
37//-----------------------------------------------------------------------------
38// Advanced Initialization (Multiple Topologies)
39//-----------------------------------------------------------------------------
40
42 const std::vector<std::vector<LineVertex>>& topologies,
44{
45 for (const auto& topo : topologies) {
46 add_topology(topo, mode);
47 }
48
50 "TopologyOperator initialized with {} topologies",
51 topologies.size());
52}
53
55 const std::vector<LineVertex>& vertices,
57{
58 if (vertices.empty()) {
60 "Cannot add topology with zero vertices");
61 return;
62 }
63
64 auto topology = std::make_shared<GpuSync::TopologyGeneratorNode>(mode, true, 1024);
65
66 topology->set_points(vertices);
67 topology->compute_frame();
68
69 uint32_t expected = 0;
70 while (!m_access_token.compare_exchange_weak(expected, 1,
71 std::memory_order_acquire, std::memory_order_relaxed)) {
72 if (m_shutdown.load(std::memory_order_relaxed))
73 return;
74 expected = 0;
75 }
76
77 m_topologies.push_back(std::move(topology));
78
79 m_access_token.store(0, std::memory_order_release);
80
82 "Added topology #{} with {} points, {} connections",
83 m_topologies.size(), vertices.size(),
84 m_topologies.back()->get_connection_count());
85}
86
87//-----------------------------------------------------------------------------
88// Processing
89//-----------------------------------------------------------------------------
90
91void TopologyOperator::process(float /*dt*/)
92{
93 uint32_t expected = 0;
94 while (!m_access_token.compare_exchange_weak(expected, 1,
95 std::memory_order_acquire, std::memory_order_relaxed)) {
96 if (m_shutdown.load(std::memory_order_relaxed))
97 return;
98 expected = 0;
99 }
100
101 for (auto& topology : m_topologies) {
102 topology->compute_frame();
103 }
104
105 m_access_token.store(0, std::memory_order_release);
106}
107
108//-----------------------------------------------------------------------------
109// GraphicsOperator Interface (Data Extraction)
110//-----------------------------------------------------------------------------
111
112std::vector<LineVertex> TopologyOperator::extract_vertices() const
113{
114 std::vector<LineVertex> positions;
115
116 for (const auto& topology : m_topologies) {
117 const auto points = topology->get_points();
118 positions.insert(positions.end(), points.rbegin(), points.rend());
119 }
120
121 return positions;
122}
123
124std::span<const uint8_t> TopologyOperator::get_vertex_data_for_collection(uint32_t idx) const
125{
126 if (m_topologies.empty() || idx >= m_topologies.size()) {
127 return {};
128 }
129 return m_topologies[idx]->get_vertex_data();
130}
131
132std::span<const uint8_t> TopologyOperator::get_vertex_data() const
133{
135 for (const auto& group : m_topologies) {
136 auto span = group->get_vertex_data();
139 span.begin(), span.end());
140 }
141 return { m_vertex_data_aggregate.data(), m_vertex_data_aggregate.size() };
142}
143
145{
146 if (m_topologies.empty()) {
147 return {};
148 }
149
150 auto layout_opt = m_topologies[0]->get_vertex_layout();
151 if (!layout_opt) {
152 return {};
153 }
154
155 auto layout = *layout_opt;
156 layout.vertex_count = static_cast<uint32_t>(get_vertex_count());
157 return layout;
158}
159
160std::optional<Portal::Graphics::PrimitiveTopology> TopologyOperator::declared_topology() const
161{
162 if (m_topologies.empty()) {
163 return std::nullopt;
164 }
165 return m_topologies[0]->get_primitive_topology();
166}
167
169{
170 size_t total = 0;
171 for (const auto& topology : m_topologies) {
172 total += topology->get_vertex_count();
173 }
174 return total;
175}
176
178{
179 return std::ranges::any_of(
181 [](const auto& group) { return group->needs_gpu_update(); });
182}
183
185{
186 for (auto& topology : m_topologies) {
187 topology->clear_gpu_update_flag();
188 }
189}
190
191std::vector<GraphicsOperator::DirtyVertexRange> TopologyOperator::dirty_vertex_ranges() const
192{
193 std::vector<DirtyVertexRange> ranges;
194
195 uint32_t offset = 0;
196 uint32_t index = 0;
197 for (const auto& topology : m_topologies) {
198 const auto count = static_cast<uint32_t>(topology->get_vertex_count());
199 if (topology->needs_gpu_update()) {
200 ranges.push_back(DirtyVertexRange {
202 .vertex_offset = offset,
203 .vertex_count = count });
204 }
205 offset += count;
206 ++index;
207 }
208
209 return ranges;
210}
211
212std::vector<DrawRun> TopologyOperator::topology_runs() const
213{
214 std::vector<DrawRun> runs;
215 uint32_t offset = 0;
216
217 for (const auto& tp : m_topologies) {
218 const auto count = static_cast<uint32_t>(tp->get_vertex_count());
219 const auto topo = tp->get_primitive_topology();
220
221 if (!runs.empty() && runs.back().topology == topo && is_concatenable_topology(topo)) {
222 runs.back().vertex_count += count;
223 } else {
224 runs.push_back(DrawRun { .topology = topo, .vertex_offset = offset, .vertex_count = count });
225 }
226
227 offset += count;
228 }
229
230 return runs;
231}
232
234{
235 size_t total = 0;
236 for (const auto& topology : m_topologies) {
237 total += topology->get_point_count();
238 }
239 return total;
240}
241
242std::vector<uint32_t> TopologyOperator::build_cluster_ids() const
243{
244 std::vector<uint32_t> ids(get_vertex_count(), 0U);
245
246 if (m_topologies.size() <= 1) {
247 return ids;
248 }
249
250 size_t offset = 0;
251 uint32_t cluster = 0;
252 for (const auto& topology : m_topologies) {
253 const size_t count = topology->get_vertex_count();
254 for (size_t i = 0; i < count && offset + i < ids.size(); ++i) {
255 ids[offset + i] = cluster;
256 }
257 offset += count;
258 ++cluster;
259 }
260
261 return ids;
262}
263
264//-----------------------------------------------------------------------------
265// Parameter Control
266//-----------------------------------------------------------------------------
267
268void TopologyOperator::set_parameter(std::string_view param, double value)
269{
270 if (param == "connection_radius") {
271 for (auto& topology : m_topologies) {
272 topology->set_connection_radius(static_cast<float>(value));
273 }
274 } else if (param == "k_neighbors") {
275 for (auto& topology : m_topologies) {
276 topology->set_k_neighbors(static_cast<size_t>(value));
277 }
278 } else if (param == "line_thickness") {
279 for (auto& topology : m_topologies) {
280 topology->set_line_thickness(static_cast<float>(value));
281 }
282 }
283}
284
285std::optional<double> TopologyOperator::query_state(std::string_view query) const
286{
287 if (query == "point_count") {
288 return static_cast<double>(get_point_count());
289 }
290
291 if (query == "connection_count") {
292 size_t total_connections = 0;
293 for (const auto& topology : m_topologies) {
294 total_connections += topology->get_connection_count();
295 }
296 return static_cast<double>(total_connections);
297 }
298
299 if (query == "topology_count") {
300 return static_cast<double>(m_topologies.size());
301 }
302 return std::nullopt;
303}
304
305//-----------------------------------------------------------------------------
306// Topology Configuration
307//-----------------------------------------------------------------------------
308
310{
311 for (auto& topology : m_topologies) {
312 topology->set_connection_radius(radius);
313 }
314}
315
317{
318 for (auto& topology : m_topologies) {
319 topology->set_line_thickness(thickness);
320 }
321}
322
324{
325 for (auto& topology : m_topologies) {
326 topology->set_line_color(color);
327 }
328}
329
331{
332 for (auto& topology : m_topologies) {
333 topology->set_samples_per_segment(samples);
334 }
335}
336
337void TopologyOperator::set_vertices(const std::vector<LineVertex>& vertices)
338{
339 if (m_topologies.empty() || vertices.size() != get_point_count()) {
340 initialize(vertices);
341 return;
342 }
343
344 uint32_t expected = 0;
345 while (!m_access_token.compare_exchange_weak(expected, 1,
346 std::memory_order_acquire, std::memory_order_relaxed)) {
347 if (m_shutdown.load(std::memory_order_relaxed))
348 return;
349 expected = 0;
350 }
351
352 auto first = vertices.begin();
353 for (auto& topology : m_topologies) {
354 const auto count = static_cast<std::ptrdiff_t>(topology->get_point_count());
355 topology->set_points(std::vector<LineVertex>(first, first + count));
356 topology->compute_frame();
357 first += count;
358 }
359
360 m_access_token.store(0, std::memory_order_release);
361}
362
363void* TopologyOperator::get_data_at(size_t /*global_index*/)
364{
365 return nullptr;
366}
367
368} // namespace MayaFlux::Nodes::Network
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
uint64_t offset
Definition Composite.cpp:10
glm::vec3 color
Definition Decoder.cpp:97
std::vector< glm::vec2 > * points
float radius
uint32_t total
uint32_t mode
std::vector< uint64_t > ids
std::vector< glm::vec3 > positions
PrimitiveTopology topology
glm::vec3 value
uint32_t index
Definition VKDevice.cpp:122
size_t count
void * get_data_at(size_t global_index) override
Get mutable access to point at global index.
void set_vertices(const std::vector< LineVertex > &vertices)
Replace every point, in extract_vertices() order, keeping the topologies.
void set_samples_per_segment(size_t samples)
Set number of samples per segment for interpolation for all topologies.
std::vector< uint32_t > build_cluster_ids() const override
Overrides GraphicsOperator::build_cluster_ids() for real multi-topology scenes.
void add_topology(const std::vector< LineVertex > &vertices, Kinesis::ProximityMode mode)
Add a single topology with full per-vertex control.
std::span< const uint8_t > get_vertex_data_for_collection(uint32_t idx) const override
Get vertex data for specific collection (if multiple)
void initialize(const std::vector< LineVertex > &vertices)
Initialize a single topology with single set of vertices.
void process(float dt) override
Process for one batch cycle.
bool is_vertex_data_dirty() const override
Check if geometry changed this frame.
void set_parameter(std::string_view param, double value) override
Set operator parameter.
std::optional< Portal::Graphics::PrimitiveTopology > declared_topology() const override
Forwards to the first topology's own get_primitive_topology().
void set_connection_radius(float radius)
Set the connection radius for topology generation.
size_t get_vertex_count() const override
Get number of vertices (may differ from point count for topology/path)
std::vector< LineVertex > extract_vertices() const
Extract current vertex data as LineVertex array.
void set_global_line_color(const glm::vec3 &color)
Set the line color for all topologies.
Kakshya::VertexLayout get_vertex_layout() const override
Get vertex layout describing vertex structure.
std::vector< DirtyVertexRange > dirty_vertex_ranges() const override
One DirtyVertexRange per topology whose TopologyGeneratorNode needs a GPU update, so add_topology() o...
std::vector< std::shared_ptr< GpuSync::TopologyGeneratorNode > > m_topologies
std::span< const uint8_t > get_vertex_data() const override
Get vertex data for GPU upload.
void set_global_line_thickness(float thickness)
Set the number of neighbors (k) for K-Nearest topology mode.
void mark_vertex_data_clean() override
Clear dirty flag after GPU upload.
std::vector< DrawRun > topology_runs() const override
Coalesces adjacent topology graphs sharing a concatenable topology into one run.
size_t get_point_count() const override
Get source point count (before topology expansion)
void initialize_topologies(const std::vector< std::vector< LineVertex > > &topologies, Kinesis::ProximityMode mode)
Initialize multiple topologies with given positions and properties.
std::optional< double > query_state(std::string_view query) const override
Query operator internal state.
TopologyOperator(Kinesis::ProximityMode mode=Kinesis::ProximityMode::K_NEAREST)
void initialize()
Definition main.cpp:10
@ NodeProcessing
Node graph processing (Nodes::NodeGraphManager)
@ Nodes
DSP Generator and Filter Nodes, graph pipeline, node management.
uint32_t vertex_count
Total number of vertices in this buffer.
Complete description of vertex data layout in a buffer.
A contiguous span of vertex records that changed since the last mark_vertex_data_clean().
One contiguous span of vertices sharing a primitive topology.