MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
VertexFormats.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "VertexLayout.hpp"
4
5namespace MayaFlux::Kakshya {
6
7/**
8 * @struct Vertex
9 * @brief Type-neutral vertex carrying the universal 60-byte attribute layout.
10 *
11 * The common substrate for geometry construction and spatial sampling before
12 * a concrete vertex type is chosen. Shares the exact byte layout of
13 * PointVertex, LineVertex, and MeshVertex so a Vertex byte buffer is a drop-in
14 * for any of them: position, color, scalar, uv, normal, tangent at identical
15 * offsets. Callers project into the concrete type via to_point_vertex(),
16 * to_line_vertex(), to_mesh_vertex() when the field semantics (size vs
17 * thickness vs weight) matter, but the raw bytes are already pipeline-ready.
18 *
19 * scalar maps to size (PointVertex), thickness (LineVertex), or weight
20 * (MeshVertex) at offset 24. uv defaults to zero and is overridden by UV
21 * generation (UVFieldProcessor, FieldOperator UV fields). normal and tangent
22 * default to the canonical Z-up / X-right frame.
23 *
24 * Layout (60 bytes):
25 * offset 0 position vec3 (12)
26 * offset 12 color vec3 (12)
27 * offset 24 scalar float (4)
28 * offset 28 uv vec2 (8)
29 * offset 36 normal vec3 (12)
30 * offset 48 tangent vec3 (12)
31 */
32struct Vertex {
33 glm::vec3 position;
34 glm::vec3 color { 1.0F };
35 float scalar { 1.0F }; ///< Normalised scalar; maps to size / thickness / weight at offset 24
36 glm::vec2 uv { 0.0F }; ///< Texture coordinates; zero unless set by UV generation
37 glm::vec3 normal { 0.0F, 0.0F, 1.0F };
38 glm::vec3 tangent { 1.0F, 0.0F, 0.0F };
39};
40
41static_assert(sizeof(Vertex) == 60,
42 "Vertex layout changed — must match VertexLayout::for_raw() stride and the other 60-byte vertex types");
43
44static_assert(offsetof(Vertex, position) == 0, "position must be at offset 0");
45static_assert(offsetof(Vertex, color) == 12, "color must be at offset 12");
46static_assert(offsetof(Vertex, scalar) == 24, "scalar must be at offset 24");
47static_assert(offsetof(Vertex, uv) == 28, "uv must be at offset 28");
48static_assert(offsetof(Vertex, normal) == 36, "normal must be at offset 36");
49static_assert(offsetof(Vertex, tangent) == 48, "tangent must be at offset 48");
50
51/**
52 * @struct PointVertex
53 * @brief Vertex type for point primitives (POINT_LIST topology)
54 *
55 * Layout (60 bytes):
56 * offset 0 — position vec3 (12)
57 * offset 12 — color vec3 (12)
58 * offset 24 — size float (4)
59 * offset 28 — uv vec2 (8)
60 * offset 36 — normal vec3 (12)
61 * offset 48 — tangent vec3 (12)
62 */
64 glm::vec3 position;
65 glm::vec3 color = glm::vec3(1.0F);
66 float size = 10.0F;
67 glm::vec2 uv = glm::vec2(0.0F);
68 glm::vec3 normal = glm::vec3(0.0F, 0.0F, 1.0F);
69 glm::vec3 tangent = glm::vec3(1.0F, 0.0F, 0.0F);
70};
71
72/**
73 * @struct LineVertex
74 * @brief Vertex type for line primitives (LINE_LIST / LINE_STRIP topology)
75 *
76 * Layout (60 bytes):
77 * offset 0 — position vec3 (12)
78 * offset 12 — color vec3 (12)
79 * offset 24 — thickness float (4)
80 * offset 28 — uv vec2 (8)
81 * offset 36 — normal vec3 (12)
82 * offset 48 — tangent vec3 (12)
83 */
84struct LineVertex {
85 glm::vec3 position;
86 glm::vec3 color = glm::vec3(1.0F);
87 float thickness = 2.0F;
88 glm::vec2 uv = glm::vec2(0.0F);
89 glm::vec3 normal = glm::vec3(0.0F, 0.0F, 1.0F);
90 glm::vec3 tangent = glm::vec3(1.0F, 0.0F, 0.0F);
91};
92
93/**
94 * @struct MeshVertex
95 * @brief Vertex type for indexed triangle mesh primitives (TRIANGLE_LIST topology)
96 *
97 * Shares the universal 60-byte layout with PointVertex and LineVertex.
98 * The scalar field at offset 24 is interpreted as a per-vertex weight
99 * (displacement magnitude, blend factor, or any user-defined scalar).
100 * FieldOperator works identically on MeshVertex data: same stride,
101 * same offsets, same raw byte buffer approach.
102 *
103 * Layout (60 bytes):
104 * offset 0 position vec3 (12)
105 * offset 12 color vec3 (12)
106 * offset 24 weight float (4)
107 * offset 28 uv vec2 (8)
108 * offset 36 normal vec3 (12)
109 * offset 48 tangent vec3 (12)
110 *
111 * Intended for use with an external index buffer (uint32_t).
112 * GeometryWriterNode::set_vertices<MeshVertex>() populates vertex data.
113 * Index data is stored separately (see GeometryBuffer index support).
114 */
116 glm::vec3 position;
117 glm::vec3 color = glm::vec3(1.0F);
118 float weight = 0.0F;
119 glm::vec2 uv = glm::vec2(0.0F);
120 glm::vec3 normal = glm::vec3(0.0F, 0.0F, 1.0F);
121 glm::vec3 tangent = glm::vec3(1.0F, 0.0F, 0.0F);
122};
123
124static_assert(sizeof(PointVertex) == 60,
125 "PointVertex layout changed — update VertexLayout::for_points(), VertexAccess write helpers, and shaders");
126static_assert(sizeof(LineVertex) == 60,
127 "LineVertex layout changed — update VertexLayout::for_lines(), VertexAccess write helpers, and shaders");
128static_assert(sizeof(MeshVertex) == 60,
129 "MeshVertex layout changed — must match PointVertex/LineVertex stride for FieldOperator compatibility");
130
131static_assert(offsetof(MeshVertex, position) == 0, "position must be at offset 0");
132static_assert(offsetof(MeshVertex, color) == 12, "color must be at offset 12");
133static_assert(offsetof(MeshVertex, weight) == 24, "weight must be at offset 24");
134static_assert(offsetof(MeshVertex, uv) == 28, "uv must be at offset 28");
135static_assert(offsetof(MeshVertex, normal) == 36, "normal must be at offset 36");
136static_assert(offsetof(MeshVertex, tangent) == 48, "tangent must be at offset 48");
137
138/**
139 * @struct TextureQuadVertex
140 * @brief Vertex layout for textured quad geometry (position + UV).
141 *
142 * Matches the vertex input expected by texture.vert.spv:
143 * location 0 → vec3 position, location 1 → vec2 texcoord.
144 */
146 glm::vec3 position;
147 glm::vec2 texcoord;
148};
149
150/**
151 * @brief Deduce a VertexLayout from a vertex struct type.
152 */
153template <typename T>
155{
156 if constexpr (std::is_same_v<T, PointVertex>) {
158 } else if constexpr (std::is_same_v<T, LineVertex>) {
160 } else if constexpr (std::is_same_v<T, MeshVertex>) {
162 } else if constexpr (std::is_same_v<T, Vertex>) {
163 return VertexLayout::for_raw();
164 } else {
165 static_assert(!std::is_same_v<T, T>,
166 "vertex_layout_for: unrecognised vertex type");
167 }
168}
169
170//-----------------------------------------------------------------------------
171// Vertex projection — convert raw Vertex to concrete vertex types.
172// These are the ONLY places that touch PointVertex / LineVertex fields.
173// Adding a new vertex type means adding one function here, nothing else.
174//-----------------------------------------------------------------------------
175
176/**
177 * @brief Project raw Vertex to PointVertex.
178 * @param s Source vertex
179 * @param size_range Min/max point size; scalar linearly interpolates within it
180 * @return PointVertex with all fields populated from vertex
181 */
182[[nodiscard]] inline PointVertex to_point_vertex(
183 const Vertex& s,
184 glm::vec2 size_range = { 8.0F, 12.0F }) noexcept
185{
186 return {
187 .position = s.position,
188 .color = s.color,
189 .size = glm::mix(size_range.x, size_range.y, s.scalar),
190 .uv = glm::vec2(0.0F),
191 .normal = s.normal,
192 .tangent = s.tangent,
193 };
194}
195
196/**
197 * @brief Project raw Vertex to LineVertex.
198 * @param s Source vertex
199 * @param thickness_range Min/max line thickness; scalar linearly interpolates within it
200 * @return LineVertex with all fields populated from vertex
201 */
202[[nodiscard]] inline LineVertex to_line_vertex(
203 const Vertex& s,
204 glm::vec2 thickness_range = { 1.0F, 2.0F }) noexcept
205{
206 return {
207 .position = s.position,
208 .color = s.color,
209 .thickness = glm::mix(thickness_range.x, thickness_range.y, s.scalar),
210 .uv = glm::vec2(0.0F),
211 .normal = s.normal,
212 .tangent = s.tangent,
213 };
214}
215
216/**
217 * @brief Project raw Vertex to MeshVertex.
218 * @param s Source vertex
219 * @return MeshVertex with all fields populated from vertex
220 *
221 * MeshVertex doesn't have a size/thickness field, so scalar is passed through
222 * as weight for potential use in shader-based deformation or other effects.
223 */
224[[nodiscard]] inline MeshVertex to_mesh_vertex(
225 const Vertex& s,
226 glm::vec2 weight_range = { 0.0F, 1.0F }) noexcept
227{
228 return {
229 .position = s.position,
230 .color = s.color,
231 .weight = glm::mix(weight_range.x, weight_range.y, s.scalar),
232 .uv = glm::vec2(0.0F),
233 .normal = s.normal,
234 .tangent = s.tangent,
235 };
236}
237
238/**
239 * @brief Batch-project raw Vertex vector to PointVertex.
240 * @param vertices Source vertices
241 * @param size_range Size range passed to to_point_vertex
242 * @return PointVertex vector of equal length
243 */
244[[nodiscard]] MAYAFLUX_API std::vector<PointVertex> to_point_vertices(
245 std::span<const Vertex> vertices,
246 glm::vec2 size_range = { 8.0F, 12.0F });
247
248/**
249 * @brief Batch-project raw Vertex vector to LineVertex.
250 * @param vertices Source vertices
251 * @param thickness_range Thickness range passed to to_line_vertex
252 * @return LineVertex vector of equal length
253 */
254[[nodiscard]] MAYAFLUX_API std::vector<LineVertex> to_line_vertices(
255 std::span<const Vertex> vertices,
256 glm::vec2 thickness_range = { 1.0F, 2.0F });
257
258/**
259 * @brief Batch-project raw Vertex vector to MeshVertex.
260 * @param vertices Source vertices
261 * @param weight_range Weight range passed to to_mesh_vertex (for potential shader use)
262 * @return MeshVertex vector of equal length
263 */
264[[nodiscard]] MAYAFLUX_API std::vector<MeshVertex> to_mesh_vertices(
265 std::span<const Vertex> vertices,
266 glm::vec2 weight_range = { 0.0F, 1.0F });
267
268} // namespace MayaFlux::Kakshya
double weight
VertexLayout vertex_layout_for()
Deduce a VertexLayout from a vertex struct type.
LineVertex to_line_vertex(const Vertex &s, glm::vec2 thickness_range={ 1.0F, 2.0F }) noexcept
Project raw Vertex to LineVertex.
std::vector< LineVertex > to_line_vertices(std::span< const Vertex > vertices, glm::vec2 thickness_range)
Batch-project raw Vertex vector to LineVertex.
MeshVertex to_mesh_vertex(const Vertex &s, glm::vec2 weight_range={ 0.0F, 1.0F }) noexcept
Project raw Vertex to MeshVertex.
PointVertex to_point_vertex(const Vertex &s, glm::vec2 size_range={ 8.0F, 12.0F }) noexcept
Project raw Vertex to PointVertex.
std::vector< PointVertex > to_point_vertices(std::span< const Vertex > vertices, glm::vec2 size_range)
Batch-project raw Vertex vector to PointVertex.
std::vector< MeshVertex > to_mesh_vertices(std::span< const Vertex > vertices, glm::vec2 weight_range)
Batch-project raw Vertex vector to MeshVertex.
Vertex type for line primitives (LINE_LIST / LINE_STRIP topology)
Vertex type for indexed triangle mesh primitives (TRIANGLE_LIST topology)
Vertex type for point primitives (POINT_LIST topology)
Vertex layout for textured quad geometry (position + UV).
static VertexLayout for_raw(uint32_t stride=60)
Factory: layout for raw vertex data with common attributes.
static VertexLayout for_lines(uint32_t stride=60)
Factory: layout for LineVertex (position, color, thickness, uv, normal, tangent)
static VertexLayout for_meshes(uint32_t stride=60)
Factory: layout for MeshVertex (position, color, weight, uv, normal, tangent)
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.
float scalar
Normalised scalar; maps to size / thickness / weight at offset 24.
glm::vec2 uv
Texture coordinates; zero unless set by UV generation.
Type-neutral vertex carrying the universal 60-byte attribute layout.