MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
MeshAccess.hpp
Go to the documentation of this file.
1#pragma once
2
4#include "VertexLayout.hpp"
5
6namespace MayaFlux::Kakshya {
7
8/**
9 * @struct MeshSubrange
10 * @brief Byte-range descriptor for one submesh within the shared index buffer.
11 *
12 * start and end are element indices into the uint32_t index array, not byte
13 * offsets. Callers multiply by sizeof(uint32_t) when computing GPU offsets.
14 * name and material_name are sourced from the originating file; both may be
15 * empty for single-mesh files or loaders that do not expose names.
16 */
17struct MAYAFLUX_API MeshSubrange {
18 uint32_t index_start {};
19 uint32_t index_count {};
20 uint32_t vertex_offset {}; ///< Base vertex added to each index (large-mesh batching)
21 std::string name;
22 std::string material_name;
23 std::string diffuse_path;
24 bool diffuse_embedded {};
25
26 /**
27 * @brief Convert this subrange to a Region for use in RegionGroup.
28 *
29 * Coordinates are [index_start, index_start + index_count).
30 * Attributes carry name, material_name, and vertex_offset.
31 */
32 [[nodiscard]] Region to_region() const;
33};
34
35/**
36 * @struct MeshAccess
37 * @brief Non-owning read view over a pair of DataVariant streams representing
38 * interleaved vertex bytes and a flat uint32_t index array.
39 *
40 * Parallel to VertexAccess and TextureAccess: describes what the data IS
41 * in memory terms with no knowledge of Vulkan, Portal, or concrete vertex
42 * structs (MeshVertex). The layout field carries full semantic description
43 * via VertexLayout::for_meshes(), including stride and attribute offsets.
44 *
45 * Ownership contract: the two DataVariant instances and the optional
46 * RegionGroup must outlive this struct. MeshAccess holds raw pointers and
47 * spans into their storage.
48 *
49 * Zero-copy: both vertex_ptr and index_ptr point directly into the storage
50 * of their respective DataVariant. No conversion buffer is needed because
51 * MeshInsertion always writes the canonical 60-byte interleaved format before
52 * producing a MeshAccess.
53 *
54 * Submesh structure: when the source file contains multiple meshes, submeshes
55 * holds a RegionGroup named "submeshes". Each Region maps to one MeshSubrange
56 * and carries name, material_name, and vertex_offset as attributes. Single-mesh
57 * files leave submeshes as nullopt; the entire index buffer is one contiguous
58 * range.
59 */
60struct MAYAFLUX_API MeshAccess {
61 const void* vertex_ptr = nullptr;
62 size_t vertex_bytes = 0;
63
64 const uint32_t* index_ptr = nullptr;
65 uint32_t index_count = 0;
66
68
69 std::optional<RegionGroup> submeshes;
70
71 // -------------------------------------------------------------------------
72 // Convenience queries
73 // -------------------------------------------------------------------------
74
75 /**
76 * @brief Number of vertices derived from vertex_bytes and layout stride.
77 * @return 0 if layout.stride_bytes is zero.
78 */
79 [[nodiscard]] uint32_t vertex_count() const noexcept
80 {
81 if (layout.stride_bytes == 0) {
82 return 0;
83 }
84 return static_cast<uint32_t>(vertex_bytes / layout.stride_bytes);
85 }
86
87 /**
88 * @brief Number of triangles (index_count / 3).
89 */
90 [[nodiscard]] uint32_t face_count() const noexcept
91 {
92 return index_count / 3;
93 }
94
95 /**
96 * @brief True when both vertex and index data are non-empty.
97 */
98 [[nodiscard]] bool is_valid() const noexcept
99 {
100 return vertex_ptr != nullptr && vertex_bytes > 0
101 && index_ptr != nullptr && index_count > 0
102 && layout.stride_bytes > 0;
103 }
104
105 /**
106 * @brief True when submesh region data is present.
107 */
108 [[nodiscard]] bool has_submeshes() const noexcept
109 {
110 return submeshes.has_value() && !submeshes->regions.empty();
111 }
112
113 /**
114 * @brief Span over the raw index array.
115 */
116 [[nodiscard]] std::span<const uint32_t> indices() const noexcept
117 {
118 return { index_ptr, index_count };
119 }
120
121 /**
122 * @brief Span over the raw vertex bytes.
123 */
124 [[nodiscard]] std::span<const std::byte> vertices() const noexcept
125 {
126 return { static_cast<const std::byte*>(vertex_ptr), vertex_bytes };
127 }
128};
129
130/**
131 * @brief Construct a MeshAccess from two DataVariant instances.
132 *
133 * vertex_variant must hold vector<uint8_t> (canonical interleaved bytes).
134 * index_variant must hold vector<uint32_t>.
135 * layout must have stride_bytes > 0 and at least one attribute.
136 * submeshes is forwarded as-is; pass std::nullopt for single-mesh data.
137 *
138 * Returns std::nullopt and logs an error for any type mismatch.
139 *
140 * The RegionGroup convention: a single RegionGroup named "submeshes" holds
141 * one Region per submesh. Each Region carries coordinates
142 * [index_start, index_start + index_count) in the index dimension, with
143 * attributes "name", "material_name", and "vertex_offset". This mirrors the
144 * audio/video pattern where e.g. "transients" is the group and each onset
145 * event is a Region inside it.
146 */
147[[nodiscard]] MAYAFLUX_API std::optional<MeshAccess> as_mesh_access(
148 const DataVariant& vertex_variant,
149 const DataVariant& index_variant,
150 const VertexLayout& layout,
151 std::optional<RegionGroup> submeshes = std::nullopt);
152
153} // namespace MayaFlux::Kakshya
std::optional< MeshAccess > as_mesh_access(const DataVariant &vertex_variant, const DataVariant &index_variant, const VertexLayout &layout, std::optional< RegionGroup > submeshes)
Construct a MeshAccess from two DataVariant instances.
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:76
std::optional< RegionGroup > submeshes
std::span< const std::byte > vertices() const noexcept
Span over the raw vertex bytes.
bool is_valid() const noexcept
True when both vertex and index data are non-empty.
uint32_t vertex_count() const noexcept
Number of vertices derived from vertex_bytes and layout stride.
std::span< const uint32_t > indices() const noexcept
Span over the raw index array.
uint32_t face_count() const noexcept
Number of triangles (index_count / 3).
bool has_submeshes() const noexcept
True when submesh region data is present.
Non-owning read view over a pair of DataVariant streams representing interleaved vertex bytes and a f...
Byte-range descriptor for one submesh within the shared index buffer.
Represents a point or span in N-dimensional space.
Definition Region.hpp:67
uint32_t stride_bytes
Total bytes per vertex (stride in Vulkan terms) e.g., 3 floats (position) + 3 floats (normal) = 24 by...
Complete description of vertex data layout in a buffer.