载入中...
搜索中...
未找到
VolumeFluidCodec.cpp
浏览该文件的文档.
1#include "fluids/VolumeFluidCodecInternal.inc"
2
3namespace eve::fluids {
7 try {
8 unpack(value, decoded, "fluids.surface.rendererSettings");
9 } catch (const std::runtime_error& error) {
11 DiagnosticCode::InvalidArgument, "Invalid, missing or unknown fluid renderer setting", error.what()));
12 }
13 return Result<FluidRendererSettings>::success(std::move(decoded));
14}
15
16Value encodeVolumeFluid(const VolumeFluidSnapshot& snapshot) { return pack(snapshot); }
17Value encodeVolumeFluidFoam(const VolumeFluidFoamSnapshot& snapshot) { return pack(snapshot); }
20 try {
21 unpack(value, decoded, "fluids.volume.foam");
22 } catch (const std::runtime_error& error) {
24 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid foam state fields", error.what()));
25 }
26 VolumeFluidFoam controller;
27 auto validated = controller.restore(decoded);
28 if (!validated) return Result<VolumeFluidFoamSnapshot>::failure(validated.status());
29 return Result<VolumeFluidFoamSnapshot>::success(std::move(decoded));
30}
31Value encodeVolumeFluidDiffuse(const VolumeFluidDiffuseSnapshot& snapshot) { return pack(snapshot); }
34 try {
35 const auto* particles = value.find("particles");
36 if (!particles || !particles->isArray() || particles->arraySize() > 65536)
37 throw std::runtime_error("fluids.volume.diffuse/particles");
38 unpack(value, decoded, "fluids.volume.diffuse");
39 } catch (const std::runtime_error& error) {
41 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid diffuse snapshot fields", error.what()));
42 }
44 auto validated = pool.restore(decoded);
45 if (!validated) return Result<VolumeFluidDiffuseSnapshot>::failure(validated.status());
46 return Result<VolumeFluidDiffuseSnapshot>::success(std::move(decoded));
47}
49 std::vector<VolumeFluidDiffuseParticle> decoded;
50 try {
51 if (!value.isArray() || value.arraySize() > 65536) throw std::runtime_error("fluids.volume.diffuse/particles");
52 unpack(value, decoded, "fluids.volume.diffuse/particles");
53 } catch (const std::runtime_error& error) {
55 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid diffuse particle fields", error.what()));
56 }
57 return Result<std::vector<VolumeFluidDiffuseParticle>>::success(std::move(decoded));
58}
59Value encodeVolumeFluidFieldSamples(const std::vector<VolumeFluidFieldSample>& samples) { return pack(samples); }
60Value encodeVolumeFluidRayHits(const std::vector<VolumeFluidRayHit>& hits) { return pack(hits); }
61Value encodeVolumeFluidDistanceHits(const std::vector<VolumeFluidDistanceHit>& hits) { return pack(hits); }
62Value encodeVolumeFluidQueryHits(const std::vector<VolumeFluidQueryHit>& hits) { return pack(hits); }
63Value encodeVolumeFluidSimplexHits(const std::vector<VolumeFluidSimplexHit>& hits) { return pack(hits); }
65 std::vector<VolumeFluidSimplex> decoded;
66 try {
67 if (!value.isArray() || value.arraySize() > 65536) throw std::runtime_error("fluids.volume/simplexes");
68 unpack(value, decoded, "fluids.volume/simplexes");
69 } catch (const std::runtime_error& error) {
71 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid simplex fields or count", error.what()));
72 }
73 return Result<std::vector<VolumeFluidSimplex>>::success(std::move(decoded));
74}
76 std::vector<VolumeFluidStitch> decoded;
77 try {
78 if (!value.isArray() || value.arraySize() > 65536) throw std::runtime_error("fluids.volume/stitches");
79 unpack(value, decoded, "fluids.volume/stitches");
80 } catch (const std::runtime_error& error) {
82 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid stitch fields or count", error.what()));
83 }
84 return Result<std::vector<VolumeFluidStitch>>::success(std::move(decoded));
85}
87 std::vector<VolumeFluidQueryShape> decoded;
88 try {
89 if (!value.isArray() || value.arraySize() > 256) throw std::runtime_error("fluids.volume.queries");
90 unpack(value, decoded, "fluids.volume.queries");
91 } catch (const std::runtime_error& error) {
93 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid query fields or count", error.what()));
94 }
95 return Result<std::vector<VolumeFluidQueryShape>>::success(std::move(decoded));
96}
98 std::vector<glm::vec4> decoded;
99 try {
100 if (!value.isArray() || value.arraySize() > 256) throw std::runtime_error("fluids.volume.queryColors");
101 unpack(value, decoded, "fluids.volume.queryColors");
102 } catch (const std::runtime_error& error) {
103 return Result<std::vector<glm::vec4>>::failure(
104 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid query color fields or count", error.what()));
105 }
106 return Result<std::vector<glm::vec4>>::success(std::move(decoded));
107}
109 std::vector<glm::vec3> decoded;
110 try {
111 if (!value.isArray() || value.arraySize() > 65536) throw std::runtime_error("fluids.volume.field/positions");
112 unpack(value, decoded, "fluids.volume.field/positions");
113 } catch (const std::runtime_error& error) {
114 return Result<std::vector<glm::vec3>>::failure(
115 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid field query positions", error.what()));
116 }
117 return Result<std::vector<glm::vec3>>::success(std::move(decoded));
118}
120 std::vector<VolumeFluidWindZone> decoded;
121 try {
122 if (!value.isArray() || value.arraySize() > 64) throw std::runtime_error("fluids.volume.wind/zones");
123 unpack(value, decoded, "fluids.volume.wind/zones");
124 } catch (const std::runtime_error& error) {
126 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid wind-zone fields or count", error.what()));
127 }
128 return Result<std::vector<VolumeFluidWindZone>>::success(std::move(decoded));
129}
130Value encodeVolumeFluidCollider(const VolumeFluidCollider& collider) { return pack(collider); }
131Value encodeVolumeFluidSdfCollider(const VolumeFluidSdfCollider& collider) { return pack(collider); }
135 std::vector<VolumeFluidSdfPose> decoded;
136 try {
137 if (!value.isArray() || value.arraySize() > 16) throw std::runtime_error("fluids.volume.sdfPoses");
138 unpack(value, decoded, "fluids.volume.sdfPoses");
139 } catch (const std::runtime_error& error) {
141 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid SDF pose fields", error.what()));
142 }
143 return Result<std::vector<VolumeFluidSdfPose>>::success(std::move(decoded));
144}
146 std::vector<VolumeFluidSdfCollider> decoded;
147 try {
148 if (!value.isArray() || value.arraySize() > 16) throw std::runtime_error("fluids.volume.sdfColliders");
149 unpack(value, decoded, "fluids.volume.sdfColliders");
150 } catch (const std::runtime_error& error) {
152 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid SDF collider fields or count", error.what()));
153 }
154 return Result<std::vector<VolumeFluidSdfCollider>>::success(std::move(decoded));
155}
157 std::vector<VolumeFluidHeightFieldCollider> decoded;
158 try {
159 if (!value.isArray() || value.arraySize() > 16) throw std::runtime_error("fluids.volume.heightFieldColliders");
160 unpack(value, decoded, "fluids.volume.heightFieldColliders");
161 } catch (const std::runtime_error& error) {
163 DiagnosticCode::InvalidArgument, "Invalid height-field collider fields or count", error.what()));
164 }
165 return Result<std::vector<VolumeFluidHeightFieldCollider>>::success(std::move(decoded));
166}
167Value encodeVolumeFluidWindZone(const VolumeFluidWindZone& zone) { return pack(zone); }
168Value encodeVolumeFluidContacts(const std::vector<VolumeFluidContact>& contacts) { return pack(contacts); }
169Value encodeVolumeFluidContactEvents(const std::vector<VolumeFluidContactEvent>& events) { return pack(events); }
172 std::vector<VolumeFluidViscosityColorKey> decoded;
173 try {
174 if (!value.isArray() || value.arraySize() > 32) throw std::runtime_error("fluids.volume.viscosityColors");
175 unpack(value, decoded, "fluids.volume.viscosityColors");
176 } catch (const std::runtime_error& error) {
178 DiagnosticCode::InvalidArgument, "Invalid viscosity color fields or count", error.what()));
179 }
180 return Result<std::vector<VolumeFluidViscosityColorKey>>::success(std::move(decoded));
181}
183 std::vector<VolumeFluidColorKey> decoded;
184 try {
185 if (!value.isArray() || value.arraySize() < 2 || value.arraySize() > 32)
186 throw std::runtime_error("fluids.volume.colorGradient");
187 unpack(value, decoded, "fluids.volume.colorGradient");
188 } catch (const std::runtime_error& error) {
190 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid color gradient fields or count", error.what()));
191 }
192 return Result<std::vector<VolumeFluidColorKey>>::success(std::move(decoded));
193}
195 std::vector<VolumeFluidThermalRule> decoded;
196 try {
197 if (!value.isArray() || value.arraySize() > 1024) throw std::runtime_error("fluids.volume.thermalRules");
198 unpack(value, decoded, "fluids.volume.thermalRules");
199 } catch (const std::runtime_error& error) {
201 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid thermal rule fields or count", error.what()));
202 }
203 return Result<std::vector<VolumeFluidThermalRule>>::success(std::move(decoded));
204}
205Value encodeVolumeFluidParticles(const std::vector<VolumeFluidParticle>& particles) { return pack(particles); }
208 VolumeFluidMaterial decoded;
209 try {
210 unpack(value, decoded, "fluids.volume.material");
211 } catch (const std::runtime_error& error) {
213 DiagnosticCode::InvalidArgument, "Invalid, missing or unknown material field", error.what()));
214 }
216}
217
221 try {
222 unpack(value, decoded, "fluids.volume.emitterBlueprint");
223 } catch (const std::runtime_error& error) {
226 "Invalid, missing or unknown fluid emitter blueprint field", error.what()));
227 }
228 return Result<VolumeFluidEmitterBlueprint3D>::success(std::move(decoded));
229}
231 return pack(blueprint);
232}
235 try {
236 unpack(value, decoded, "fluids.volume.granularEmitterBlueprint");
237 } catch (const std::runtime_error& error) {
240 "Invalid, missing or unknown granular emitter blueprint field", error.what()));
241 }
242 return Result<VolumeGranularEmitterBlueprint3D>::success(std::move(decoded));
243}
245 Value result(Value::Object{});
246 VolumeFluidSnapshot solver;
247 solver.settings = application.settings;
248 result.set("solver", encodeVolumeFluid(solver));
249 result.set("emission", encodeVolumeFluidEmission(application.emission));
250 Value metrics(Value::Object{});
251 metrics.set("particleSize", double(application.metrics.particleSize));
252 metrics.set("particleMass", double(application.metrics.particleMass));
253 metrics.set("smoothingRadius", double(application.metrics.smoothingRadius));
254 result.set("metrics", std::move(metrics));
255 return result;
256}
258 std::vector<VolumeFluidCollider> decoded;
259 try {
260 if (!value.isArray() || value.arraySize() > 1024) throw std::runtime_error("fluids.volume.colliders");
261 unpack(value, decoded, "fluids.volume.colliders");
262 } catch (const std::runtime_error& error) {
264 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid collider fields or count", error.what()));
265 }
266 return Result<std::vector<VolumeFluidCollider>>::success(std::move(decoded));
267}
268
270 VolumeFluidNozzlePose decoded;
271 try {
272 unpack(value, decoded, "fluids.volume.nozzlePose");
273 } catch (const std::runtime_error& error) {
275 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid nozzle pose fields", error.what()));
276 }
278}
279
283 try {
284 unpack(value, decoded, "fluids.volume.emitterState");
285 } catch (const std::runtime_error& error) {
287 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid emitter-state fields", error.what()));
288 }
291 auto validated = decoded.kind == 0 ? rate.restore(decoded) : jet.restore(decoded);
292 if (!validated) return Result<VolumeFluidEmitterSnapshot>::failure(validated.status());
293 return Result<VolumeFluidEmitterSnapshot>::success(std::move(decoded));
294}
295
297 std::vector<VolumeFluidParticle> decoded;
298 try {
299 unpack(value, decoded, "fluids.volume.particles");
300 } catch (const std::runtime_error& error) {
302 DiagnosticCode::InvalidArgument, "Invalid, missing or unknown particle field", error.what()));
303 }
304 return Result<std::vector<VolumeFluidParticle>>::success(std::move(decoded));
305}
306
309 value.set("schema", checkpoint.schema);
310 value.set("version", int64_t(checkpoint.version));
311 value.set("solver", encodeVolumeFluid(checkpoint.solver));
312 value.set("emission", encodeVolumeFluidEmission(checkpoint.emission));
313 value.set("controller", encodeVolumeFluidEmitterState(checkpoint.controller));
314 return value;
315}
316
318 const auto failure = [](const char* message) {
320 Diagnostic::error(DiagnosticCode::InvalidArgument, message, "fluids.volume.emitterCheckpoint"));
321 };
322 try {
323 const auto* schema = value.find("schema");
324 const auto* version = value.find("version");
325 const auto* solver = value.find("solver");
326 const auto* emission = value.find("emission");
327 const auto* controller = value.find("controller");
328 if (!value.isObject() || value.keys().size() != 5 || !schema || !schema->isString() ||
329 schema->asString() != "eve.volume-fluid-emitter-checkpoint" || !version || !version->isInt64() ||
330 version->asInt() != 1 || !solver || !emission || !controller)
331 return failure("Invalid emitter checkpoint schema, version or fields");
332 auto decodedSolver = decodeVolumeFluid(*solver);
333 if (!decodedSolver) return Result<VolumeFluidEmitterCheckpoint>::failure(decodedSolver.status());
334 auto decodedEmission = decodeVolumeFluidEmission(*emission);
335 if (!decodedEmission) return Result<VolumeFluidEmitterCheckpoint>::failure(decodedEmission.status());
336 auto decodedController = decodeVolumeFluidEmitterState(*controller);
337 if (!decodedController) return Result<VolumeFluidEmitterCheckpoint>::failure(decodedController.status());
339 {schema->asString(), 1u, std::move(decodedSolver).takeValue(), std::move(decodedEmission).takeValue(),
340 std::move(decodedController).takeValue()});
341 } catch (const std::runtime_error&) {
342 return failure("Invalid emitter checkpoint value types");
343 }
344}
345
347 Value out(Value::Object{});
348 out.set("schema", "eve.volume-fluid-emission");
349 out.set("version", 14);
350 out.set("description", pack(emission));
351 return out;
352}
353
355 VolumeFluidEmission decoded;
356 try {
357 const auto* schema = value.find("schema");
358 const auto* version = value.find("version");
359 const auto* description = value.find("description");
360 if (!value.isObject() || value.keys().size() != 3 || !schema || !schema->isString() ||
361 schema->asString() != "eve.volume-fluid-emission" || !version || !version->isInt64() ||
362 (version->asInt() < 1 || version->asInt() > 14) || !description)
363 throw std::runtime_error("fluids.volume.emission");
364 auto migrated = *description;
365 if (version->asInt() == 1) {
366 if (!migrated.isObject() || migrated.find("distribution"))
367 throw std::runtime_error("fluids.volume.emission/description");
368 migrated.set("distribution", Value(Value::Array{}));
369 }
370 if (version->asInt() <= 2) {
371 auto* prototype = migrated.find("prototype");
372 if (!prototype || !prototype->isObject() || prototype->find("collisionFilter"))
373 throw std::runtime_error("fluids.volume.emission/description/prototype");
374 prototype->set("collisionFilter", int64_t(0xffff0001u));
375 }
376 if (version->asInt() <= 3) {
377 auto* prototype = migrated.find("prototype");
378 if (!prototype || !prototype->isObject() || prototype->find("radii") || prototype->find("orientation"))
379 throw std::runtime_error("fluids.volume.emission/description/prototype");
380 prototype->set("radii", pack(glm::vec3(0.f)));
381 prototype->set("orientation", pack(glm::vec4(0, 0, 0, 1)));
382 }
383 if (version->asInt() <= 4) {
384 auto* prototype = migrated.find("prototype");
385 auto* material = prototype && prototype->isObject() ? prototype->find("material") : nullptr;
386 if (!prototype || !prototype->isObject() || prototype->find("actorGroup") ||
387 prototype->find("selfCollide") || !material || !material->isObject() ||
388 material->find("atmosphericPressure"))
389 throw std::runtime_error("fluids.volume.emission/description/prototype");
390 prototype->set("actorGroup", int64_t(0));
391 prototype->set("selfCollide", true);
392 material->set("atmosphericPressure", 0.0);
393 }
394 if (version->asInt() <= 5) {
395 if (!migrated.isObject() || migrated.find("granularRadiusRandomness"))
396 throw std::runtime_error("fluids.volume.emission/description");
397 migrated.set("granularRadiusRandomness", 0.0);
398 }
399 if (version->asInt() <= 6) {
400 auto* prototype = migrated.find("prototype");
401 auto* material = prototype && prototype->isObject() ? prototype->find("material") : nullptr;
402 if (!material || !material->isObject() || material->find("smoothing"))
403 throw std::runtime_error("fluids.volume.emission/description/prototype/material");
404 material->set("smoothing", 2.0);
405 }
406 if (version->asInt() <= 7) {
407 auto* prototype = migrated.find("prototype");
408 auto* material = prototype && prototype->isObject() ? prototype->find("material") : nullptr;
409 if (!prototype || !prototype->isObject() || prototype->find("angularVelocity") || !material ||
410 !material->isObject() || material->find("rollingContacts") || material->find("rollingFriction"))
411 throw std::runtime_error("fluids.volume.emission/description/prototype");
412 prototype->set("angularVelocity", pack(glm::vec3(0.f)));
413 material->set("rollingContacts", false);
414 material->set("rollingFriction", 0.0);
415 }
416 if (version->asInt() <= 8) {
417 auto* prototype = migrated.find("prototype");
418 auto* material = prototype && prototype->isObject() ? prototype->find("material") : nullptr;
419 if (!material || !material->isObject() || material->find("dynamicFriction") ||
420 material->find("staticFriction"))
421 throw std::runtime_error("fluids.volume.emission/description/prototype/material");
422 material->set("dynamicFriction", 0.2);
423 material->set("staticFriction", 0.2);
424 }
425 if (version->asInt() <= 9) {
426 const auto* source = migrated.find("distribution");
427 if (!source || !source->isArray() || source->arraySize() > 4096)
428 throw std::runtime_error("fluids.volume.emission/description/distribution");
430 points.reserve(source->arraySize());
431 for (size_t i = 0; i < source->arraySize(); ++i) {
432 auto point = source->at(i);
433 if (!point.isObject() || point.find("direction"))
434 throw std::runtime_error("fluids.volume.emission/description/distribution");
435 point.set("direction", pack(glm::vec3(0, 0, 1)));
436 points.push_back(std::move(point));
437 }
438 migrated.set("distribution", Value(std::move(points)));
439 }
440 if (version->asInt() <= 10) {
441 if (!migrated.isObject() || migrated.find("randomVelocity"))
442 throw std::runtime_error("fluids.volume.emission/description");
443 migrated.set("randomVelocity", 0.0);
444 }
445 if (version->asInt() <= 11) {
446 auto* prototype = migrated.find("prototype");
447 auto* material = prototype && prototype->isObject() ? prototype->find("material") : nullptr;
448 if (!material || !material->isObject() || material->find("stickiness") || material->find("stickDistance") ||
449 material->find("frictionCombine") || material->find("stickinessCombine"))
450 throw std::runtime_error("fluids.volume.emission/description/prototype/material");
451 material->set("stickiness", 0.0);
452 material->set("stickDistance", 0.0);
453 material->set("frictionCombine", 0);
454 material->set("stickinessCombine", 0);
455 }
456 if (version->asInt() <= 12) {
457 if (!migrated.isObject() || migrated.find("useShapeColor"))
458 throw std::runtime_error("fluids.volume.emission/description");
459 migrated.set("useShapeColor", true);
460 }
461 if (version->asInt() <= 13) {
462 if (!migrated.isObject() || migrated.find("actorCapacity"))
463 throw std::runtime_error("fluids.volume.emission/description");
464 migrated.set("actorCapacity", int64_t(1000));
465 }
466 unpack(migrated, decoded, "fluids.volume.emission/description");
467 if (decoded.actorCapacity < 1 || decoded.actorCapacity > 65536)
468 throw std::runtime_error("fluids.volume.emission/description/actorCapacity");
469 } catch (const std::runtime_error& error) {
471 DiagnosticCode::InvalidArgument, "Invalid emission schema, version or fields", error.what()));
472 }
473 return Result<VolumeFluidEmission>::success(std::move(decoded));
474}
475
476} // namespace eve::fluids
double value
eve::EntitySpatialPose pose
std::string message
std::string description
std::string error
Definition Package.cpp:60
std::shared_ptr< const std::vector< glm::vec2 > > points
Material * material
Battle::Events events
TerrainThermalSettings settings
const UnitySourceAsset & source
glm::vec3 point
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
The canonical owning dynamic value used by data-facing protocols.
Definition Value.h:31
std::map< std::string, Value > Object
Definition Value.h:34
void set(const std::string &key, Value value)
Insert or replace an object member.
Definition Value.cpp:118
std::vector< Value > Array
Definition Value.h:33
Bounded, one-way fluid-advected secondary particle pool. @ownership Owns particles and capacity; no f...
Result< void > restore(const VolumeFluidDiffuseSnapshot &snapshot)
Validates schema, capacity [1,65536] and all particles before replacing state.
Bounded runtime stream controller with explicit snapshot/restore.
Generates secondary particles at high-curl, low-density fluid source positions. @ownership Owns setti...
Result< void > restore(const VolumeFluidFoamSnapshot &state)
Validates all settings/schema/credit/RNG before atomic replacement.
Spacing-driven planar/distribution jet controller with independent, owned stream phase.
Result< void > restore(const VolumeFluidEmitterSnapshot &state)
Validates schema, kind and phase before atomic replacement; invokes no callbacks.
GLSL compute kernels for the GPU surface-flow solver.
Definition FluidTarget.h:12
Value encodeVolumeFluid(const VolumeFluidSnapshot &snapshot)
Canonical schema-17 value projection, shared by JSON, scripts and authoring.
Result< std::vector< VolumeFluidViscosityColorKey > > decodeVolumeFluidViscosityColors(const Value &value)
Strict owning decode of at most 32 transient viscosity color keys; application validates domains.
Result< VolumeGranularEmitterBlueprint3D > decodeVolumeGranularEmitterBlueprint3D(const Value &value)
Strictly decodes one owning Fluid3D granular-emitter blueprint value.
Result< FluidRendererSettings > decodeFluidRendererSettings(const Value &value)
Strictly decodes one complete owning Fluid3D-renderer settings value.
Value encodeVolumeFluidEmitterBlueprint3D(const VolumeFluidEmitterBlueprint3D &blueprint)
Projects default or caller-prepared Fluid3D-emitter blueprint values.
Result< std::vector< VolumeFluidQueryShape > > decodeVolumeFluidQueries(const Value &value)
Strict owning decode of at most 256 transient mixed query descriptions.
Value encodeVolumeFluidContacts(const std::vector< VolumeFluidContact > &contacts)
Projects last-step contacts, including world-space point and opposite impulse.
Result< VolumeFluidMaterial > decodeVolumeFluidMaterial(const Value &value)
Strict transient material decode; paint validates numeric domains before mutation.
Value encodeVolumeFluidFieldSamples(const std::vector< VolumeFluidFieldSample > &samples)
Projects owning field samples, preserving query order.
Result< std::vector< VolumeFluidSdfPose > > decodeVolumeFluidSdfPoses(const Value &value)
Strict transient decode of at most 16 SDF transform-only updates.
Value encodeVolumeFluidWindZone(const VolumeFluidWindZone &zone)
Projects one complete wind-zone description for script construction.
Value encodeVolumeFluidSimplexHits(const std::vector< VolumeFluidSimplexHit > &hits)
Projects owning Fluid3D-compatible simplex query results.
Result< VolumeFluidNozzlePose > decodeVolumeFluidNozzlePose(const Value &value)
Strict transient pose-argument decode; advanceMoving validates the unit quaternion.
Result< std::vector< VolumeFluidSimplex > > decodeVolumeFluidSimplexes(const Value &value)
Strict owning decode of at most 65536 point, edge or triangle topology entries.
Result< std::vector< VolumeFluidWindZone > > decodeVolumeFluidWindZones(const Value &value)
Strict owning decode of at most 64 transient Fluid3D-style wind zones.
Value encodeVolumeFluidCollider(const VolumeFluidCollider &collider)
Projects an owning collider description for script construction.
Value encodeVolumeFluidContactEvents(const std::vector< VolumeFluidContactEvent > &events)
Projects owning Enter/Stay/Exit contact lifecycle events.
Value encodeVolumeFluidHeightFieldCollider(const VolumeFluidHeightFieldCollider &collider)
Projects one complete owning regular height field.
Value encodeVolumeFluidSdfCollider(const VolumeFluidSdfCollider &collider)
Projects one complete owning SDF collider.
Result< std::vector< glm::vec4 > > decodeVolumeFluidColors(const Value &value)
Strict owning decode of at most 256 transient linear RGBA colors.
Result< std::vector< VolumeFluidStitch > > decodeVolumeFluidStitches(const Value &value)
Strict owning decode of at most 65536 Fluid3DStitcher particle pairs.
Result< VolumeFluidEmitterSnapshot > decodeVolumeFluidEmitterState(const Value &value)
Strict version-1 controller-state decode; unsupported fields, kinds and phase values fail.
Value encodeVolumeFluidParticles(const std::vector< VolumeFluidParticle > &particles)
Projects an owning particle batch without copying the live solver.
Value encodeVolumeFluidDiffuse(const VolumeFluidDiffuseSnapshot &snapshot)
Projects the owning version-1 secondary particle pool state.
Result< std::vector< VolumeFluidHeightFieldCollider > > decodeVolumeFluidHeightFieldColliders(const Value &value)
Strict owning decode of at most 16 regular sampled height fields.
Value encodeVolumeFluidSdfPose(const VolumeFluidSdfPose &pose)
Projects one transform-only SDF update for script construction.
Result< std::vector< VolumeFluidDiffuseParticle > > decodeVolumeFluidDiffuseParticles(const Value &value)
Strict transient batch decode of at most 65536 particles; emit validates domains.
Value encodeFluidRendererSettings(const FluidRendererSettings &settings)
Projects one complete Fluid3D-renderer settings value.
Value encodeVolumeFluidQueryHits(const std::vector< VolumeFluidQueryHit > &hits)
Projects owning mixed-query hits with their source query indices.
Result< std::vector< glm::vec3 > > decodeVolumeFluidFieldPositions(const Value &value)
Strict owning decode of up to 65536 transient world-space field query positions.
Result< VolumeFluidFoamSnapshot > decodeVolumeFluidFoam(const Value &value)
Strict decode with atomic-controller validation; rejects unknown fields and versions.
EVENGINE_API_DOMAINS Result< VolumeFluidSnapshot > decodeVolumeFluid(const Value &value)
Strict owning decode; unknown/missing fields, unsupported versions and invalid state are rejected.
Value encodeVolumeFluidThermalRule(const VolumeFluidThermalRule &rule)
Owning default-rule projection for script construction.
Result< std::vector< VolumeFluidColorKey > > decodeVolumeFluidColorGradient(const Value &value)
Strict owning decode of a 2..32-key normalized linear RGBA gradient.
Result< VolumeFluidDiffuseSnapshot > decodeVolumeFluidDiffuse(const Value &value)
Strict bounded decode; validates the entire pool before returning owning state.
Result< VolumeFluidEmission > decodeVolumeFluidEmission(const Value &value)
Strict structural decode; nozzle/material domain validation occurs atomically at emission.
Result< std::vector< VolumeFluidSdfCollider > > decodeVolumeFluidSdfColliders(const Value &value)
Strict owning decode of at most 16 sampled SDF colliders.
Value encodeVolumeFluidEmitterBlueprintApplication3D(const VolumeFluidEmitterBlueprintApplication3D &application)
Projects the complete native solver/emission setup produced from a blueprint.
Result< std::vector< VolumeFluidThermalRule > > decodeVolumeFluidThermalRules(const Value &value)
Strict owning decode of at most 1024 transient thermal rules; step validates domains.
Result< std::vector< VolumeFluidParticle > > decodeVolumeFluidParticles(const Value &value)
Decodes an owning emission batch without serializing the live solver; admission validates domains.
Value encodeVolumeFluidParticleEvents(const VolumeFluidParticleEventBatch &batch)
Projects one owning bounded particle lifecycle-event drain.
Value encodeVolumeFluidEmission(const VolumeFluidEmission &emission)
Encodes a version-9 emission description including precomputed points and particle state.
Value encodeVolumeFluidFoam(const VolumeFluidFoamSnapshot &snapshot)
Projects owning schema-1 foam settings, credit text and RNG state.
Value encodeVolumeFluidDistanceHits(const std::vector< VolumeFluidDistanceHit > &hits)
Projects owning signed-distance hits including captured particle values.
Value encodeVolumeFluidEmitterState(const VolumeFluidEmitterSnapshot &state)
Encodes controller state without converting phase text to VM floating point.
Result< std::vector< VolumeFluidCollider > > decodeVolumeFluidColliders(const Value &value)
Strict transient collider batch decode; setColliders validates geometry atomically.
Value encodeVolumeFluidRayHits(const std::vector< VolumeFluidRayHit > &hits)
Projects owning ray hits including captured particle values.
Value encodeVolumeFluidEmitterCheckpoint(const VolumeFluidEmitterCheckpoint &checkpoint)
Encodes one version-1 solver/emission/controller checkpoint.
Result< VolumeFluidEmitterCheckpoint > decodeVolumeFluidEmitterCheckpoint(const Value &value)
Strictly decodes and validates all owning checkpoint members without publishing state.
Value encodeVolumeGranularEmitterBlueprint3D(const VolumeGranularEmitterBlueprint3D &blueprint)
Projects default or caller-prepared Fluid3D granular-emitter blueprint values.
Result< VolumeFluidEmitterBlueprint3D > decodeVolumeFluidEmitterBlueprint3D(const Value &value)
Strictly decodes one owning Fluid3D-emitter blueprint value.
Complete owning mirror of Fluid3DRendererSettings with package defaults.
Owned obstacle sample; the caller updates moving obstacles before stepping.
Strict version-1 diffuse pool state; unknown fields and versions are rejected.
Value-owned emission description; +Z is mapped to direction.
unsigned actorCapacity
Maximum live particles owned by this emitter actor, matching Fluid3DEmitterBlueprintBase capacity.
Owning Fluid3DEmitterBlueprint values used to prepare a native 3D emitter.
Fully owned native setup prepared from one Fluid3D-emitter blueprint.
float particleMass
Per-particle rest mass in kilograms.
float smoothingRadius
Fluid support radius in metres.
float particleSize
Recommended solver rest spacing and particle diameter in metres.
Version-1 owning atomic checkpoint for a solver, emission description and controller.
Version-1 owning state for rate (kind 0) or jet (kind 1) controllers.
Owning strict version-1 foam controller state; checkpoint the diffuse pool separately.
Owned regular-grid terrain collider matching Fluid3D height-field sample layout.
Per-particle material, copied at emission; densities enable multiphase buoyancy.
Definition VolumeFluid.h:26
Owning world-space nozzle pose; rotation is a unit quaternion in XYZW order.
Owning result of one explicit particle lifecycle-event drain.
Owned sampled mesh/SDF collider with a uniform world transform.
Transient transform update for one owned SDF collider, identified by stable label.
Canonical version-20 owning state; older codecs migrate collider, attachment, stitch,...
One-step contact transfer into user channels x/y; negative rate heats, positive cools.
Owning description of one transient ambient or spherical wind zone.
Owning Fluid3DGranularEmitterBlueprint values used to prepare a native 3D emitter.