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_control_points(max_control_points)
63 , m_samples_per_segment(samples_per_segment)
70 layout.vertex_count = 0;
73 m_vertices.reserve(samples_per_segment * max_control_points);
76 "Created PathGeneratorNode with mode {}, {} samples per segment, capacity {}",
77 static_cast<int>(mode), samples_per_segment, max_control_points);
82 Eigen::Index samples_per_segment,
83 size_t max_control_points)
85 , m_mode(Kinesis::InterpolationMode::CUSTOM)
86 , m_custom_func(
std::move(custom_func))
87 , m_control_points(max_control_points)
88 , m_samples_per_segment(samples_per_segment)
95 layout.vertex_count = 0;
98 m_vertices.reserve(samples_per_segment * max_control_points);
101 "Created PathGeneratorNode with custom function");
112 const std::vector<LineVertex>& curve_verts,
114 std::vector<LineVertex>& output)
116 if (start_idx + 3 >= curve_verts.size()) {
120 Eigen::MatrixXd segment_controls(3, 4);
121 for (Eigen::Index i = 0; i < 4; ++i) {
122 const auto& pt = curve_verts[start_idx + i].position;
123 segment_controls.col(i) << pt.x, pt.y, pt.z;
138 for (Eigen::Index i = 0; i < interpolated.cols() - 1; ++i) {
139 float t0 =
static_cast<float>(i) /
static_cast<float>(interpolated.cols() - 1);
140 float t1 =
static_cast<float>(i + 1) /
static_cast<float>(interpolated.cols() - 1);
142 size_t ctrl_idx0 = start_idx + std::min(
static_cast<size_t>(t0 * 3),
size_t(3));
143 size_t ctrl_idx1 = start_idx + std::min(
static_cast<size_t>(t1 * 3),
size_t(3));
151 glm::vec3 p0(interpolated(0, i), interpolated(1, i), interpolated(2, i));
152 glm::vec3 p1(interpolated(0, i + 1), interpolated(1, i + 1), interpolated(2, i + 1));
154 output.push_back({ p0, color0, thick0 });
155 output.push_back({ p1, color1, thick1 });
162 std::vector<LineVertex>& output)
170 output.push_back({ v0.
position, color0, thick0 });
171 output.push_back({ v1.
position, color1, thick1 });
194 for (
const auto& v : vertices) {
206 "Control point index {} out of range (count: {})",
213 auto range = calculate_affected_segment_range(
235 "Control point index {} out of range (count: {})",
246 std::vector<LineVertex> positions;
247 positions.reserve(view.size());
248 for (
const auto& v : view) {
249 positions.push_back(v);
298 v.thickness = thickness;
301 v.thickness = thickness;
351 if (num_points < 2) {
371 for (
const auto& v : view) {
378 .thickness = thickness });
385 const size_t num_points = view.size();
390 for (Eigen::Index i = 0; i < total_samples; ++i) {
391 double t =
static_cast<double>(i) /
static_cast<double>(total_samples - 1);
393 auto ctrl_idx = std::min<size_t>(
static_cast<size_t>(t *
float(num_points - 1)), num_points - 1);
400 .thickness = thickness
408 std::vector<LineVertex> control_vec(control_view.begin(), control_view.end());
410 for (
size_t i = 0; i + 3 < control_vec.size(); ++i) {
436 const size_t num_points = view.size();
438 if (start_ctrl_idx >= num_points || end_ctrl_idx >= num_points) {
440 "Invalid segment range [{}, {}] for {} control points",
441 start_ctrl_idx, end_ctrl_idx, num_points);
445 std::vector<LineVertex> segment_verts;
446 for (
size_t i = start_ctrl_idx; i <= end_ctrl_idx; ++i) {
447 segment_verts.push_back(view[i]);
452 std::vector<LineVertex> new_segment;
454 for (
size_t i = 0; i + 3 < segment_verts.size(); ++i) {
492#ifdef MAYAFLUX_PLATFORM_MACOS
493 std::vector<LineVertex> expanded = expand_lines_to_triangles(
m_combined_cache);
494 set_vertices<LineVertex>(std::span { expanded.data(), expanded.size() });
497 layout->vertex_count =
static_cast<uint32_t
>(expanded.size());
512 "Not enough points in draw window to generate curve segment ({} points)",
524 std::vector<LineVertex> smoothed;
526 size_t start_idx = 0;
532 for (
size_t i = start_idx + 1; i <
m_draw_window.size(); ++i) {
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
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.
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()
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 force_uniform_color(bool should_force)
Set uniform color mode.
Eigen::Index m_samples_per_segment
bool m_arc_length_parameterization
Memory::HistoryBuffer< LineVertex > m_control_points
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.
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)
void generate_interpolated_path()
void draw_to(const LineVertex &vertex)
Extend path with full LineVertex data.
void generate_curve_segment(const std::vector< LineVertex > &curve_verts, size_t start_idx, std::vector< LineVertex > &output)
@ NodeProcessing
Node graph processing (Nodes::NodeGraphManager)
@ Nodes
DSP Generator and Filter Nodes, graph pipeline, node management.
std::vector< Nodes::LineVertex > reparameterize_by_arc_length(const std::vector< Nodes::LineVertex > &path_vertices, size_t num_samples)
Resample path vertices for arc-length parameterization.
Eigen::MatrixXd generate_interpolated_points(const Eigen::MatrixXd &control_points, Eigen::Index num_samples, InterpolationMode mode, double tension)
Generate interpolated points from control points.
InterpolationMode
Mathematical interpolation methods.
static VertexLayout for_lines(uint32_t stride=36)
Factory: Create layout for line primitives (position, color, thickness)