MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ write_operator_sample()

bool MayaFlux::IO::write_operator_sample ( SpatialCache cache,
const std::string &  stream_name,
const Nodes::Network::GraphicsOperator op 
)

Pack one GraphicsOperator's current vertex state into a SpatialCache stream, as a Points or Curves sample depending on what the operator declares.

Reads op->get_vertex_data() as Kakshya::Vertex records: PointVertex, LineVertex, and MeshVertex all share its exact 60-byte layout, so this works unchanged for any GraphicsOperator, not only PhysicsOperator. Every field comes along, not only position: color, scalar (size/thickness/ weight depending on the concrete type), uv, normal, and tangent each become their own SpatialAttribute, so a vertex reaches the archive whole rather than reduced to a coordinate. Always attaches a "cluster" attribute from op->build_cluster_ids() (0 for every vertex on an operator that never overrides it), plus one SpatialAttribute per op->extract_vertex_attributes() entry (extra state beyond the vertex record itself, e.g. PhysicsOperator's mass).

op->declared_topology() decides the sample's shape:

  • nullopt or POINT_LIST: the point path. ids are the vertex's own index within this operator, for cross-sample identity tracking, and native velocities come from op->extract_vertex_velocities() when non-empty.
  • LINE_STRIP (PathOperator): one curve per contiguous build_cluster_ids() run, matching one path per continuous interpolated strip.
  • LINE_LIST (TopologyOperator): fixed 2-vertex curves, one per expanded edge, since a graph's edges are independent segments, not one connected strip through the whole graph. Curve samples carry no ids/velocities (Alembic's Curves schema has neither) and fail outright if declared_topology() reports LINE_LIST for an odd vertex count, which no known producer of that topology should do.
Parameters
cacheTarget cache, already open().
stream_nameStream to write.
opSource operator. Must be non-null, report at least one vertex, and use the Kakshya::Vertex record layout (every GraphicsOperator does today).
Returns
False if op is null, reports zero vertices, its vertex layout is not a Kakshya::Vertex record, its vertex buffer is smaller than layout.stride_bytes * get_vertex_count(), any extract_vertex_attributes()/extract_vertex_velocities() entry disagrees with get_vertex_count() in size, or a LINE_LIST topology's vertex count is odd.

Definition at line 156 of file SpatialExport.cpp.

