MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
VertexLayout.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "NDData.hpp"
4
5namespace MayaFlux::Kakshya {
6
7/**
8 * @struct VertexAttributeLayout
9 * @brief Semantic description of a single vertex attribute
10 *
11 * Describes one component of vertex data without exposing Vulkan types.
12 * The modality encodes everything needed (3D position, 2D texture coords, etc.)
13 */
15 /**
16 * Semantic type of this attribute
17 * e.g., VERTEX_POSITIONS_3D → vec3, TEXTURE_COORDS_2D → vec2
18 */
20
21 /**
22 * Byte offset of this attribute within one vertex
23 * e.g., position at 0, normal at 12, color at 24
24 */
25 uint32_t offset_in_vertex = 0;
26
27 /**
28 * Optional name for debugging/introspection
29 * e.g., "position", "normal", "texCoord"
30 */
31 std::string name;
32};
33
34/**
35 * @struct VertexLayout
36 * @brief Complete description of vertex data layout in a buffer
37 *
38 * Fully semantic and backend-agnostic. Portal layer translates to Vulkan.
39 * Derived from buffer's modality and dimensions.
40 */
42 /**
43 * Total number of vertices in this buffer
44 */
45 uint32_t vertex_count = 0;
46
47 /**
48 * Total bytes per vertex (stride in Vulkan terms)
49 * e.g., 3 floats (position) + 3 floats (normal) = 24 bytes
50 */
51 uint32_t stride_bytes = 0;
52
53 /**
54 * All attributes that make up one vertex
55 * Ordered by shader location (0, 1, 2, ...)
56 */
57 std::vector<VertexAttributeLayout> attributes;
58
59 /**
60 * @brief Helper: compute stride from attributes if not explicitly set
61 */
63 {
64 if (stride_bytes == 0 && !attributes.empty()) {
65 uint32_t max_offset = 0;
66 uint32_t last_size = 0;
67
68 for (const auto& attr : attributes) {
69 uint32_t attr_size = modality_size_bytes(attr.component_modality);
70 max_offset = std::max(max_offset, attr.offset_in_vertex);
71 if (attr.offset_in_vertex == max_offset) {
72 last_size = attr_size;
73 }
74 }
75
76 stride_bytes = max_offset + last_size;
77 }
78 }
79
80 /**
81 * @brief Factory: layout for PointVertex (position, color, size, uv, normal, tangent)
82 *
83 * Matches PointVertex field order exactly (60 bytes):
84 * loc 0 offset 0 VERTEX_POSITIONS_3D position
85 * loc 1 offset 12 VERTEX_COLORS_RGB color
86 * loc 2 offset 24 UNKNOWN size
87 * loc 3 offset 28 TEXTURE_COORDS_2D uv
88 * loc 4 offset 36 VERTEX_NORMALS_3D normal
89 * loc 5 offset 48 VERTEX_TANGENTS_3D tangent
90 *
91 * @param stride Override stride (default: sizeof(PointVertex) == 60)
92 */
93 static VertexLayout for_points(uint32_t stride = 60)
94 {
95 VertexLayout layout;
96 layout.stride_bytes = stride;
97
98 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_POSITIONS_3D,
99 .offset_in_vertex = 0,
100 .name = "position" });
101
102 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_COLORS_RGB,
103 .offset_in_vertex = 12,
104 .name = "color" });
105
106 layout.attributes.push_back({ .component_modality = DataModality::SCALAR_F32,
107 .offset_in_vertex = 24,
108 .name = "size" });
109
110 layout.attributes.push_back({ .component_modality = DataModality::TEXTURE_COORDS_2D,
111 .offset_in_vertex = 28,
112 .name = "uv" });
113
114 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_NORMALS_3D,
115 .offset_in_vertex = 36,
116 .name = "normal" });
117
118 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_TANGENTS_3D,
119 .offset_in_vertex = 48,
120 .name = "tangent" });
121
122 return layout;
123 }
124
125 /**
126 * @brief Factory: layout for LineVertex (position, color, thickness, uv, normal, tangent)
127 *
128 * Matches LineVertex field order exactly (60 bytes):
129 * loc 0 offset 0 VERTEX_POSITIONS_3D position
130 * loc 1 offset 12 VERTEX_COLORS_RGB color
131 * loc 2 offset 24 UNKNOWN thickness
132 * loc 3 offset 28 TEXTURE_COORDS_2D uv
133 * loc 4 offset 36 VERTEX_NORMALS_3D normal
134 * loc 5 offset 48 VERTEX_TANGENTS_3D tangent
135 *
136 * @param stride Override stride (default: sizeof(LineVertex) == 60)
137 */
138 static VertexLayout for_lines(uint32_t stride = 60)
139 {
140 VertexLayout layout;
141 layout.stride_bytes = stride;
142
143 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_POSITIONS_3D,
144 .offset_in_vertex = 0,
145 .name = "position" });
146
147 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_COLORS_RGB,
148 .offset_in_vertex = 12,
149 .name = "color" });
150
151 layout.attributes.push_back({ .component_modality = DataModality::SCALAR_F32,
152 .offset_in_vertex = 24,
153 .name = "thickness" });
154
155 layout.attributes.push_back({ .component_modality = DataModality::TEXTURE_COORDS_2D,
156 .offset_in_vertex = 28,
157 .name = "uv" });
158
159 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_NORMALS_3D,
160 .offset_in_vertex = 36,
161 .name = "normal" });
162
163 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_TANGENTS_3D,
164 .offset_in_vertex = 48,
165 .name = "tangent" });
166 return layout;
167 }
168
169 /**
170 * @brief Factory: layout for MeshVertex (position, color, weight, uv, normal, tangent)
171 *
172 * Matches MeshVertex field order exactly (60 bytes):
173 * loc 0 offset 0 VERTEX_POSITIONS_3D position
174 * loc 1 offset 12 VERTEX_COLORS_RGB color
175 * loc 2 offset 24 SCALAR_F32 weight
176 * loc 3 offset 28 TEXTURE_COORDS_2D uv
177 * loc 4 offset 36 VERTEX_NORMALS_3D normal
178 * loc 5 offset 48 VERTEX_TANGENTS_3D tangent
179 *
180 * Identical offset table to for_points() and for_lines().
181 * FieldOperator processes all three types with the same constants.
182 *
183 * @param stride Override stride (default: sizeof(MeshVertex) == 60)
184 */
185 static VertexLayout for_meshes(uint32_t stride = 60)
186 {
187 VertexLayout layout;
188 layout.stride_bytes = stride;
189
190 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_POSITIONS_3D,
191 .offset_in_vertex = 0,
192 .name = "position" });
193
194 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_COLORS_RGB,
195 .offset_in_vertex = 12,
196 .name = "color" });
197
198 layout.attributes.push_back({ .component_modality = DataModality::SCALAR_F32,
199 .offset_in_vertex = 24,
200 .name = "weight" });
201
202 layout.attributes.push_back({ .component_modality = DataModality::TEXTURE_COORDS_2D,
203 .offset_in_vertex = 28,
204 .name = "uv" });
205
206 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_NORMALS_3D,
207 .offset_in_vertex = 36,
208 .name = "normal" });
209
210 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_TANGENTS_3D,
211 .offset_in_vertex = 48,
212 .name = "tangent" });
213
214 return layout;
215 }
216
217 /**
218 * @brief Factory: layout for raw vertex data with common attributes
219 *
220 * Matches PointVertex/LineVertex/MeshVertex field order exactly (60 bytes):
221 * loc 0 offset 0 VERTEX_POSITIONS_3D position
222 * loc 1 offset 12 VERTEX_COLORS_RGB color
223 * loc 2 offset 24 SCALAR_F32 scalar
224 * loc 3 offset 28 TEXTURE_COORDS_2D uv
225 * loc 4 offset 36 VERTEX_NORMALS_3D normal
226 * loc 5 offset 48 VERTEX_TANGENTS_3D tangent
227 *
228 * Use when vertex data is pre-packed or doesn't fit standard structs.
229 *
230 * @param stride Override stride (default: 60 bytes for these attributes)
231 */
232 static VertexLayout for_raw(uint32_t stride = 60)
233 {
234 VertexLayout layout;
235 layout.stride_bytes = stride;
236 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_POSITIONS_3D,
237 .offset_in_vertex = 0,
238 .name = "position" });
239 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_COLORS_RGB,
240 .offset_in_vertex = 12,
241 .name = "color" });
242 layout.attributes.push_back({ .component_modality = DataModality::SCALAR_F32,
243 .offset_in_vertex = 24,
244 .name = "scalar" });
245 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_NORMALS_3D,
246 .offset_in_vertex = 36,
247 .name = "normal" });
248 layout.attributes.push_back({ .component_modality = DataModality::VERTEX_TANGENTS_3D,
249 .offset_in_vertex = 48,
250 .name = "tangent" });
251 return layout;
252 }
253
254 /**
255 * @brief Factory: Create layout for textured quad primitives (position, texcoord).
256 * @param vertex_count Number of vertices in the buffer (default: 4).
257 * @return VertexLayout configured for Nodes::TextureQuadVertex.
258 */
260 {
261 VertexLayout layout;
262 layout.vertex_count = vertex_count;
263 layout.stride_bytes = static_cast<uint32_t>(sizeof(glm::vec3) + sizeof(glm::vec2)); // 20
264
265 layout.attributes.push_back(VertexAttributeLayout {
267 .offset_in_vertex = 0,
268 .name = "position" });
269
270 layout.attributes.push_back(VertexAttributeLayout {
272 .offset_in_vertex = static_cast<uint32_t>(sizeof(glm::vec3)),
273 .name = "texcoord" });
274
275 return layout;
276 }
277
278private:
279 /**
280 * Get size in bytes for a given modality
281 * Mirrors VKBuffer::get_format() logic
282 */
284 {
285 switch (mod) {
290 return sizeof(glm::vec3); // 12
291
293 return sizeof(glm::vec2); // 8
294
296 return sizeof(glm::vec4); // 16
297
300 return sizeof(double); // 8
301
302 default:
303 return 4; // Conservative default
304 }
305 }
306};
307
308} // namespace MayaFlux::Buffers
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:81
@ AUDIO_MULTICHANNEL
Multi-channel audio.
@ SCALAR_F32
Single-channel float data.
std::string name
Optional name for debugging/introspection e.g., "position", "normal", "texCoord".
uint32_t offset_in_vertex
Byte offset of this attribute within one vertex e.g., position at 0, normal at 12,...
DataModality component_modality
Semantic type of this attribute e.g., VERTEX_POSITIONS_3D → vec3, TEXTURE_COORDS_2D → vec2.
Semantic description of a single vertex attribute.
static VertexLayout for_raw(uint32_t stride=60)
Factory: layout for raw vertex data with common attributes.
uint32_t stride_bytes
Total bytes per vertex (stride in Vulkan terms) e.g., 3 floats (position) + 3 floats (normal) = 24 by...
uint32_t vertex_count
Total number of vertices in this buffer.
static VertexLayout for_lines(uint32_t stride=60)
Factory: layout for LineVertex (position, color, thickness, uv, normal, tangent)
static VertexLayout for_textured_quad(uint32_t vertex_count=4)
Factory: Create layout for textured quad primitives (position, texcoord).
static uint32_t modality_size_bytes(DataModality mod)
Get size in bytes for a given modality Mirrors VKBuffer::get_format() logic.
void compute_stride()
Helper: compute stride from attributes if not explicitly set.
static VertexLayout for_meshes(uint32_t stride=60)
Factory: layout for MeshVertex (position, color, weight, uv, normal, tangent)
std::vector< VertexAttributeLayout > attributes
All attributes that make up one vertex Ordered by shader location (0, 1, 2, ...)
static VertexLayout for_points(uint32_t stride=60)
Factory: layout for PointVertex (position, color, size, uv, normal, tangent)
Complete description of vertex data layout in a buffer.