MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
MayaFlux::Nodes::GpuSync::PathGeneratorNode Class Reference

Generates dense vertex paths from sparse control points or freehand drawing. More...

#include <PathGeneratorNode.hpp>

+ Inheritance diagram for MayaFlux::Nodes::GpuSync::PathGeneratorNode:
+ Collaboration diagram for MayaFlux::Nodes::GpuSync::PathGeneratorNode:

Public Types

using CustomPathFunction = std::function< glm::vec3(std::span< const LineVertex >, double)>
 

Public Member Functions

 PathGeneratorNode (Kinesis::InterpolationMode mode=Kinesis::InterpolationMode::QUADRATIC_BEZIER, Eigen::Index samples_per_segment=32, size_t max_control_points=64, double tension=0.5)
 Create path generator with interpolation mode.
 
 PathGeneratorNode (CustomPathFunction custom_func, Eigen::Index samples_per_segment=32, size_t max_control_points=64)
 Create path generator with custom interpolation function.
 
void add_control_point (const LineVertex &vertex)
 Add control point with full LineVertex data.
 
void draw_to (const LineVertex &vertex)
 Extend path with full LineVertex data.
 
void set_control_points (const std::vector< LineVertex > &vertices)
 Set all control points with full LineVertex data.
 
void update_control_point (size_t index, const LineVertex &vertex)
 Update specific control point with full LineVertex data.
 
LineVertex get_control_point (size_t index) const
 Get control point.
 
std::vector< LineVertexget_control_points () const
 Get all control points as vector.
 
void clear_path ()
 Clear all control points and generated vertices.
 
void set_path_color (const glm::vec3 &color, bool force_uniform=true)
 Set path color (applied to all generated vertices)
 
void force_uniform_color (bool should_force)
 Set uniform color mode.
 
bool should_force_uniform_color () const
 Check if uniform color mode is enabled.
 
void set_path_thickness (float thickness, bool force_uniform=true)
 Set path thickness (applied to all generated vertices)
 
void force_uniform_thickness (bool should_force)
 Set uniform thickness mode.
 
const glm::vec3 & get_path_color () const
 Get current path color.
 
const float & get_path_thickness () const
 Get current path thickness.
 
void set_interpolation_mode (Kinesis::InterpolationMode mode)
 Set interpolation mode.
 
void set_samples_per_segment (Eigen::Index samples)
 Set samples per segment.
 
void set_tension (double tension)
 Set tension parameter (for Catmull-Rom)
 
void parameterize_arc_length (bool enable)
 Enable/disable arc-length parameterization.
 
size_t get_control_point_count () const
 Get number of control points currently stored.
 
size_t get_control_point_capacity () const
 Get maximum control point capacity.
 
size_t get_generated_vertex_count () const
 Get number of generated vertices.
 
size_t get_all_vertex_count () const
 Get combined vertex count (control points + completed strokes + in-progress stroke)
 
const std::vector< LineVertex > & get_all_vertices () const
 Get all generated vertices (control points + completed strokes + in-progress stroke)
 
void compute_frame () override
 Compute frame - generates interpolated vertices from control points.
 
void complete ()
 Finish incremental drawing stroke.
 
void set_primitive_topology (Portal::Graphics::PrimitiveTopology topology)
 Set primitive topology for rendering.
 
Portal::Graphics::PrimitiveTopology get_primitive_topology () const override
 Get primitive topology for rendering.
 
- Public Member Functions inherited from MayaFlux::Nodes::GpuSync::GeometryWriterNode
 GeometryWriterNode (uint32_t initial_capacity=1024)
 Constructor.
 
 ~GeometryWriterNode () override=default
 
std::vector< double > process_batch (unsigned int num_samples) override
 Process batch for geometry generation.
 
std::span< const uint8_t > get_vertex_data () const
 Get raw vertex buffer data.
 
size_t get_vertex_buffer_size_bytes () const
 Get vertex buffer size in bytes.
 
uint32_t get_vertex_count () const
 Get number of vertices.
 
size_t get_vertex_stride () const
 Get stride (bytes per vertex)
 
void set_vertex_stride (size_t stride)
 Set vertex stride (bytes per vertex)
 