160{
161 if (!op) {
162 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
163 "write_operator_sample: null operator");
164 return false;
165 }
166
167 const size_t vertex_count = op->get_vertex_count();
168 if (vertex_count == 0) {
169 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
170 "write_operator_sample: operator reports zero vertices");
171 return false;
172 }
173
174 const Kakshya::VertexLayout layout = op->get_vertex_layout();
175 const std::span<const uint8_t> raw = op->get_vertex_data();
176 if (layout.stride_bytes == 0 || raw.size() < static_cast<size_t>(layout.stride_bytes) * vertex_count) {
177 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
178 "write_operator_sample: vertex buffer smaller than layout implies");
179 return false;
180 }
181
182 std::vector<glm::vec3> positions;
183 std::vector<SpatialAttribute> attributes;
184 if (!extract_vertex_columns(layout, raw, vertex_count, positions, attributes)) {
185 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
186 "write_operator_sample: vertex layout is not a Kakshya::Vertex record");
187 return false;
188 }
189
190 std::vector<uint32_t> cluster_ids = op->build_cluster_ids();
191 if (cluster_ids.size() != vertex_count) {
192 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
193 "write_operator_sample: build_cluster_ids() count mismatch");
194 return false;
195 }
196
197 const auto topology = op->declared_topology().value_or(Portal::Graphics::PrimitiveTopology::POINT_LIST);
198 std::optional<std::vector<int32_t>> vertex_counts_per_curve;
199 if (topology == Portal::Graphics::PrimitiveTopology::LINE_LIST
200 || topology == Portal::Graphics::PrimitiveTopology::LINE_STRIP) {
201 vertex_counts_per_curve = curve_vertex_counts(topology, cluster_ids, vertex_count);
202 if (!vertex_counts_per_curve) {
203 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
204 "write_operator_sample: {} vertices cannot form LINE_LIST pairs", vertex_count);
205 return false;
206 }
207 }
208
209 attributes.push_back(SpatialAttribute {
210 .name = "cluster",
211 .scope = SpatialScope::Varying,
212 .values = Kakshya::DataVariant { std::move(cluster_ids) } });
213
214 for (auto& [name, values] : op->extract_vertex_attributes()) {
215 const size_t count = std::visit([](const auto& v) { return v.size(); }, values);
216 if (count != vertex_count) {
217 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
218 "write_operator_sample: extract_vertex_attributes() '{}' count mismatch", name);
219 return false;
220 }
221 attributes.push_back(SpatialAttribute {
222 .name = name,
223 .scope = SpatialScope::Varying,
224 .values = std::move(values) });
225 }
226
227 if (vertex_counts_per_curve) {
228 return cache.write(stream_name,
229 SpatialSample {
230 .topology = topology,
231 .positions = positions,
232 .vertex_counts_per_curve = *vertex_counts_per_curve,
233 .attributes = attributes });
234 }
235
236 std::vector<uint64_t> ids(vertex_count);
237 std::ranges::iota(ids, uint64_t { 0 });
238
239 std::vector<glm::vec3> velocities = op->extract_vertex_velocities();
240 if (!velocities.empty() && velocities.size() != vertex_count) {
241 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
242 "write_operator_sample: extract_vertex_velocities() count mismatch");
243 return false;
244 }
245
246 return cache.write(stream_name,
247 SpatialSample {
248 .topology = Portal::Graphics::PrimitiveTopology::POINT_LIST,
249 .positions = positions,
250 .ids = ids,
251 .velocities = velocities,
252 .attributes = attributes });
253}
#define MF_ERROR(comp, ctx,...)
std::vector< std::byte > values
Definition VDBWriter.cpp:26
std::string name
Definition VKDevice.cpp:143
size_t count
bool write(const std::string &stream_name, const SpatialSample &sample)
Append one sample to a named stream.
virtual size_t get_vertex_count() const =0
Get number of vertices (may differ from point count for topology/path)
virtual std::vector< uint32_t > build_cluster_ids() const
Per-vertex collection index, global index order.
virtual Kakshya::VertexLayout get_vertex_layout() const =0
Get vertex layout describing vertex structure.
virtual std::optional< Portal::Graphics::PrimitiveTopology > declared_topology() const
Topology this operator's vertex data is authored for, if it holds a node to ask.
virtual std::vector< glm::vec3 > extract_vertex_velocities() const
Per-vertex velocity, for a consumer that wants to write it as a native channel (e....
virtual std::span< const uint8_t > get_vertex_data() const =0
Get vertex data for GPU upload.

References MayaFlux::Nodes::Network::GraphicsOperator::build_cluster_ids(), count, MayaFlux::Nodes::Network::GraphicsOperator::declared_topology(), MayaFlux::Nodes::Network::GraphicsOperator::extract_vertex_attributes(), MayaFlux::Nodes::Network::GraphicsOperator::extract_vertex_velocities(), MayaFlux::Journal::FileIO, MayaFlux::Nodes::Network::GraphicsOperator::get_vertex_count(), MayaFlux::Nodes::Network::GraphicsOperator::get_vertex_data(), MayaFlux::Nodes::Network::GraphicsOperator::get_vertex_layout(), MayaFlux::Journal::IO, MayaFlux::Portal::Graphics::LINE_LIST, MayaFlux::Portal::Graphics::LINE_STRIP, MF_ERROR, name, MayaFlux::IO::SpatialAttribute::name, MayaFlux::Portal::Graphics::POINT_LIST, MayaFlux::Kakshya::VertexLayout::stride_bytes, MayaFlux::IO::SpatialSample::topology, values, Varying, and MayaFlux::IO::SpatialCache::write().

Referenced by write_network_geometry_buffer_sample().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: