MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
FieldOperator.hpp
Go to the documentation of this file.
1#pragma once
2
4
8
10
13
14/**
15 * @class FieldOperator
16 * @brief Pure field-driven vertex manipulation via Tendency evaluation
17 *
18 * No velocity, no mass, no integration. Each frame, evaluates bound
19 * Tendency fields at each vertex position and writes results into
20 * the targeted vertex attributes.
21 *
22 * ABSOLUTE mode: restores full reference vertex state before evaluation.
23 * Deterministic, stateless, frame-rate independent.
24 *
25 * ACCUMULATE mode: applies on top of current state. Produces drift
26 * and evolution, frame-rate dependent.
27 *
28 * Works with both PointVertex and LineVertex (identical 60-byte layout).
29 *
30 * Implemented targets:
31 * POSITION VectorField displacement added to position
32 * COLOR VectorField direct RGB assignment at position
33 * NORMAL VectorField direction assignment at position (auto-normalized)
34 * TANGENT VectorField direction assignment at position (auto-normalized)
35 * SCALAR SpatialField direct assignment (size/thickness)
36 * UV UVField direct assignment (UV coordinates)
37 *
38 * Usage with ParticleNetwork:
39 * @code
40 * auto field_op = particles->create_operator<FieldOperator>();
41 * field_op->bind(FieldTarget::POSITION, Kinesis::VectorField { ... });
42 * field_op->bind(FieldTarget::SCALAR, Kinesis::SpatialField { ... });
43 * @endcode
44 *
45 * Usage with PointCloudNetwork:
46 * @code
47 * auto field_op = cloud->create_operator<FieldOperator>();
48 * field_op->bind(FieldTarget::POSITION, Kinesis::VectorField { ... });
49 * @endcode
50 */
51class MAYAFLUX_API FieldOperator : public GraphicsOperator {
52public:
53 explicit FieldOperator(FieldMode mode = FieldMode::ABSOLUTE);
54
55 /**
56 * @brief Initialize from PointVertex data
57 * @param vertices Source vertices (positions stored as reference frame)
58 */
59 void initialize(const std::vector<PointVertex>& vertices);
60
61 /**
62 * @brief Initialize from LineVertex data
63 * @param vertices Source vertices (positions stored as reference frame)
64 */
65 void initialize(const std::vector<LineVertex>& vertices);
66
67 /**
68 * @brief Initialize from MeshVertex data
69 * @param vertices Source vertices (positions stored as reference frame)
70 */
71 void initialize(const std::vector<MeshVertex>& vertices);
72
73 void process(float dt) override;
74
75 // -----------------------------------------------------------------
76 // Field binding
77 // -----------------------------------------------------------------
78
79 /**
80 * @brief Bind a VectorField to a vec3 target
81 * @param target POSITION, COLOR, NORMAL, or TANGENT
82 * @param field VectorField: glm::vec3 -> glm::vec3
83 *
84 * POSITION fields are additive (displacement).
85 * COLOR fields are direct assignment (RGB).
86 * NORMAL fields are direct assignment (auto-normalized).
87 * TANGENT fields are direct assignment (auto-normalized).
88 */
89 void bind(FieldTarget target, Kinesis::VectorField field);
90
91 /**
92 * @brief Bind a SpatialField to a scalar target
93 * @param target SCALAR or UV
94 * @param field SpatialField: glm::vec3 -> float
95 */
97
98 /**
99 * @brief Bind a UVField to the UV target
100 * @param target Must be UV
101 * @param field UVField: glm::vec3 -> glm::vec2
102 *
103 * Multiple fields accumulate additively. Evaluation order matches
104 * bind order. Use ACCUMULATE mode for animated UV drift.
105 */
106 void bind(FieldTarget target, Kinesis::UVField field);
107
108 /**
109 * @brief Remove all fields bound to a target
110 * @param target Target to clear
111 */
112 void unbind(FieldTarget target);
113
114 /**
115 * @brief Remove all bound fields
116 */
117 void unbind_all();
118
119 /**
120 * @brief Set field application mode
121 * @param mode ABSOLUTE (reset each frame) or ACCUMULATE (stack displacements)
122 */
123 void set_mode(FieldMode mode) { m_mode = mode; }
124
125 /**
126 * @brief Get current field mode
127 */
128 [[nodiscard]] FieldMode get_mode() const { return m_mode; }
129
130 // -----------------------------------------------------------------
131 // GraphicsOperator interface
132 // -----------------------------------------------------------------
133
134 [[nodiscard]] std::span<const uint8_t> get_vertex_data() const override;
135 [[nodiscard]] std::span<const uint8_t> get_vertex_data_for_collection(uint32_t idx) const override;
136 [[nodiscard]] Kakshya::VertexLayout get_vertex_layout() const override;
137 [[nodiscard]] size_t get_vertex_count() const override;
138 [[nodiscard]] bool is_vertex_data_dirty() const override;
139 void mark_vertex_data_clean() override;
140 [[nodiscard]] std::vector<PointVertex> extract_point_vertices() const;
141 [[nodiscard]] std::vector<LineVertex> extract_line_vertices() const;
142 [[nodiscard]] std::vector<MeshVertex> extract_mesh_vertices() const;
143
144 void set_parameter(std::string_view param, double value) override;
145 [[nodiscard]] std::optional<double> query_state(std::string_view query) const override;
146 [[nodiscard]] std::string_view get_type_name() const override { return "Field"; }
147 [[nodiscard]] size_t get_point_count() const override;
148 [[nodiscard]] const char* get_vertex_type_name() const override;
149
150 void apply_one_to_one(
151 std::string_view param,
152 const std::shared_ptr<NodeNetwork>& source) override;
153
154 /**
155 * @brief Seed vertex data from the upstream operator's current output.
156 *
157 * Called by OperatorChain when consumes_upstream() is true. No-op if
158 * already initialised (m_count > 0) or if upstream is null. Derives
159 * vertex type from the upstream layout stride matching k_stride.
160 */
161 void seed_from_upstream(const GraphicsOperator* upstream) override;
162
163protected:
164 void* get_data_at(size_t global_index) override;
165
166private:
167 /**
168 * @enum VertexType
169 * @brief Tracks which vertex type was used at initialization
170 */
171 enum class VertexType : uint8_t { NONE,
172 POINT,
173 LINE,
174 MESH
175 };
176
178 VertexType m_vertex_type { VertexType::NONE };
179 size_t m_count { 0 };
180
181 std::vector<uint8_t> m_reference_data;
182 std::vector<uint8_t> m_vertex_data;
183 bool m_dirty { false };
184
185 std::vector<Kinesis::VectorField> m_position_fields;
186 std::vector<Kinesis::VectorField> m_color_fields;
187 std::vector<Kinesis::VectorField> m_normal_fields;
188 std::vector<Kinesis::VectorField> m_tangent_fields;
189 std::vector<Kinesis::SpatialField> m_scalar_fields;
190 std::vector<Kinesis::UVField> m_uv_fields;
191
192 static constexpr size_t k_stride = 60;
193 static constexpr size_t k_position_offset = 0;
194 static constexpr size_t k_color_offset = 12;
195 static constexpr size_t k_scalar_offset = 24;
196 static constexpr size_t k_uv_offset = 28;
197 static constexpr size_t k_normal_offset = 36;
198 static constexpr size_t k_tangent_offset = 48;
199
200 glm::vec3& vec3_at(size_t i, size_t offset);
201 float& float_at(size_t i, size_t offset);
202 [[nodiscard]] glm::vec3 ref_position_at(size_t i) const;
203
204 void store_reference(const void* data, size_t count);
205};
206
207} // namespace MayaFlux::Nodes::Network
size_t count
float value
float offset
std::vector< Kinesis::VectorField > m_position_fields
void set_mode(FieldMode mode)
Set field application mode.
std::vector< Kinesis::VectorField > m_tangent_fields
VertexType
Tracks which vertex type was used at initialization.
std::vector< Kinesis::SpatialField > m_scalar_fields
void bind(FieldTarget target, Kinesis::UVField field)
Bind a UVField to the UV target.
std::vector< Kinesis::VectorField > m_color_fields
std::vector< Kinesis::VectorField > m_normal_fields
std::string_view get_type_name() const override
Type name for introspection.
std::vector< Kinesis::UVField > m_uv_fields
void bind(FieldTarget target, Kinesis::SpatialField field)
Bind a SpatialField to a scalar target.
FieldMode get_mode() const
Get current field mode.
Pure field-driven vertex manipulation via Tendency evaluation.
Operator that produces GPU-renderable geometry.
void initialize()
Definition main.cpp:11
FieldTarget
What a Tendency drives when applied to a vertex record.
FieldMode
How a field result combines with the value already present.
Complete description of vertex data layout in a buffer.
Typed, composable, stateless callable from domain D to range R.
Definition Tendency.hpp:22