void resize_vertex_buffer (uint32_t vertex_count, bool preserve_data=false)
 Resize vertex buffer to hold specified number of vertices.
 
void set_vertex_data (const void *data, size_t size_bytes)
 Copy raw vertex data into buffer.
 
void set_vertex (uint32_t vertex_index, const void *data, size_t size_bytes)
 Set a single vertex by index.
 
std::span< const uint8_t > get_vertex (uint32_t vertex_index) const
 Get a single vertex by index.
 
template<typename T >
void set_vertices (std::span< const T > vertices)
 Set multiple vertices from typed array.
 
template<typename T >
void set_vertex_typed (uint32_t index, const T &vertex)
 Set a single vertex by index from typed data.
 
template<typename T >
get_vertex_typed (uint32_t index) const
 Get a single vertex by index as typed data.
 
void clear ()
 Clear vertex buffer and reset count.
 
void clear_and_resize (uint32_t vertex_count)
 Clear vertex buffer and resize to specified count.
 
void set_vertex_layout (const Kakshya::VertexLayout &layout)
 Set cached vertex layout.
 
std::optional< Kakshya::VertexLayoutget_vertex_layout () const
 Get cached vertex layout.
 
bool needs_layout_update () const
 Check if layout needs update.
 
void clear_layout_update_flag ()
 Clear layout update flag.
 
void save_state () override
 Save current geometry state.
 
void restore_state () override
 Restore saved geometry state.
 
bool needs_gpu_update () const override
 Check if vertex data or layout changed since last GPU sync.
 
bool needs_vertex_data_update () const
 Check if vertex data has changed since last GPU sync.
 
void mark_vertex_data_dirty (bool state)
 Set vertex data dirty flag.
 
void clear_gpu_update_flag () override
 Clear the dirty flag after GPU upload completes.
 
NodeContextget_last_context () override
 Retrieves the last created context object.
 
void update_context (double value) override
 Updates the context object with the current node state.
 
- Public Member Functions inherited from MayaFlux::Nodes::GpuSync::GpuSync
 ~GpuSync () override=default
 
double process_sample (double) override
 Single sample processing hook.
 
std::vector< double > process_batch (unsigned int num_samples) override
 Batch processing for GPU nodes.
 
- Public Member Functions inherited from MayaFlux::Nodes::Node
virtual ~Node ()=default
 Virtual destructor for proper cleanup of derived classes.
 
virtual void on_tick (const NodeHook &callback)
 Registers a callback to be called on each tick.
 
virtual void on_tick_if (const NodeCondition &condition, const NodeHook &callback)
 Registers a conditional callback.
 
virtual bool remove_hook (const NodeHook &callback)
 Removes a previously registered callback.
 
virtual bool remove_conditional_hook (const NodeCondition &callback)
 Removes a previously registered conditional callback.
 
virtual void remove_all_hooks ()
 Removes all registered callbacks.
 
virtual void reset_processed_state ()
 Resets the processed state of the node and any attached input nodes.
 
virtual double get_last_output ()
 Retrieves the most recent output value produced by the node.
 
void register_channel_usage (uint32_t channel_id)
 Mark the specificed channel as a processor/user.
 
void unregister_channel_usage (uint32_t channel_id)
 Removes the specified channel from the usage tracking.
 
bool is_used_by_channel (uint32_t channel_id) const
 Checks if the node is currently used by a specific channel.
 
void request_reset_from_channel (uint32_t channel_id)
 Requests a reset of the processed state from a specific channel.
 
const std::atomic< uint32_t > & get_channel_mask () const
 Retrieves the current bitmask of active channels using this node.
 
void set_gpu_compatible (bool compatible)
 Sets whether the node is compatible with GPU processing.
 
bool is_gpu_compatible () const
 Checks if the node supports GPU processing.
 
std::span< const float > get_gpu_data_buffer () const
 Provides access to the GPU data buffer.
 
void set_sample_rate (uint32_t sample_rate)
 
uint32_t get_sample_rate () const
 
bool try_claim_snapshot_context (uint64_t context_id)
 Attempt to claim snapshot context for this processing cycle.
 
bool is_in_snapshot_context (uint64_t context_id) const
 Check if currently in a snapshot context.
 
void release_snapshot_context (uint64_t context_id)
 Release snapshot context.
 
