MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
PathOperator.hpp
Go to the documentation of this file.
1#pragma once
4
6
7class MAYAFLUX_API PathOperator : public GraphicsOperator {
8public:
9 explicit PathOperator(
10 Kinesis::InterpolationMode mode = Kinesis::InterpolationMode::CATMULL_ROM,
11 Eigen::Index samples_per_segment = 32);
12
13 ~PathOperator() override { m_shutdown.store(true, std::memory_order_release); }
14
15 /**
16 * @brief Initialize a single path with given control points and properties.
17 */
18 void initialize(const std::vector<LineVertex>& vertices);
19
20 /**
21 * @brief Initialize multiple paths with given control points and properties.
22 * @param paths Vector of control point vectors, one per path.
23 * @param mode Interpolation mode for all paths.
24 */
25 void initialize_paths(
26 const std::vector<std::vector<LineVertex>>& paths,
28
29 /**
30 * @brief Add a new path with given control points and properties.
31 * @param control_points Vector of control points for the path.
32 * @param mode Interpolation mode for the path.
33 * @param default_samples_per_segment Number of samples to generate per segment (between control points).
34 * @param max_control_points Maximum number of control points to store in history for this path
35 * @param tension Tension parameter for applicable interpolation modes (e.g. Catmull-Rom)
36 */
37 void add_path(
38 const std::vector<LineVertex>& control_vertices,
39 Kinesis::InterpolationMode mode, uint32_t default_samples_per_segment = 32, size_t max_control_points = 64, double tension = 0.5);
40
41 /**
42 * @brief Add an externally constructed PathGeneratorNode subtype to the operator.
43 *
44 * Accepts any PathGeneratorNode subclass (e.g. LineSegmentNode) that was
45 * constructed and configured by the caller. The node is appended to m_paths
46 * and will participate in process(), get_vertex_data(), and extract_vertices()
47 * identically to nodes created by add_path().
48 *
49 * compute_frame() is called once before insertion so the node's vertex buffer
50 * is populated on the first frame.
51 *
52 * @param node Non-null shared_ptr to a PathGeneratorNode or subclass.
53 */
54 void add_node(std::shared_ptr<GpuSync::PathGeneratorNode> node);
55
56 void process(float dt) override;
57
58 [[nodiscard]] std::span<const uint8_t> get_vertex_data() const override;
59 [[nodiscard]] std::span<const uint8_t> get_vertex_data_for_collection(uint32_t idx) const override;
60 [[nodiscard]] Kakshya::VertexLayout get_vertex_layout() const override;
61 [[nodiscard]] size_t get_vertex_count() const override;
62 [[nodiscard]] bool is_vertex_data_dirty() const override;
63 void mark_vertex_data_clean() override;
64
65 /**
66 * @brief One DirtyVertexRange per path whose PathGeneratorNode needs a GPU
67 * update, so add_control_point() on one path re-uploads only that
68 * path's vertices.
69 *
70 * Ranges are in add_path() order, matching get_vertex_data() and
71 * build_cluster_ids(); group_index is the path index and feeds
72 * get_vertex_data_for_collection(). Empty when no path changed.
73 */
74 [[nodiscard]] std::vector<DirtyVertexRange> dirty_vertex_ranges() const override;
75
76 /**
77 * @brief True: add_control_point()/set_control_points()/clear_path() and
78 * every interpolation-parameter change route through a
79 * PathGeneratorNode dirty flag, so per-path ranges are complete.
80 */
81 [[nodiscard]] bool supports_incremental_upload() const override { return true; }
82
83 /**
84 * @brief Extract current vertex data as LineVertex array
85 * @return Vector of LineVertex with current positions, colors, thicknesses
86 */
87 [[nodiscard]] std::vector<LineVertex> extract_vertices() const;
88
89 void set_parameter(std::string_view param, double value) override;
90 [[nodiscard]] std::optional<double> query_state(std::string_view query) const override;
91 [[nodiscard]] std::string_view get_type_name() const override { return "Path"; }
92 [[nodiscard]] size_t get_point_count() const override;
93
94 /**
95 * @brief Overrides GraphicsOperator::build_cluster_ids() for real
96 * multi-path scenes.
97 * @return get_vertex_count() elements: entry i is the index of the
98 * path (in initialize_paths()/add_path() order) vertex i
99 * belongs to, in the same concatenation order get_vertex_data()
100 * itself produces. All zero when there is at most one path,
101 * matching the base class default exactly.
102 *
103 * A single PathOperator holding several independent paths is the same
104 * "many complete vertex-array packs" shape PhysicsOperator's collections
105 * and TopologyOperator's topologies are. Overriding this is what lets a
106 * cluster-scoped GpuFieldOperator binding, or the spatial hash's own
107 * cluster guard, treat each path as its own population without a
108 * dynamic_cast anywhere in the buffer layer.
109 */
110 [[nodiscard]] std::vector<uint32_t> build_cluster_ids() const override;
111
112 /**
113 * @brief Access a specific path node directly.
114 * @param i Collection index.
115 * @return Shared pointer to the PathGeneratorNode, or nullptr if out of range.
116 */
117 [[nodiscard]] std::shared_ptr<GpuSync::PathGeneratorNode> get_path(size_t i) const
118 {
119 if (i >= m_paths.size()) {
120 return nullptr;
121 }
122 return m_paths[i];
123 }
124
125 /**
126 * @brief Set the number of samples per segment for all paths.
127 * @param samples Number of samples to generate per segment between control points.
128 */
129 void set_samples_per_segment(Eigen::Index samples);
130
131 /**
132 * @brief Set the tension parameter for all paths (if supported by mode).
133 * @param tension Tension value (e.g., for cubic Hermite interpolation).
134 */
135 void set_tension(double tension);
136
137 /**
138 * @brief Set the global thickness for all paths.
139 * @param thickness Thickness value to apply to all paths.
140 */
141 void set_global_thickness(float thickness);
142
143 /**
144 * @brief Set the global color tint for all paths.
145 * @param color Color tint to apply to all paths (multiplied with individual tints).
146 */
147 void set_global_color(const glm::vec3& color);
148
149 /**
150 * @brief Get the number of paths currently managed by this operator.
151 * @return Number of path collections.
152 */
153 [[nodiscard]] size_t get_path_count() const { return m_paths.size(); }
154
155 const char* get_vertex_type_name() const override { return "PathVertex"; }
156
157protected:
158 void* get_data_at(size_t global_index) override;
159
160private:
161 std::vector<std::shared_ptr<GpuSync::PathGeneratorNode>> m_paths;
162
163 mutable std::vector<uint8_t> m_vertex_data_aggregate;
164
167 float m_default_thickness { 2.0F };
168
169 mutable std::atomic<uint32_t> m_access_token { 0 };
170 std::atomic<bool> m_shutdown { false };
171};
172
173} // namespace MayaFlux::Nodes::Network
float value
Operator that produces GPU-renderable geometry.
const char * get_vertex_type_name() const override
Get human-readable vertex type name (for validation/debugging)
std::vector< uint8_t > m_vertex_data_aggregate
Kinesis::InterpolationMode m_default_mode
std::vector< std::shared_ptr< GpuSync::PathGeneratorNode > > m_paths
size_t get_path_count() const
Get the number of paths currently managed by this operator.
bool supports_incremental_upload() const override
True: add_control_point()/set_control_points()/clear_path() and every interpolation-parameter change ...
std::string_view get_type_name() const override
Type name for introspection.
std::shared_ptr< GpuSync::PathGeneratorNode > get_path(size_t i) const
Access a specific path node directly.
void initialize()
Definition main.cpp:11
InterpolationMode
Mathematical interpolation methods.
Complete description of vertex data layout in a buffer.