MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
MeshNetwork.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "MeshSlot.hpp"
4#include "NodeNetwork.hpp"
5
7
8/**
9 * @class MeshNetwork
10 * @brief NodeNetwork subclass whose nodes are named, hierarchically
11 * transformable mesh slots.
12 *
13 * Each slot holds a MeshWriterNode (geometry) and a local-space glm::mat4.
14 * Slots form an optional DAG via parent indices; MeshNetwork resolves
15 * processing order so parents are always updated before children.
16 * World transforms propagate as: world = parent_world * local.
17 *
18 * The primary operator (set via create_operator<T> / set_operator) runs
19 * first each cycle. The operator chain (get_operator_chain()) runs after.
20 * Both receive the slot list via the operator interface.
21 *
22 * MeshNetwork initializes m_operator_chain on construction because it
23 * requires multi-operator sequencing as a necessity, not an option.
24 *
25 * No topology enum from NodeNetwork is used: the DAG is explicit via
26 * parent indices in each MeshSlot.
27 *
28 * Usage:
29 * @code
30 * auto net = std::make_shared<MeshNetwork>();
31 *
32 * auto torso_node = std::make_shared<GpuSync::MeshWriterNode>();
33 * torso_node->set_mesh(torso_verts, torso_indices);
34 * uint32_t torso = net->add_slot("torso", torso_node);
35 *
36 * auto arm_node = std::make_shared<GpuSync::MeshWriterNode>();
37 * arm_node->set_mesh(arm_verts, arm_indices);
38 * uint32_t arm_l = net->add_slot("arm_l", arm_node, torso);
39 *
40 * net->create_operator<MeshTransformOperator>();
41 * net->get_operator_chain()->emplace<MeshFieldOperator>();
42 * @endcode
43 */
44class MAYAFLUX_API MeshNetwork : public NodeNetwork {
45public:
47 ~MeshNetwork() override = default;
48
49 // -------------------------------------------------------------------------
50 // Slot management
51 // -------------------------------------------------------------------------
52
53 /**
54 * @brief Add a slot to the network.
55 * @param name Logical name for lookup and logging.
56 * @param node MeshWriterNode carrying the slot's geometry.
57 * @param parent Index of the parent slot, or nullopt for a root slot.
58 * @return Stable index of the new slot. Never changes after insertion.
59 */
60 uint32_t add_slot(
61 std::string name,
62 std::shared_ptr<GpuSync::MeshWriterNode> node,
63 std::optional<uint32_t> parent = std::nullopt);
64
65 /**
66 * @brief Return the slot at the given index.
67 * @param index Slot index as returned by add_slot().
68 */
69 [[nodiscard]] MeshSlot& get_slot(uint32_t index);
70 [[nodiscard]] const MeshSlot& get_slot(uint32_t index) const;
71
72 /**
73 * @brief Find a slot by name.
74 * @return Pointer to the slot, or nullptr if not found.
75 */
76 [[nodiscard]] MeshSlot* find_slot(std::string_view name);
77 [[nodiscard]] const MeshSlot* find_slot(std::string_view name) const;
78
79 /**
80 * @brief Find the index of a slot by name.
81 * @return Index, or nullopt if not found.
82 */
83 [[nodiscard]] std::optional<uint32_t> find_slot_index(std::string_view name) const;
84
85 /**
86 * @brief Number of slots in the network.
87 */
88 [[nodiscard]] size_t slot_count() const { return m_slots.size(); }
89
90 /**
91 * @brief Read-only access to the full slot list.
92 */
93 [[nodiscard]] const std::vector<MeshSlot>& slots() const { return m_slots; }
94 [[nodiscard]] std::vector<MeshSlot>& slots() { return m_slots; }
95
96 // -------------------------------------------------------------------------
97 // NodeNetwork interface
98 // -------------------------------------------------------------------------
99
100 void process_batch(unsigned int num_samples) override;
101 void reset() override;
102
103 [[nodiscard]] size_t get_node_count() const override { return m_slots.size(); }
104 [[nodiscard]] std::optional<double> get_node_output(size_t index) const override;
105 [[nodiscard]] std::unordered_map<std::string, std::string> get_metadata() const override;
106
107 // -------------------------------------------------------------------------
108 // Operator management (mirrors ParticleNetwork pattern)
109 // -------------------------------------------------------------------------
110
111 /**
112 * @brief Replace the primary operator.
113 * @param op New operator. Must be non-null.
114 */
115 void set_operator(std::shared_ptr<NetworkOperator> op);
116
117 /**
118 * @brief Construct and set the primary operator in one call.
119 * @tparam OpType Concrete operator type.
120 * @return Shared pointer to the new operator.
121 */
122 template <typename OpType, typename... Args>
123 std::shared_ptr<OpType> create_operator(Args&&... args)
124 {
125 auto op = std::make_shared<OpType>(std::forward<Args>(args)...);
126 set_operator(op);
127 return op;
128 }
129
131 {
132 return m_operator.get();
133 }
134
135 const NetworkOperator* get_operator() const override
136 {
137 return m_operator.get();
138 }
139
140 bool has_operator() const override
141 {
142 return m_operator != nullptr;
143 }
144
145 /**
146 * @brief Get the processing order of slots as indices into m_slots.
147 * Parents always appear before children.
148 */
149 [[nodiscard]] const std::vector<uint32_t>& sorted_indices() const { return m_sorted_indices; }
150
151 /**
152 * @brief Ensure the slot processing order is up to date. Called internally
153 * before processing, but can be called manually after making changes
154 * to the slot DAG.
155 */
156 void ensure_sorted();
157
158private:
159 std::vector<MeshSlot> m_slots;
160
161 /// @brief Processing order: indices into m_slots, parents before children.
162 std::vector<uint32_t> m_sorted_indices;
163
164 /// @brief Set when add_slot() changes the DAG and a re-sort is needed.
165 bool m_sort_dirty { true };
166
167 std::shared_ptr<NetworkOperator> m_operator;
168
169 void rebuild_sort();
170 void propagate_world_transforms();
171};
172
173} // namespace MayaFlux::Nodes::Network
std::vector< uint32_t > m_sorted_indices
Processing order: indices into m_slots, parents before children.
size_t get_node_count() const override
Get the number of nodes in the network.
size_t slot_count() const
Number of slots in the network.
std::shared_ptr< NetworkOperator > m_operator
NetworkOperator * get_operator() override
const std::vector< MeshSlot > & slots() const
Read-only access to the full slot list.
std::vector< MeshSlot > & slots()
const std::vector< uint32_t > & sorted_indices() const
Get the processing order of slots as indices into m_slots.
std::shared_ptr< OpType > create_operator(Args &&... args)
Construct and set the primary operator in one call.
const NetworkOperator * get_operator() const override
NodeNetwork subclass whose nodes are named, hierarchically transformable mesh slots.
Domain-agnostic interpretive lens for network processing.
Abstract base class for structured collections of nodes with defined relationships.
Named, independently transformable mesh unit within a MeshNetwork.
Definition MeshSlot.hpp:31