bool has_active_snapshot () const
 Check if node is currently being snapshotted by any context.
 
uint64_t get_active_snapshot_context () const
 Get the active snapshot context ID.
 
void add_buffer_reference ()
 Increments the buffer reference count This method is called when a new buffer starts using this node to ensure proper lifecycle management.
 
void remove_buffer_reference ()
 Decrements the buffer reference count This method is called when a buffer stops using this node to ensure proper lifecycle management.
 
bool mark_buffer_processed ()
 Marks the node as having been processed by a buffer.
 
void request_buffer_reset ()
 Requests a reset of the buffer state.
 
bool is_buffer_processed () const
 Checks if the buffer has been processed.
 
bool is_in_network () const
 Sets whether the node is part of a NodeNetwork.
 
void set_in_network (bool networked)
 Marks the node as being part of a NodeNetwork.
 
const RoutingStateget_routing_state () const
 Retrieves the current routing state of the network.
 
RoutingStateget_routing_state ()
 Retrieves the current routing state of the network (non-const)
 
bool needs_channel_routing () const
 Checks if the network is currently in a routing transition phase.
 

Private Member Functions

void generate_path_vertices ()
 
void generate_direct_path ()
 
void generate_custom_path ()
 
void generate_interpolated_path ()
 
void regenerate_geometry ()
 
void regenerate_segment_range (size_t start_ctrl_idx, size_t end_ctrl_idx)
 
void generate_curve_segment (const std::vector< LineVertex > &curve_verts, size_t start_idx, std::vector< LineVertex > &output)
 
void append_line_segment (const LineVertex &v0, const LineVertex &v1, std::vector< LineVertex > &output)
 

Private Attributes

Kinesis::InterpolationMode m_mode
 
CustomPathFunction m_custom_func
 
Memory::HistoryBuffer< LineVertexm_control_points
 
std::vector< LineVertexm_vertices
 
std::vector< LineVertexm_draw_vertices
 
std::vector< LineVertexm_completed_draws
 
std::vector< LineVertexm_combined_cache
 
std::vector< LineVertexm_draw_window
 
Eigen::Index m_samples_per_segment
 
double m_tension
 
glm::vec3 m_current_color { 1.0F, 1.0F, 1.0F }
 
float m_current_thickness { 2.0F }
 
bool m_force_uniform_color {}
 
bool m_force_uniform_thickness {}
 
bool m_geometry_dirty { true }
 
bool m_arc_length_parameterization {}
 
Portal::Graphics::PrimitiveTopology m_primitive_topology { Portal::Graphics::PrimitiveTopology::LINE_STRIP }
 
size_t m_dirty_segment_start { INVALID_SEGMENT }
 
size_t m_dirty_segment_end { INVALID_SEGMENT }
 

Static Private Attributes

static constexpr size_t INVALID_SEGMENT { std::numeric_limits<size_t>::max() }
 

Additional Inherited Members

