MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Mint.cpp
Go to the documentation of this file.
1#include "Mint.hpp"
2
16
17namespace MayaFlux {
18
19namespace {
20
21 [[nodiscard]] bool has_target(const StructureConfig::RenderConfig& render)
22 {
23 if (render.target_window) {
24 return true;
25 }
26
28 "mint: RenderConfig::target_window is required, there is no default window");
29 return false;
30 }
31
32 [[nodiscard]] std::shared_ptr<Nodes::GpuSync::MeshWriterNode> resolve_writer(
33 const std::optional<Kakshya::MeshData>& mesh,
34 const StructureConfig::MeshExpression& expression,
35 const std::shared_ptr<Nodes::GpuSync::MeshWriterNode>& writer,
36 std::string_view context)
37 {
38 const unsigned int source_count = static_cast<unsigned int>(mesh.has_value())
39 + static_cast<unsigned int>(static_cast<bool>(expression))
40 + static_cast<unsigned int>(writer != nullptr);
41
42 if (source_count != 1) {
44 "mint: {} requires exactly one mesh, expression or writer source", context);
45 return nullptr;
46 }
47
48 if (writer) {
49 return writer;
50 }
51
52 Kakshya::MeshData data = mesh ? *mesh : expression();
53 if (!data.is_valid()) {
55 "mint: {} produced invalid MeshData", context);
56 return nullptr;
57 }
58
59 auto resolved = std::make_shared<Nodes::GpuSync::MeshWriterNode>(data.vertex_count());
60 resolved->set_mesh(data);
61 return resolved;
62 }
63
64 void add_extra_textures(
66 const std::vector<std::shared_ptr<Core::VKImage>>& textures,
67 size_t first)
68 {
69 for (size_t index = first; index < textures.size(); ++index) {
70 if (textures[index]) {
71 render.additional_textures.emplace_back(
72 "texture" + std::to_string(index), textures[index]);
73 }
74 }
75 }
76
77 void add_all_textures(
79 const std::vector<std::shared_ptr<Core::VKImage>>& textures)
80 {
81 if (!textures.empty() && textures.front()) {
82 render.additional_textures.emplace_back("diffuseTex", textures.front());
83 }
84 add_extra_textures(render, textures, 1);
85 }
86
87 void register_network_if_needed(
88 const std::shared_ptr<Nodes::Network::NodeNetwork>& network)
89 {
90 if (!get_node_graph_manager()->is_network_registered(
93 }
94 }
95
96 template <typename Buffer>
97 void bind_mesh_textures(
98 const std::shared_ptr<Buffer>& buffer,
100 const std::vector<std::shared_ptr<Core::VKImage>>& textures)
101 {
102 if (!textures.empty() && textures.front()) {
103 const std::string binding = render.default_texture_binding.empty()
104 ? "diffuseTex"
105 : render.default_texture_binding;
106 buffer->bind_diffuse_texture(textures.front(), binding);
107 render.default_texture_binding = binding;
108 }
109 add_extra_textures(render, textures, 1);
110 }
111
112} // namespace
113
114/** @brief Wiring sequences behind Mint. Holds no state. */
116 [[nodiscard]] std::shared_ptr<Buffers::MeshBuffer> build(
117 const StructureConfig::Object& config) const
118 {
119 if (!has_target(config.render)) {
120 return nullptr;
121 }
122
123 const unsigned int source_count = static_cast<unsigned int>(config.mesh.has_value())
124 + static_cast<unsigned int>(static_cast<bool>(config.expression))
125 + static_cast<unsigned int>(config.writer != nullptr);
126 if (source_count != 1) {
128 "mint: Object requires exactly one mesh, expression or writer source");
129 return nullptr;
130 }
131
132 auto writer = resolve_writer(
133 config.mesh, config.expression, config.writer, "Object");
134 if (!writer) {
135 return nullptr;
136 }
137
138 auto buffer = std::make_shared<Buffers::MeshBuffer>(writer);
139
141 bind_mesh_textures(buffer, render, config.textures);
143 buffer->setup_rendering(render);
144 return buffer;
145 }
146
147 [[nodiscard]] std::shared_ptr<Buffers::MeshNetworkBuffer> build(
148 const StructureConfig::Model& config) const
149 {
150 if (!has_target(config.render)) {
151 return nullptr;
152 }
153
154 auto network = config.network
155 ? config.network
156 : std::make_shared<Nodes::Network::MeshNetwork>();
157 const auto first_component_slot = static_cast<uint32_t>(network->slot_count());
158
159 for (size_t index = 0; index < config.components.size(); ++index) {
160 const auto& component = config.components[index];
161 auto writer = resolve_writer(
162 component.mesh, component.expression, component.writer, "Model component");
163 if (!writer) {
164 return nullptr;
165 }
166
167 if (component.parent_component && component.parent_slot) {
169 "mint: Model component {} cannot name both a component and slot parent",
170 index);
171 return nullptr;
172 }
173
174 std::optional<uint32_t> parent;
175 if (component.parent_component) {
176 if (*component.parent_component >= index) {
178 "mint: Model component {} must name an earlier component as parent",
179 index);
180 return nullptr;
181 }
182 parent = first_component_slot + *component.parent_component;
183 } else if (component.parent_slot) {
184 if (*component.parent_slot >= first_component_slot) {
186 "mint: Model component {} parent slot is not in the supplied network",
187 index);
188 return nullptr;
189 }
190 parent = component.parent_slot;
191 }
192
193 const uint32_t slot_index = network->add_slot(
194 "component_" + std::to_string(index), writer, parent);
195 network->get_slot(slot_index).local_transform = component.local_transform;
196 }
197
198 if (network->slot_count() == 0) {
200 "mint: Model requires at least one mesh component");
201 return nullptr;
202 }
203
204 register_network_if_needed(network);
205 auto buffer = std::make_shared<Buffers::MeshNetworkBuffer>(
208 bind_mesh_textures(buffer, render, config.textures);
210 buffer->setup_rendering(render);
211 return buffer;
212 }
213
214 [[nodiscard]] std::shared_ptr<Buffers::InstanceNetworkBuffer> build(
215 const StructureConfig::Instances& config) const
216 {
217 if (!has_target(config.render)) {
218 return nullptr;
219 }
220
221 auto network = config.network
222 ? config.network
223 : std::make_shared<Nodes::Network::InstanceNetwork>();
224
225 if (!config.transforms.empty()) {
226 auto writer = resolve_writer(
227 config.prototype_mesh,
229 config.prototype_writer,
230 "Instances prototype");
231 if (!writer) {
232 return nullptr;
233 }
234
235 for (size_t index = 0; index < config.transforms.size(); ++index) {
236 const uint32_t slot_index = network->add_slot(
237 "instance_" + std::to_string(index), writer);
238 network->get_slot(slot_index).transform = config.transforms[index];
239 }
240 }
241
242 if (network->slot_count() == 0) {
244 "mint: Instances requires an existing populated network or transforms");
245 return nullptr;
246 }
247
248 register_network_if_needed(network);
249 auto buffer = std::make_shared<Buffers::InstanceNetworkBuffer>(
252 add_all_textures(render, config.textures);
254 buffer->setup_rendering(render);
255 return buffer;
256 }
257
258 [[nodiscard]] std::shared_ptr<Buffers::NetworkGeometryBuffer> build(
259 const StructureConfig::Assembly& config) const
260 {
261 if (!has_target(config.render)) {
262 return nullptr;
263 }
264
265 auto network = config.network
266 ? config.network
267 : std::make_shared<Nodes::Network::AssemblyNetwork>();
268
269 for (const auto& source : config.sources) {
270 network->add_geometry(source);
271 }
272
273 if (network->get_node_count() == 0) {
275 "mint: Assembly requires at least one geometry source");
276 return nullptr;
277 }
278
279 register_network_if_needed(network);
280 auto buffer = std::make_shared<Buffers::NetworkGeometryBuffer>(network);
282 render.triangulate = true;
283 add_all_textures(render, config.textures);
285 buffer->setup_rendering(render);
286 buffer->get_render_processor()->set_mill_spec(config.mill);
287 return buffer;
288 }
289
290 [[nodiscard]] std::shared_ptr<Buffers::ComputeMeshBuffer> build(
291 const StructureConfig::Isosurface& config) const
292 {
293 if (!has_target(config.render)) {
294 return nullptr;
295 }
296
297 const bool has_buffer = config.buffer != nullptr;
298 const bool has_config = config.config.has_value();
299 if (static_cast<unsigned int>(has_buffer)
300 + static_cast<unsigned int>(has_config)
301 != 1) {
303 "mint: Isosurface requires exactly one buffer or config");
304 return nullptr;
305 }
306
307 auto buffer = has_buffer
308 ? config.buffer
309 : std::make_shared<Buffers::ComputeMeshBuffer>(*config.config);
310
312 if (!config.textures.empty() && config.textures.front()) {
313 const std::string binding = render.default_texture_binding.empty()
314 ? "diffuseTex"
316 buffer->set_texture(config.textures.front(), binding);
317 render.default_texture_binding = binding;
318 }
319 add_extra_textures(render, config.textures, 1);
321 buffer->setup_rendering(render);
322 return buffer;
323 }
324};
325
327 : m_impl(std::make_unique<Impl>())
328{
329}
330
331Mint::~Mint() = default;
332
333Mint::Mint(Mint&&) noexcept = default;
334
335Mint& Mint::operator=(Mint&&) noexcept = default;
336
337std::shared_ptr<Buffers::MeshBuffer> Mint::build(
338 const StructureConfig::Object& config)
339{
340 return m_impl->build(config);
341}
342
343std::shared_ptr<Buffers::MeshNetworkBuffer> Mint::build(
344 const StructureConfig::Model& config)
345{
346 return m_impl->build(config);
347}
348
349std::shared_ptr<Buffers::InstanceNetworkBuffer> Mint::build(
350 const StructureConfig::Instances& config)
351{
352 return m_impl->build(config);
353}
354
355std::shared_ptr<Buffers::NetworkGeometryBuffer> Mint::build(
356 const StructureConfig::Assembly& config)
357{
358 return m_impl->build(config);
359}
360
361std::shared_ptr<Buffers::ComputeMeshBuffer> Mint::build(
362 const StructureConfig::Isosurface& config)
363{
364 return m_impl->build(config);
365}
366
367} // namespace MayaFlux
#define MF_ERROR(comp, ctx,...)
Core::GlobalNetworkConfig network
Definition Config.cpp:43
std::vector< uint32_t > parent
std::shared_ptr< NetworkGeometryBuffer > buffer
uint32_t index
Definition VKDevice.cpp:122
std::unique_ptr< Impl > m_impl
Definition Mint.hpp:104
std::shared_ptr< Buffers::MeshBuffer > build(const StructureConfig::Object &config)
Definition Mint.cpp:337
Turns a structural config into a registered and rendered object.
Definition Mint.hpp:28
@ Init
Engine/subsystem initialization.
@ API
MayaFlux/API Wrapper and convenience functions.
@ VISUAL_RATE
Nodes that process at the visual frame rate.
std::shared_ptr< Nodes::NodeGraphManager > get_node_graph_manager()
Gets the node graph manager from the default engine.
Definition Graph.cpp:51
void register_node_network(const std::shared_ptr< Nodes::Network::NodeNetwork > &network, const Nodes::ProcessingToken &token)
Registers a node network with the default engine's node graph manager.
Definition Graph.cpp:208
void register_graphics_buffer(const std::shared_ptr< Buffers::VKBuffer > &buffer, Buffers::ProcessingToken token)
Registers a VKBuffer with the default engine's buffer manager.
Definition Graph.cpp:250
Main namespace for the Maya Flux audio engine.
Definition Runtime.cpp:12
std::shared_ptr< Buffers::NetworkGeometryBuffer > build(const StructureConfig::Assembly &config) const
Definition Mint.cpp:258
std::shared_ptr< Buffers::MeshNetworkBuffer > build(const StructureConfig::Model &config) const
Definition Mint.cpp:147
std::shared_ptr< Buffers::MeshBuffer > build(const StructureConfig::Object &config) const
Definition Mint.cpp:116
std::shared_ptr< Buffers::ComputeMeshBuffer > build(const StructureConfig::Isosurface &config) const
Definition Mint.cpp:290
std::shared_ptr< Buffers::InstanceNetworkBuffer > build(const StructureConfig::Instances &config) const
Definition Mint.cpp:214
Wiring sequences behind Mint.
Definition Mint.cpp:115
bool triangulate
Reduce supplied spans to triangles before drawing them.
Unified rendering configuration for graphics buffers.
std::shared_ptr< Nodes::Network::AssemblyNetwork > network
Existing assembly to complete, or null to construct one.
Portal::Graphics::MillSpec mill
Fixed milling policy shared by the rendered assembly.
std::vector< std::shared_ptr< Core::VKImage > > textures
Images available to the selected render pipeline.
RenderConfig render
Required render destination and pipeline overrides.
std::vector< Nodes::Network::AssemblyNetwork::Source > sources
Independent sources appended before registration.
Independent heterogeneous sources and their shared milling policy.
std::shared_ptr< Nodes::Network::InstanceNetwork > network
Existing network to complete, or null to construct one.
std::optional< Kakshya::MeshData > prototype_mesh
Fixed prototype source.
MeshExpression prototype_expression
Fixed prototype expression.
float over_allocate_factor
Fixed initial vertex-buffer capacity multiplier.
std::vector< glm::mat4 > transforms
Fixed initial world transform for each new instance.
std::shared_ptr< Nodes::GpuSync::MeshWriterNode > prototype_writer
Live prototype source.
RenderConfig render
Required render destination and pipeline overrides.
std::vector< std::shared_ptr< Core::VKImage > > textures
Images available to the selected render pipeline.
Prototype mesh and world transforms for one InstanceNetworkBuffer.
std::vector< std::shared_ptr< Core::VKImage > > textures
Images available to the selected render pipeline.
std::optional< Buffers::ComputeMeshBuffer::Config > config
Library-owned construction state when Mint creates the buffer.
RenderConfig render
Required render destination and pipeline overrides.
std::shared_ptr< Buffers::ComputeMeshBuffer > buffer
Existing isosurface buffer, exclusive with config.
Existing isosurface buffer or new buffer construction state.
float over_allocate_factor
Fixed initial vertex-buffer capacity multiplier.
std::shared_ptr< Nodes::Network::MeshNetwork > network
Existing network to complete, or null to construct one.
RenderConfig render
Required render destination and pipeline overrides.
std::vector< ModelComponent > components
Components appended before registration.
std::vector< std::shared_ptr< Core::VKImage > > textures
Images available to the selected render pipeline.
Mesh components and allocation policy for one MeshNetworkBuffer.
RenderConfig render
Required render destination and pipeline overrides.
MeshExpression expression
Fixed construction expression.
std::shared_ptr< Nodes::GpuSync::MeshWriterNode > writer
Live geometry source.
std::optional< Kakshya::MeshData > mesh
Fixed materialised source.
std::vector< std::shared_ptr< Core::VKImage > > textures
Images available to the selected render pipeline.
One independently rendered mesh-backed object.
std::function< Kakshya::MeshData()> MeshExpression
A one-shot typed mesh expression, normally invoking Kinesis.
Buffers::VKBuffer::RenderConfig RenderConfig
Render target and pipeline overrides.
API-side playground for a complete visible structure.