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: Create layout for textured quad primitives (position, texcoord).
219 * @param vertex_count Number of vertices in the buffer (default: 4).
220 * @return VertexLayout configured for Nodes::TextureQuadVertex.
221 */
223 {
224 VertexLayout layout;
225 layout.vertex_count = vertex_count;
226 layout.stride_bytes = static_cast<uint32_t>(sizeof(glm::vec3) + sizeof(glm::vec2)); // 20
227
228 layout.attributes.push_back(VertexAttributeLayout {
230 .offset_in_vertex = 0,
231 .name = "position" });
232
233 layout.attributes.push_back(VertexAttributeLayout {
235 .offset_in_vertex = static_cast<uint32_t>(sizeof(glm::vec3)),
236 .name = "texcoord" });
237
238 return layout;
239 }
240
241private:
242 /**
243 * Get size in bytes for a given modality
244 * Mirrors VKBuffer::get_format() logic
245 */
247 {
248 switch (mod) {
253 return sizeof(glm::vec3); // 12
254
256 return sizeof(glm::vec2); // 8
257
259 return sizeof(glm::vec4); // 16
260
263 return sizeof(double); // 8
264
265 default:
266 return 4; // Conservative default
267 }
268 }
269};
270
271} // 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.
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.