16 SegmentRange calculate_affected_segment_range(
18 size_t total_controls,
20 Eigen::Index samples_per_segment)
22 SegmentRange
range {};
27 range.start_control_idx = (control_idx > 0) ? control_idx - 1 : 0;
28 range.end_control_idx = std::min(control_idx + 2, total_controls - 1);
33 range.start_control_idx = (control_idx / 4) * 4;
34 range.end_control_idx = std::min(
range.start_control_idx + 3, total_controls - 1);
38 range.start_control_idx = (control_idx / 3) * 3;
39 range.end_control_idx = std::min(
range.start_control_idx + 2, total_controls - 1);
43 range.start_control_idx = control_idx;
44 range.end_control_idx = control_idx;
48 range.start_vertex_idx =
range.start_control_idx * samples_per_segment;
49 range.end_vertex_idx = (
range.end_control_idx + 1) * samples_per_segment;
57 Eigen::Index samples_per_segment,
58 size_t max_control_points,
62 , m_max_control_points(max_control_points)
63 , m_samples_per_segment(samples_per_segment)
70 layout.vertex_count = 0;
74 m_vertices.reserve(samples_per_segment * max_control_points);
77 "Created PathGeneratorNode with mode {}, {} samples per segment, capacity {}",
78 static_cast<int>(mode), samples_per_segment, max_control_points);
83 Eigen::Index samples_per_segment,
84 size_t max_control_points)
86 , m_mode(Kinesis::InterpolationMode::CUSTOM)
87 , m_custom_func(
std::move(custom_func))
88 , m_max_control_points(max_control_points)
89 , m_samples_per_segment(samples_per_segment)
96 layout.vertex_count = 0;
100 m_vertices.reserve(samples_per_segment * max_control_points);
103 "Created PathGeneratorNode with custom function");
122 const std::vector<LineVertex>& curve_verts,
132 for (
size_t i = 0; i < span; ++i) {
133 const size_t c0 = start_idx + std::min((i * 3) / span,
size_t(3));
134 const size_t c1 = start_idx + std::min(((i + 1) * 3) / span,
size_t(3));
148 const std::vector<LineVertex>& curve_verts,
152 if (start_idx + 3 >= curve_verts.size()) {
158 for (
size_t i = 0; i < 4; ++i) {
159 const auto& pt = curve_verts[start_idx + i].position;
180 const double* x = curve->data();
181 const double* y = x +
count;
182 const double* z = y +
count;
184 for (
size_t i = 0; i <
count - 1; ++i) {
186 static_cast<float>(x[i]),
static_cast<float>(y[i]),
static_cast<float>(z[i])
189 static_cast<float>(x[i + 1]),
static_cast<float>(y[i + 1]),
static_cast<float>(z[i + 1])
200 for (
size_t i = 0; i < n; ++i) {
210 if (num_points == 0 || total < 2) {
213 for (
size_t i = 0; i < total; ++i) {
214 const size_t ctrl_idx = std::min((i * (num_points - 1)) / (total - 1), num_points - 1);
228 if (
m_vertices.size() < windows * per_window) {
232 for (
size_t w = 0; w < windows; ++w) {
240 std::vector<LineVertex>&
output)
248 output.push_back({ .position = v0.
position, .color = color0, .thickness = thick0 });
249 output.push_back({ .position = v1.
position, .color = color1, .thickness = thick1 });
285 "Control point index {} out of range (count: {})",
292 auto range = calculate_affected_segment_range(
314 "Control point index {} out of range (count: {})",
371 v.thickness = thickness;
374 v.thickness = thickness;
424 if (num_points < 2) {
450 .thickness = thickness });
461 for (Eigen::Index i = 0; i < total_samples; ++i) {
462 double t =
static_cast<double>(i) /
static_cast<double>(total_samples - 1);
464 auto ctrl_idx = std::min<size_t>(
static_cast<size_t>(t *
float(num_points - 1)), num_points - 1);
471 .thickness = thickness
486 m_vertices.resize(base + windows * per_window);
488 for (
size_t w = 0; w < windows; ++w) {
515 if (start_ctrl_idx >= num_points || end_ctrl_idx >= num_points) {
517 "Invalid segment range [{}, {}] for {} control points",
518 start_ctrl_idx, end_ctrl_idx, num_points);
524 for (
size_t i = start_ctrl_idx; i <= end_ctrl_idx; ++i) {
540 for (
size_t w = 0; w < windows; ++w) {
577#ifdef MAYAFLUX_PLATFORM_MACOS
579 set_vertices<LineVertex>(std::span { m_expand_cache.data(), m_expand_cache.size() });
582 layout->vertex_count =
static_cast<uint32_t
>(m_expand_cache.size());
599 "Not enough points in draw window to generate curve segment ({} points)",
617 for (
size_t w = 0; w < windows; ++w) {
621 for (
size_t i = windows + 1; i <
m_draw_window.size(); ++i) {
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
std::shared_ptr< Core::VKImage > output
void reparameterize_planar(std::span< const double > points, size_t dim, Eigen::Index point_count, Eigen::Index num_samples, std::vector< double > &out)
Resample a polyline to uniform arc length, coordinate-major.
void evaluate_planar(std::span< const double > control_points, size_t dim, Eigen::Index num_samples, std::vector< double > &out)
Evaluate a curve into a coordinate-major buffer.
void configure(InterpolationMode mode, double tension)
Re-resolve the kernel.
bool m_vertex_data_dirty
Flag: vertex data or layout changed since last GPU upload.
std::optional< Kakshya::VertexLayout > get_vertex_layout() const
Get cached vertex layout.
void set_vertex_layout(const Kakshya::VertexLayout &layout)
Set cached vertex layout.
void resize_vertex_buffer(uint32_t vertex_count, bool preserve_data=false)
Resize vertex buffer to hold specified number of vertices.
void set_vertex_stride(size_t stride)
Set vertex stride (bytes per vertex)
bool m_needs_layout_update
Flag indicating if layout needs update.
Base class for nodes that generate 3D geometry data.
void generate_path_vertices()
void set_samples_per_segment(Eigen::Index samples)
Set samples per segment.
std::array< double, 12 > m_segment_controls
void compute_frame() override
Compute frame - generates interpolated vertices from control points.
std::vector< LineVertex > m_draw_window
size_t m_dirty_segment_start
void generate_custom_path()
void regenerate_geometry()
void refresh_attributes()
Rewrite colour and thickness over existing geometry, no curve evaluation.
size_t vertices_per_window() const
Vertices emitted per four-point window.
Kinesis::CurveEvaluator m_evaluator
Kinesis::InterpolationMode m_mode
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.
bool m_force_uniform_thickness
std::function< glm::vec3(std::span< const LineVertex >, double)> CustomPathFunction
void set_tension(double tension)
Set tension parameter (for Catmull-Rom)
void set_path_color(const glm::vec3 &color, bool force_uniform=true)
Set path color (applied to all generated vertices)
void write_curve_segment(const std::vector< LineVertex > &curve_verts, size_t start_idx, LineVertex *dst)
Evaluate one window and write its vertices.
std::vector< LineVertex > m_control_points
Control points, newest first: index 0 is the most recently added.
std::vector< double > m_curve_secondary
void force_uniform_color(bool should_force)
Set uniform color mode.
Eigen::Index m_samples_per_segment
bool m_arc_length_parameterization
glm::vec3 m_current_color
size_t m_dirty_segment_end
void complete()
Finish incremental drawing stroke.
float m_current_thickness
std::vector< LineVertex > m_completed_draws
CustomPathFunction m_custom_func
std::vector< LineVertex > m_vertices
void set_interpolation_mode(Kinesis::InterpolationMode mode)
Set interpolation mode.
void generate_direct_path()
void update_control_point(size_t index, const LineVertex &vertex)
Update specific control point with full LineVertex data.
std::vector< LineVertex > get_control_points() const
Get all control points as vector.
LineVertex get_control_point(size_t index) const
Get control point.
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.
void parameterize_arc_length(bool enable)
Enable/disable arc-length parameterization.
bool m_force_uniform_color
void set_control_points(const std::vector< LineVertex > &vertices)
Set all control points with full LineVertex data.
std::vector< LineVertex > m_range_cache
void add_control_point(const LineVertex &vertex)
Add control point with full LineVertex data.
void append_line_segment(const LineVertex &v0, const LineVertex &v1, std::vector< LineVertex > &output)
static constexpr size_t INVALID_SEGMENT
void clear_path()
Clear all control points and generated vertices.
std::vector< LineVertex > m_draw_vertices
std::vector< LineVertex > m_combined_cache
void regenerate_segment_range(size_t start_ctrl_idx, size_t end_ctrl_idx)
size_t m_max_control_points
void write_segment_attributes(const std::vector< LineVertex > &curve_verts, size_t start_idx, LineVertex *dst) const
Write colour and thickness for one window, leaving positions intact.
std::vector< double > m_curve_primary
void generate_interpolated_path()
void draw_to(const LineVertex &vertex)
Extend path with full LineVertex data.
@ NodeProcessing
Node graph processing (Nodes::NodeGraphManager)
@ Nodes
DSP Generator and Filter Nodes, graph pipeline, node management.
std::vector< double > range(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Value range (max - min) per window.
InterpolationMode
Mathematical interpolation methods.
Kakshya::LineVertex LineVertex
Vertex type for line primitives (LINE_LIST / LINE_STRIP topology)
static VertexLayout for_lines(uint32_t stride=60)
Factory: layout for LineVertex (position, color, thickness, uv, normal, tangent)