MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
MeshInsertion.cpp
Go to the documentation of this file.
1#include "MeshInsertion.hpp"
2#include "MeshAccess.hpp"
3
5
6namespace MayaFlux::Kakshya {
7
8// =============================================================================
9// Construction
10// =============================================================================
11
13 : m_vertex_variant(vertex_variant)
14 , m_index_variant(index_variant)
15{
16}
17
18// =============================================================================
19// Private helpers
20// =============================================================================
21
23{
24 if (!std::holds_alternative<std::vector<uint8_t>>(m_vertex_variant)) {
25 m_vertex_variant = std::vector<uint8_t> {};
26 }
27}
28
30{
31 if (!std::holds_alternative<std::vector<uint32_t>>(m_index_variant)) {
32 m_index_variant = std::vector<uint32_t> {};
33 }
34}
35
37{
38 if (incoming.stride_bytes != m_layout.stride_bytes) {
40 "MeshInsertion: submesh stride {} does not match established stride {}; "
41 "batch skipped",
43 return false;
44 }
45 if (incoming.attributes.size() != m_layout.attributes.size()) {
47 "MeshInsertion: submesh attribute count {} does not match established count {}; "
48 "batch skipped",
49 incoming.attributes.size(), m_layout.attributes.size());
50 return false;
51 }
52 return true;
53}
54
55// =============================================================================
56// insert_flat
57// =============================================================================
58
60 std::span<const uint8_t> vertex_bytes,
61 std::span<const uint32_t> index_data,
62 const VertexLayout& layout)
63{
64 if (layout.stride_bytes == 0) {
66 "MeshInsertion::insert_flat: layout stride_bytes is zero");
67 return;
68 }
69 if (vertex_bytes.size() % layout.stride_bytes != 0) {
71 "MeshInsertion::insert_flat: vertex_bytes {} not a multiple of stride {}",
72 vertex_bytes.size(), layout.stride_bytes);
73 return;
74 }
75 if (index_data.size() % 3 != 0) {
77 "MeshInsertion::insert_flat: index count {} is not a multiple of 3",
78 index_data.size());
79 return;
80 }
81
82 m_vertex_variant = std::vector<uint8_t>(vertex_bytes.begin(), vertex_bytes.end());
83 m_index_variant = std::vector<uint32_t>(index_data.begin(), index_data.end());
84
85 m_layout = layout;
86 m_vertex_count = static_cast<uint32_t>(vertex_bytes.size() / layout.stride_bytes);
87 m_index_count = static_cast<uint32_t>(index_data.size());
89 m_layout_set = true;
90 m_submeshes = std::nullopt;
91
93 "MeshInsertion::insert_flat: {} vertices, {} indices ({} faces)",
95}
96
97// =============================================================================
98// insert_submesh
99// =============================================================================
100
102 std::span<const uint8_t> vertex_bytes,
103 std::span<const uint32_t> index_data,
104 std::string_view name,
105 std::string_view material_name,
106 const VertexLayout& layout)
107{
108 if (layout.stride_bytes == 0) {
110 "MeshInsertion::insert_submesh: layout stride_bytes is zero");
111 return;
112 }
113 if (vertex_bytes.size() % layout.stride_bytes != 0) {
115 "MeshInsertion::insert_submesh: vertex_bytes {} not a multiple of stride {}",
116 vertex_bytes.size(), layout.stride_bytes);
117 return;
118 }
119 if (index_data.size() % 3 != 0) {
121 "MeshInsertion::insert_submesh: index count {} is not a multiple of 3",
122 index_data.size());
123 return;
124 }
125
126 if (!m_layout_set) {
127 m_layout = layout;
128 m_layout_set = true;
129 } else if (!validate_layout(layout)) {
130 return;
131 }
132
135
136 auto& vbuf = std::get<std::vector<uint8_t>>(m_vertex_variant);
137 auto& ibuf = std::get<std::vector<uint32_t>>(m_index_variant);
138
139 const auto submesh_vcount = static_cast<uint32_t>(vertex_bytes.size() / layout.stride_bytes);
140 const uint32_t index_start = m_index_count;
141
142 vbuf.insert(vbuf.end(), vertex_bytes.begin(), vertex_bytes.end());
143
144 ibuf.reserve(ibuf.size() + index_data.size());
145 for (const uint32_t idx : index_data) {
146 ibuf.push_back(idx + m_vertex_count);
147 }
148
149 MeshSubrange sub;
150 sub.index_start = index_start;
151 sub.index_count = static_cast<uint32_t>(index_data.size());
153 sub.name = std::string(name);
154 sub.material_name = std::string(material_name);
155
156 if (!m_submeshes.has_value()) {
157 m_submeshes = RegionGroup("submeshes");
158 }
159 m_submeshes->add_region(sub.to_region());
160
161 m_vertex_count += submesh_vcount;
162 m_index_count += static_cast<uint32_t>(index_data.size());
164
166 "MeshInsertion::insert_submesh: '{}' +{} vertices, +{} indices, "
167 "running totals: {} vertices / {} indices",
168 name.empty() ? "<unnamed>" : name,
169 submesh_vcount, index_data.size(),
171}
172
173// =============================================================================
174// clear
175// =============================================================================
176
178{
179 m_vertex_variant = std::vector<uint8_t> {};
180 m_index_variant = std::vector<uint32_t> {};
181 m_layout = {};
182 m_layout_set = false;
183 m_vertex_count = 0;
184 m_index_count = 0;
185 m_submeshes = std::nullopt;
186}
187
188// =============================================================================
189// build
190// =============================================================================
191
192std::optional<MeshAccess> MeshInsertion::build() const
193{
194 if (!m_layout_set || m_vertex_count == 0 || m_index_count == 0) {
196 "MeshInsertion::build: no data inserted");
197 return std::nullopt;
198 }
199
200 return as_mesh_access(
203 m_layout,
205}
206
207} // namespace MayaFlux::Kakshya
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
std::optional< RegionGroup > m_submeshes
void insert_submesh(std::span< const uint8_t > vertex_bytes, std::span< const uint32_t > index_data, std::string_view name={}, std::string_view material_name={}, const VertexLayout &layout=VertexLayout::for_meshes(60))
Append one submesh batch, accumulating into the shared buffers.
MeshInsertion(DataVariant &vertex_variant, DataVariant &index_variant)
Construct with mutable references to the two storage variants.
std::optional< MeshAccess > build() const
Produce a MeshAccess over the current variant contents.
uint32_t m_vertex_count
Running total across all submitted batches.
void insert_flat(std::span< const uint8_t > vertex_bytes, std::span< const uint32_t > index_data, const VertexLayout &layout)
Insert a single flat mesh (no submesh tracking).
bool validate_layout(const VertexLayout &incoming) const
void clear()
Clear both variants and reset all internal state.
@ Runtime
General runtime operations (default fallback)
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.
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
Region to_region() const
Convert this subrange to a Region for use in RegionGroup.
uint32_t vertex_offset
Base vertex added to each index (large-mesh batching)
Byte-range descriptor for one submesh within the shared index buffer.
Organizes related signal regions into a categorized collection.
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.
std::vector< VertexAttributeLayout > attributes
All attributes that make up one vertex Ordered by shader location (0, 1, 2, ...)
Complete description of vertex data layout in a buffer.