MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Geometry.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Mapped.hpp"
4
6class Context;
7}
8
10
11/**
12 * @file Geometry.hpp
13 * @brief Illustrative geometry functions for common Mapped use cases.
14 *
15 * These are starting points for reading and understanding the GeometryFn
16 * contract, not the primary or idiomatic way to use Mapped in MayaFlux.
17 *
18 * The idiomatic use is a custom geometry function that writes from whatever
19 * data source makes sense: mouse pixel coordinates written directly as buffer
20 * data, microphone energy mapped to a spatial form, a node output driving
21 * vertex positions, a tendency field evaluated at runtime. The function
22 * receives a value and an output byte buffer — what it does with those is
23 * unconstrained.
24 *
25 * The helpers below demonstrate the pattern concretely. They are not
26 * privileged and carry no special status in the framework.
27 */
28
29/**
30 * @brief Write a vertex array into a GeometryFn output buffer.
31 * @param out Output buffer. Resized to fit @p verts exactly.
32 * @param verts Vertices to copy.
33 */
34template <typename V>
35void write_verts(std::vector<uint8_t>& out, const std::vector<V>& verts)
36{
37 out.resize(verts.size() * sizeof(V));
38 std::memcpy(out.data(), verts.data(), out.size());
39}
40
41/**
42 * @brief Write a contiguous range of trivially-copyable vertices into a GeometryFn output buffer.
43 */
44template <typename V>
45 requires std::ranges::contiguous_range<V>
46 && std::is_trivially_copyable_v<std::ranges::range_value_t<V>>
47void write_verts(std::vector<uint8_t>& out, const V& verts)
48{
49 const size_t n = std::ranges::size(verts) * sizeof(std::ranges::range_value_t<V>);
50 out.resize(n);
51 std::memcpy(out.data(), std::ranges::data(verts), n);
52}
53
54template <typename V>
55 requires std::is_trivially_copyable_v<V>
56 && (!std::ranges::range<V>)
57void write_verts(std::vector<uint8_t>& out, const V& v)
58{
59 out.resize(sizeof(v));
60 std::memcpy(out.data(), &v, sizeof(v));
61}
62
63// =============================================================================
64// Horizontal fader
65//
66// Value in [0, 1] moves a handle quad along a track quad.
67// Two quads: track (static) and handle (value-driven).
68// Both written as TRIANGLE_STRIP pairs into a single buffer.
69//
70// Track: full extent of bounds.
71// Handle: small square at x = bounds.min.x + value * bounds.width().
72//
73// Hit region follows the handle, updated on every sync().
74// =============================================================================
75
76/**
77 * @brief Geometry function for a horizontal fader in NDC space.
78 * @param bounds Full extent of the fader in NDC.
79 * @param handle_w Handle width in NDC units.
80 * @param track_color Track quad color.
81 * @param handle_color Handle quad color.
82 */
83[[nodiscard]] MAYAFLUX_API GeometryFn<float> horizontal_fader(
84 Kinesis::AABB2D bounds,
85 float handle_w,
86 glm::vec3 track_color = glm::vec3(0.3F),
87 glm::vec3 handle_color = glm::vec3(0.9F));
88
89// =============================================================================
90// Vertical fader
91//
92// Symmetric counterpart to horizontal_fader. Value in [0, 1] moves a handle
93// quad upward along a track quad.
94//
95// Track: thin vertical band through the center of bounds.
96// Handle: small square at y = bounds.min.y + value * (bounds.height() - handle_h).
97//
98// Hit region follows the handle, updated on every sync().
99// Topology: TRIANGLE_STRIP (two quad pairs via to_mesh_vertices).
100// =============================================================================
101
102/**
103 * @brief Geometry function for a vertical fader in NDC space.
104 * @param bounds Full extent of the fader in NDC.
105 * @param handle_h Handle height in NDC units.
106 * @param track_color Track quad color.
107 * @param handle_color Handle quad color.
108 */
109[[nodiscard]] MAYAFLUX_API GeometryFn<float> vertical_fader(
110 Kinesis::AABB2D bounds,
111 float handle_h,
112 glm::vec3 track_color = glm::vec3(0.3F),
113 glm::vec3 handle_color = glm::vec3(0.9F));
114
115// =============================================================================
116// Radial / arc
117//
118// Value in [0, 1] sweeps an indicator line around a center point.
119// angle_start and angle_end in radians, measured from +X, CCW.
120// Produces a LINE_LIST of two vertices: center to indicator tip.
121// =============================================================================
122
123/**
124 * @brief Geometry function for a radial indicator in NDC space.
125 * @param center Arc center in NDC.
126 * @param radius Arc radius in NDC units.
127 * @param angle_start Start angle in radians (value = 0).
128 * @param angle_end End angle in radians (value = 1).
129 * @param color Line color.
130 */
131[[nodiscard]] MAYAFLUX_API GeometryFn<float> radial(
132 glm::vec2 center,
133 float radius,
134 float angle_start,
135 float angle_end,
136 glm::vec3 color = glm::vec3(0.9F));
137
138// =============================================================================
139// Point
140//
141// Value is glm::vec2 in NDC space. Produces a single POINT_LIST vertex.
142// Hit region is a circle centered on the point.
143// Use as a cursor follower, node handle, or any positioned point primitive.
144// =============================================================================
145
146/**
147 * @brief Geometry function for a positioned point in NDC space.
148 *
149 * Value type is glm::vec2 (NDC position). Renders a single PointVertex
150 * and sets a circular hit region centered on the position. Suitable as
151 * a cursor follower, node handle, or any draggable point primitive.
152 *
153 * @param color Point color.
154 * @param size Point size in pixels.
155 * @param hit_radius Hit region radius in NDC units.
156 */
157[[nodiscard]] MAYAFLUX_API GeometryFn<glm::vec2> point(
158 glm::vec3 color = glm::vec3(1.0F),
159 float size = 10.0F,
160 float hit_radius = 0.04F);
161
162// =============================================================================
163// 2D position picker
164//
165// Value is glm::vec2 in [0,1]x[0,1], mapped to a point inside bounds.
166// Produces a single POINT_LIST vertex at the mapped position.
167// =============================================================================
168
169/**
170 * @brief Geometry function for a 2D position picker in NDC space.
171 * @param bounds Full extent of the pick area in NDC.
172 * @param color Point color.
173 * @param size Point size in pixels.
174 */
175[[nodiscard]] MAYAFLUX_API GeometryFn<glm::vec2> position_picker(
176 Kinesis::AABB2D bounds,
177 glm::vec3 color = glm::vec3(0.9F),
178 float size = 8.0F);
179
180// =============================================================================
181// Stroke slider
182//
183// Value in [0, 1] positions a handle point along a user-supplied polyline.
184// Renders two layers: the full path as a LINE_LIST in track_color, a
185// highlighted prefix segment from path start to the handle position in
186// fill_color, and a PointVertex handle on a caller-supplied secondary buffer.
187//
188// The secondary buffer must be a POINT_LIST FormaBuffer registered with the
189// same BufferManager and window before this function is called. The caller
190// adds it as a separate Element and relates it to the path element via
191// Layer::relate_to so removal and visibility cascade.
192//
193// Hit region: stroke_bounds over the full path at half_thickness.
194// bounds_hint: tight AABB enclosing all path points.
195//
196// Topology for the path buffer: LINE_LIST.
197// Topology for the handle buffer: POINT_LIST.
198// =============================================================================
199
200/**
201 * @brief Geometry function for a value scrubber along an arbitrary polyline.
202 *
203 * Value in [0, 1] maps to arc-length position along @p path. The full path
204 * is rendered as a LINE_LIST in @p track_color; the prefix from the path
205 * start to the handle position is rendered in @p fill_color. The handle
206 * itself is a PointVertex submitted to @p handle_buf each sync.
207 *
208 * @param path Ordered polyline vertices in NDC. Copied into closure.
209 * @param handle_buf POINT_LIST FormaBuffer for the handle point.
210 * Must be registered and have setup_rendering called.
211 * @param half_thickness Hit region half-thickness in NDC units.
212 * @param track_color Color of the full path.
213 * @param fill_color Color of the prefix segment up to the handle.
214 * @param handle_color Color of the handle point.
215 * @param handle_size Handle point size in pixels.
216 */
217[[nodiscard]] MAYAFLUX_API GeometryFn<float> stroke_slider(
218 std::span<const glm::vec2> path,
219 std::shared_ptr<Buffers::FormaBuffer> handle_buf,
220 float half_thickness = 0.02F,
221 glm::vec3 track_color = glm::vec3(0.3F),
222 glm::vec3 fill_color = glm::vec3(0.2F, 0.6F, 1.0F),
223 glm::vec3 handle_color = glm::vec3(0.95F),
224 float handle_size = 10.0F);
225
226// =============================================================================
227// Toggle
228//
229// Value type: bool. Renders a filled rect in one of two colors.
230// The geometry function is purely visual — it carries no interaction.
231// The caller wires on_press to flip state->value:
232//
233// surface.ctx().on_press(el.element.id, IO::MouseButtons::Left,
234// [state = el.state](uint32_t, glm::vec2) {
235// state->write(!state->value);
236// });
237//
238// Topology: TRIANGLE_STRIP (4 MeshVertex via to_mesh_vertices).
239// =============================================================================
240
241/**
242 * @brief Geometry function for a boolean toggle in NDC space.
243 *
244 * Renders @p region as a filled rect in @p color_off or @p color_on based
245 * on the current bool value. Interaction is the caller's responsibility.
246 *
247 * @param region NDC bounds of the toggle.
248 * @param color_off Fill color when false.
249 * @param color_on Fill color when true.
250 */
251[[nodiscard]] MAYAFLUX_API GeometryFn<bool> toggle(
252 Kinesis::AABB2D region,
253 glm::vec3 color_off = glm::vec3(0.25F),
254 glm::vec3 color_on = glm::vec3(0.2F, 0.7F, 0.4F));
255
256// =============================================================================
257// Level meter
258//
259// Value type: float in [0, 1]. Renders a filled bar from the origin edge of
260// bounds proportional to the value, with the remainder as a second color.
261// No handle, no hit region. Suitable for audio level, progress, any scalar readout.
262//
263// Orientation:
264// horizontal = true - bar grows left to right
265// horizontal = false - bar grows bottom to top
266//
267// Topology: TRIANGLE_STRIP (two quad pairs via to_mesh_vertices).
268// =============================================================================
269
270/**
271 * @brief Geometry function for a level meter in NDC space.
272 *
273 * No interaction. Drive from a node via bridge().at(el.state).bind(node).
274 *
275 * @param bounds Full extent of the meter in NDC.
276 * @param horizontal True for left-to-right fill, false for bottom-to-top.
277 * @param fill_color Color of the active (filled) portion.
278 * @param track_color Color of the inactive remainder.
279 */
280[[nodiscard]] MAYAFLUX_API GeometryFn<float> level_meter(
281 Kinesis::AABB2D bounds,
282 bool horizontal = true,
283 glm::vec3 fill_color = glm::vec3(0.2F, 0.7F, 0.3F),
284 glm::vec3 track_color = glm::vec3(0.15F));
285
286// =============================================================================
287// Crosshair
288//
289// Value type: glm::vec2 (NDC position). Renders two LINE_LIST segments —
290// horizontal and vertical — crossing at the value position.
291// Hit region: circle centered on the position.
292//
293// Pairs naturally with position_picker sharing the same MappedState<glm::vec2>.
294// Topology: LINE_LIST (4 LineVertex).
295// =============================================================================
296
297/**
298 * @brief Geometry function for a crosshair indicator in NDC space.
299 *
300 * @param arm_len Half-length of each arm in NDC units.
301 * @param color Line color.
302 * @param thickness Line thickness (maps to LineVertex::thickness).
303 * @param hit_radius Hit region radius in NDC units.
304 *
305 * @note Pass @c PrimitiveTopology::LINE_LIST explicitly to create_element —
306 * the default TRIANGLE_STRIP will misinterpret the 4 vertices.
307 */
308[[nodiscard]] MAYAFLUX_API GeometryFn<glm::vec2> crosshair(
309 float arm_len = 0.04F,
310 glm::vec3 color = glm::vec3(0.9F),
311 float thickness = 1.F,
312 float hit_radius = 0.05F);
313
314// =============================================================================
315// Drawable canvas
316//
317// value is vector<float> of N samples in [0, 1] mapped to the Y axis.
318// X positions are distributed evenly across bounds.
319// Renders as LINE_LIST: N-1 segments connecting adjacent samples.
320//
321// on_drag callback pattern:
322// ctx->on_drag(el.element.id, IO::MouseButtons::Left,
323// [&el, bounds](uint32_t, glm::vec2 ndc) {
324// auto& v = el.state->value;
325// const float t = (ndc.x - bounds.min.x) / bounds.width();
326// const size_t i = static_cast<size_t>(
327// std::clamp(t, 0.F, 1.F) * (v.size() - 1));
328// const float a = (ndc.y - bounds.min.y) / bounds.height();
329// v[i] = std::clamp(a, 0.F, 1.F);
330// ++el.state->version;
331// });
332//
333// For sparse-sample prevention at high drag speed, interpolate between the
334// previous and current index before calling state->write().
335//
336// Topology: LINE_LIST.
337// =============================================================================
338
339/**
340 * @brief Geometry function for a drawable curve canvas in NDC space.
341 *
342 * Renders the sample vector as a LINE_LIST polyline. Each adjacent sample
343 * pair becomes one segment. The hit region covers the full canvas bounds.
344 *
345 * @param bounds Canvas extent in NDC.
346 * @param color Line color.
347 * @param thickness LineVertex thickness value.
348 */
349[[nodiscard]] MAYAFLUX_API GeometryFn<std::vector<float>> drawable_canvas(
350 Kinesis::AABB2D bounds,
351 glm::vec3 color = glm::vec3(0.8F),
352 float thickness = 1.5F);
353
354/**
355 * @brief Wire drag interaction for a drawable canvas element.
356 *
357 * Registers a left-button drag callback on @p ctx that maps NDC cursor
358 * position to a sample index and amplitude, writes into @p state, and
359 * increments the version. Linear interpolation fills the range between the
360 * previously touched index and the current one, preventing sparse samples
361 * under fast drag.
362 *
363 * @param ctx Context owning the element.
364 * @param id Element id from the Mapped.
365 * @param state MappedState<vector<float>> to write into.
366 * @param bounds Canvas NDC bounds — must match those passed to drawable_canvas().
367 */
368MAYAFLUX_API void wire_canvas_drag(
369 Context& ctx,
370 uint32_t id,
371 std::shared_ptr<MappedState<std::vector<float>>> state,
372 Kinesis::AABB2D bounds);
373
374} // namespace MayaFlux::Portal::Forma::Geometry
Event wiring between a Layer and a window surface.
Definition Context.hpp:40
Context
Execution contexts for log messages.
GeometryFn< glm::vec2 > point(glm::vec3 color, float size, float hit_radius)
Geometry function for a positioned point in NDC space.
Definition Geometry.cpp:86
GeometryFn< bool > toggle(Kinesis::AABB2D region, glm::vec3 color_off, glm::vec3 color_on)
Geometry function for a boolean toggle in NDC space.
Definition Geometry.cpp:221
GeometryFn< float > stroke_slider(std::span< const glm::vec2 > path, std::shared_ptr< Buffers::FormaBuffer > handle_buf, float half_thickness, glm::vec3 track_color, glm::vec3 fill_color, glm::vec3 handle_color, float handle_size)
Geometry function for a value scrubber along an arbitrary polyline.
Definition Geometry.cpp:129
GeometryFn< glm::vec2 > crosshair(float arm_len, glm::vec3 color, float thickness, float hit_radius)
Geometry function for a crosshair indicator in NDC space.
Definition Geometry.cpp:266
GeometryFn< glm::vec2 > position_picker(Kinesis::AABB2D bounds, glm::vec3 color, float size)
Geometry function for a 2D position picker in NDC space.
Definition Geometry.cpp:102
GeometryFn< float > radial(glm::vec2 center, float radius, float angle_start, float angle_end, glm::vec3 color)
Geometry function for a radial indicator in NDC space.
Definition Geometry.cpp:61
GeometryFn< std::vector< float > > drawable_canvas(Kinesis::AABB2D bounds, glm::vec3 color, float thickness)
Geometry function for a drawable curve canvas in NDC space.
Definition Geometry.cpp:287
GeometryFn< float > vertical_fader(Kinesis::AABB2D bounds, float handle_h, glm::vec3 track_color, glm::vec3 handle_color)
Geometry function for a vertical fader in NDC space.
Definition Geometry.cpp:35
void wire_canvas_drag(Context &ctx, uint32_t id, std::shared_ptr< MappedState< std::vector< float > > > state, Kinesis::AABB2D bounds)
Wire drag interaction for a drawable canvas element.
Definition Geometry.cpp:334
GeometryFn< float > level_meter(Kinesis::AABB2D bounds, bool horizontal, glm::vec3 fill_color, glm::vec3 track_color)
Geometry function for a level meter in NDC space.
Definition Geometry.cpp:234
GeometryFn< float > horizontal_fader(Kinesis::AABB2D bounds, float handle_w, glm::vec3 track_color, glm::vec3 handle_color)
Geometry function for a horizontal fader in NDC space.
Definition Geometry.cpp:9
void write_verts(std::vector< uint8_t > &out, const std::vector< V > &verts)
Write a vertex array into a GeometryFn output buffer.
Definition Geometry.hpp:35
std::function< void(T value, std::vector< uint8_t > &out_bytes, Element &element)> GeometryFn
Geometry function signature.
Definition Mapped.hpp:64
Axis-aligned bounding rectangle in a 2D coordinate space.
Definition Bounds.hpp:21
Value carrier for a Mapped primitive.
Definition Mapped.hpp:36