- Public Attributes inherited from MayaFlux::Nodes::Node
bool m_fire_events_during_snapshot = false
 Internal flag controlling whether notify_tick fires during state snapshots Default: false (events don't fire during isolated buffer processing) Can be exposed in future if needed via concrete implementation in parent.
 
std::atomic< NodeStatem_state { NodeState::INACTIVE }
 Atomic state flag tracking the node's processing status.
 
std::atomic< uint32_t > m_modulator_count { 0 }
 Counter tracking how many other nodes are using this node as a modulator.
 
- Protected Member Functions inherited from MayaFlux::Nodes::GpuSync::GpuSync
void notify_tick (double) override
 GPU sync nodes don't emit tick callbacks.
 
- Protected Member Functions inherited from MayaFlux::Nodes::Node
virtual void reset_processed_state_internal ()
 Resets the processed state of the node directly.
 
- Protected Attributes inherited from MayaFlux::Nodes::GpuSync::GeometryWriterNode
std::vector< uint8_t > m_vertex_buffer
 Vertex data buffer (flat array of bytes)
 
uint32_t m_vertex_count {}
 Number of vertices in buffer.
 
size_t m_vertex_stride {}
 Bytes per vertex (stride for vertex buffer binding)
 
std::optional< Kakshya::VertexLayoutm_vertex_layout
 Cached vertex layout for descriptor binding.
 
bool m_needs_layout_update {}
 Flag indicating if layout needs update.
 
bool m_vertex_data_dirty { true }
 Flag: vertex data or layout changed since last GPU upload.
 
GeometryContext m_context { 0.0, {}, 0, 0 }
 
- Protected Attributes inherited from MayaFlux::Nodes::Node
double m_last_output { 0 }
 The most recent sample value generated by this oscillator.
 
bool m_gpu_compatible {}
 Flag indicating if the node supports GPU processing This flag is set by derived classes to indicate whether the node can be processed on the GPU.
 
std::vector< float > m_gpu_data_buffer
 GPU data buffer for context objects.
 
std::vector< NodeHookm_callbacks
 Collection of standard callback functions.
 
std::vector< std::pair< NodeHook, NodeCondition > > m_conditional_callbacks
 Collection of conditional callback functions with their predicates.
 
bool m_networked_node {}
 Flag indicating if the node is part of a NodeNetwork This flag is used to disable event firing when the node is managed within a NodeNetwork, preventing redundant or conflicting event notifications.
 
bool m_state_saved {}
 tracks if the node's state has been saved by a snapshot operation
 
uint32_t m_sample_rate { 48000 }
 Sample rate for audio processing, used for normalization.
 

Detailed Description

Generates dense vertex paths from sparse control points or freehand drawing.

Supports two distinct workflows:

  1. Parametric curve editing via control points (full regeneration on changes)
  2. Incremental freehand drawing (append-only strokes with smoothing on completion)

Both modes use Catmull-Rom or other interpolation methods to generate smooth curves. Produces LINE_STRIP topology output.

Philosophy:

  • Dual-mode design: parametric editing + incremental drawing in one node
  • Structural Reactivity: Only parametric paths (control points) are live. Changing interpolation modes, tension, or sampling density will rebuild the parametric curve but will NOT affect completed freehand strokes.
  • Control points are sparse input (artist/algorithm provides key positions)
  • Freehand strokes draw linearly in real-time, smooth on completion
  • Output vertices are dense (GPU draws smooth curves)
  • Interpolation happens CPU-side, leveraging Kinesis math primitives
  • Fixed memory allocation (real-time safe after construction)
  • Visual Reactivity: Changes to color and thickness are applied globally to both live control-point paths and "baked" freehand strokes.
  • Memory Efficiency: Freehand strokes are converted to static vertices upon completion; raw mouse data is discarded, preventing re-interpolation of baked strokes.

Parametric Mode Usage:

auto path = std::make_shared<PathGeneratorNode>(
32, // 32 vertices between each control point
100 // Store up to 100 control points
);
path->add_control_point({glm::vec3(0.0f, 0.0f, 0.0f)});
path->add_control_point({glm::vec3(0.5f, 0.5f, 0.0f)});
path->add_control_point({glm::vec3(1.0f, 0.0f, 0.0f)});
// Entire curve regenerates through all control points
auto buffer = std::make_shared<GeometryBuffer>(path);
buffer->setup_rendering({
.target_window = window,
.topology = PrimitiveTopology::LINE_STRIP
});

Freehand Drawing Mode Usage:

auto path = std::make_shared<PathGeneratorNode>(
32 // Smoothing resolution
);
// Real-time drawing (linear segments)
window->on_mouse_move([path](double x, double y) {
if (mouse_button_pressed) {
path->draw_to(screen_to_ndc(x, y)); // Appends linear segment
}
});
// Smooth the stroke when finished
window->on_mouse_release([path]() {
path->complete(); // Replaces linear segments with smooth curve
});
auto buffer = std::make_shared<GeometryBuffer>(path);
buffer->setup_rendering({.target_window = window});

Implementation Details:

  • Control points stored in fixed-capacity ring buffer (index [0] = newest)
  • Freehand strokes use sliding 4-point window for Catmull-Rom interpolation
  • Three vertex collections: control point geometry, completed strokes, in-progress stroke
  • Parametric edits trigger full regeneration; freehand is append-only
  • Both modes can coexist: control points and freehand strokes are independent

Definition at line 85 of file PathGeneratorNode.hpp.


The documentation for this class was generated from the following files: