26 std::shared_ptr<GpuSync::MeshWriterNode> node,
27 std::optional<uint32_t>
parent)
30 error<std::invalid_argument>(
32 std::source_location::current(),
33 "MeshNetwork::add_slot: null MeshWriterNode for slot '{}'",
name);
37 error<std::out_of_range>(
39 std::source_location::current(),
40 "MeshNetwork::add_slot: parent index {} out of range (slot count: {})",
44 const auto idx =
static_cast<uint32_t
>(
m_slots.size());
49 slot.
node = std::move(node);
57 m_slots.push_back(std::move(slot));
61 "MeshNetwork: added slot '{}' at index {} (parent: {})",
63 parent.has_value() ? std::to_string(
parent.value()) :
"none");
80 auto it = std::ranges::find_if(
m_slots,
82 return it !=
m_slots.end() ? &*it :
nullptr;
87 auto it = std::ranges::find_if(
m_slots,
89 return it !=
m_slots.end() ? &*it :
nullptr;
94 for (uint32_t i = 0; i < static_cast<uint32_t>(
m_slots.size()); ++i) {
115 for (
unsigned int frame = 0; frame < num_samples; ++frame) {
126 if (
auto* mesh_op =
dynamic_cast<MeshOperator*
>(op.get()))
133 for (
const auto& slot :
m_slots) {
135 slot.node->compute_frame();
142 slot.local_transform = glm::mat4(1.0F);
143 slot.world_transform = glm::mat4(1.0F);
152 return static_cast<double>(
index);
158 meta[
"slot_count"] = std::to_string(
m_slots.size());
174 "MeshNetwork::set_operator: null operator ignored");
193 std::vector<uint32_t> queue;
194 for (uint32_t i = 0; i < static_cast<uint32_t>(
m_slots.size()); ++i) {
195 if (!
m_slots[i].parent_index.has_value())
202 while (!queue.empty()) {
203 uint32_t idx = queue.front();
204 queue.erase(queue.begin());
207 for (uint32_t child :
m_slots[idx].child_indices)
208 queue.push_back(child);
213 "MeshNetwork: slot DAG contains a cycle — sort is incomplete");
219 "MeshNetwork: rebuilt slot sort order ({} slots)",
m_sorted_indices.size());
226 if (slot.parent_index.has_value()) {
228 =
m_slots[slot.parent_index.value()].world_transform
229 * slot.local_transform;
231 slot.world_transform = slot.local_transform;
241 for (
const auto& slot :
m_slots) {
246 const auto packed = slot.node->get_mesh_data();
252 std::get<std::vector<uint8_t>>(packed->vertex_variant),
253 std::get<std::vector<uint32_t>>(packed->index_variant),
254 slot.name.empty() ? std::to_string(slot.index) : slot.name,
259 const auto access = ins.
build();
263 mesh_data.layout = access->layout;
264 mesh_data.submeshes = access->submeshes;
#define MF_ERROR(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
std::vector< uint32_t > parent
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.
std::optional< MeshAccess > build() const
Produce a MeshAccess over the current variant contents.
Write counterpart to MeshAccess.
std::vector< MeshSlot > m_slots
MeshSlot & get_slot(uint32_t index)
Return the slot at the given index.
void propagate_world_transforms()
std::vector< uint32_t > m_sorted_indices
Processing order: indices into m_slots, parents before children.
bool m_sort_dirty
Set when add_slot() changes the DAG and a re-sort is needed.
void set_operator(std::shared_ptr< NetworkOperator > op)
Replace the primary operator.
std::optional< Kakshya::MeshData > get_mesh_data() const
Every slot's geometry merged into one MeshData, one submesh per slot.
std::unordered_map< std::string, std::string > get_metadata() const override
Get network metadata for debugging/visualization.
uint32_t add_slot(std::string name, std::shared_ptr< GpuSync::MeshWriterNode > node, std::optional< uint32_t > parent=std::nullopt)
Add a slot to the network.
std::shared_ptr< NetworkOperator > m_operator
void process_batch(unsigned int num_samples) override
Process the network for the given number of samples.
void ensure_sorted()
Ensure the slot processing order is up to date.
std::optional< uint32_t > find_slot_index(std::string_view name) const
Find the index of a slot by name.
MeshSlot * find_slot(std::string_view name)
Find a slot by name.
std::optional< double > get_node_output(size_t index) const override
Get output of specific internal node (for ONE_TO_ONE mapping)
void reset() override
Reset network to initial state.
Abstract base for operators that process MeshNetwork slots.
virtual void set_topology(Topology topology)
Set the network's topology.
bool is_enabled() const
Check if network is enabled.
float get_timestep() const
Seconds one visual frame advances this network.
std::shared_ptr< OperatorChain > m_operator_chain
virtual std::unordered_map< std::string, std::string > get_metadata() const
Get network metadata for debugging/visualization.
void set_output_mode(OutputMode mode)
Set the network's output routing mode.
@ Init
Engine/subsystem initialization.
@ Nodes
DSP Generator and Filter Nodes, graph pipeline, node management.
@ CUSTOM
User-defined arbitrary topology.
@ GRAPHICS_BIND
State available for visualization (read-only)
static MeshData empty()
Construct an empty MeshData with the canonical 60-byte mesh layout.
std::string name
Logical name. Used for lookup and logging only.
bool dirty
Set when local_transform or slot config changes since last upload.
std::shared_ptr< GpuSync::MeshWriterNode > node
Geometry node for this slot.
uint32_t index
Position of this slot in MeshNetwork::m_slots. Stable after insertion.
std::optional< uint32_t > parent_index
Index of the parent slot, or nullopt for a root slot.
Named, independently transformable mesh unit within a MeshNetwork.