载入中...
搜索中...
未找到
VolumeFluidEmitter.cpp
浏览该文件的文档.
13bool finiteVector(glm::vec3 v) { return std::isfinite(v.x) && std::isfinite(v.y) && std::isfinite(v.z); }
18 if (!finiteVector(p.position) || !finiteVector(p.direction) || !std::isfinite(directionLength) ||
25 return finiteVector(e.origin) && finiteVector(e.direction) && std::isfinite(length) && length > 1e-6f &&
27 e.extent.x <= 10000.f && e.extent.y <= 10000.f && e.extent.z <= 10000.f && std::isfinite(e.speed) &&
28 e.speed >= 0.f && std::isfinite(e.jitter) && e.jitter >= 0.f && std::isfinite(e.randomVelocity) &&
29 e.randomVelocity >= 0.f && e.randomVelocity <= 1.f && std::isfinite(e.granularRadiusRandomness) &&
30 e.granularRadiusRandomness >= 0.f && e.granularRadiusRandomness <= 100.f && e.actorCapacity >= 1 &&
40 Diagnostic::error(DiagnosticCode::InvalidArgument, "Unsupported emitter checkpoint schema/version", "fluids.volume.emitterCheckpoint"));
42 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid checkpoint emission description", "fluids.volume.emitterCheckpoint"));
59void randomizeGranularRadius(VolumeFluidParticle& particle, float spacing, float randomness, uint32_t& rng);
61Result<unsigned> emitBurst(VolumeFluid& solver, const VolumeFluidEmission& e, unsigned count, uint32_t sequence,
92 local = {(2.f * a - 1.f) * e.extent.x, (2.f * b - 1.f) * e.extent.y, (2.f * c - 1.f) * e.extent.z};
109 particle.orientation = {worldOrientation.x, worldOrientation.y, worldOrientation.z, worldOrientation.w};
112 const float jx = 2.f * sample(rng) - 1.f, jy = 2.f * sample(rng) - 1.f, jz = 2.f * sample(rng) - 1.f;
120 const auto spawnDirection = emissionDirection * (1.f - e.randomVelocity) + randomDirection * e.randomVelocity;
138void randomizeGranularRadius(VolumeFluidParticle& particle, float spacing, float randomness, uint32_t& rng) {
140 const float radius = std::max(.001f, spacing * .5f + .001f - sample(rng) * spacing * (randomness * .01f));
145Result<VolumeFluidEmitterBlueprintMetrics> evaluateVolumeFluidEmitterBlueprint3D(float resolution, float restDensity,
147 if (!std::isfinite(resolution) || resolution < .001f || resolution > 1000000.f || !std::isfinite(restDensity) ||
148 restDensity < .001f || restDensity > 1000000.f || !std::isfinite(smoothing) || smoothing < 1.f ||
151 DiagnosticCode::InvalidArgument, "Invalid 3D emitter blueprint metrics", "fluids.volume.emitterBlueprint"));
154 metrics.particleMass = restDensity * metrics.particleSize * metrics.particleSize * metrics.particleSize;
162 evaluateVolumeFluidEmitterBlueprint3D(blueprint.resolution, blueprint.restDensity, blueprint.smoothing);
167 !finiteRange(blueprint.viscosity, 0.f, 100.f) || !finiteRange(blueprint.surfaceTension, 0.f, 10.f) ||
168 !finiteRange(blueprint.buoyancy, -10.f, 10.f) || !finiteRange(blueprint.atmosphericDrag, 0.f, 100.f) ||
169 !finiteRange(blueprint.atmosphericPressure, 0.f, 1000.f) || !finiteRange(blueprint.vorticity, 0.f, 10.f) ||
170 !finiteRange(blueprint.diffusion, 0.f, 100.f) || !finiteVector(glm::vec3(blueprint.diffusionData)) ||
173 DiagnosticCode::InvalidArgument, "Invalid 3D fluid emitter blueprint", "fluids.volume.emitterBlueprint"));
197 const auto metrics = evaluateVolumeFluidEmitterBlueprint3D(blueprint.resolution, blueprint.restDensity, 1.f);
198 if (!metrics || blueprint.capacity == 0 || blueprint.capacity > 65536 || !std::isfinite(blueprint.randomness) ||
216Result<unsigned> emitVolumeFluidBurst(VolumeFluid& solver, const VolumeFluidEmission& e, unsigned count) {
220 const size_t actorFree = e.actorCapacity > active.value() ? e.actorCapacity - active.value() : 0;
224Result<unsigned> VolumeFluidEmitter::emitParticle(VolumeFluid& solver, const VolumeFluidEmission& emission,
226 if (!valid(emission) || !std::isfinite(offset) || offset < 0.f || offset > 1.f || !std::isfinite(dt) || dt < 0.f ||
231 const size_t actorFree = emission.actorCapacity > active.value() ? emission.actorCapacity - active.value() : 0;
246Result<unsigned> VolumeFluidEmitter::advance(VolumeFluid& solver, const VolumeFluidEmission& emission, float dt,
248 if (!valid(emission) || !std::isfinite(dt) || dt < 0.f || dt > 1.f / 30.f || !std::isfinite(rate) || rate < 0.f ||
249 rate > 1000000.f || maxPerStep == 0 || maxPerStep > 4096 || !std::isfinite(minimumPoolFraction) ||
261 const size_t actorFree = emission.actorCapacity > active.value() ? emission.actorCapacity - active.value() : 0;
262 if ((emission.shape == VolumeFluidEmissionShape::Distribution && emission.distribution.empty()) || free == 0 ||
264 (!emitting_ && double(actorFree) <= std::floor(double(emission.actorCapacity) * minimumPoolFraction))) {
271 const unsigned count = unsigned(std::min({whole, double(maxPerStep), double(free), double(actorFree)}));
282Result<unsigned> VolumeFluidEmitter::advanceBurst(VolumeFluid& solver, const VolumeFluidEmission& emission,
295 double(emission.actorCapacity) <= std::floor(double(emission.actorCapacity) * minimumPoolFraction)) {
299 auto result = emitBurst(solver, emission, count, sequence_, 0, emission.actorCapacity, 0.f, 0.f);
308Result<unsigned> VolumeFluidJetEmitter::advance(VolumeFluid& solver, const VolumeFluidEmission& e, float dt,
319Result<unsigned> VolumeFluidJetEmitter::advanceMoving(VolumeFluid& solver, const VolumeFluidEmission& e,
327 if (!validPose(begin) || !validPose(end) || !std::isfinite(inheritVelocity) || inheritVelocity < 0.f ||
330 if (!valid(e) || e.shape == VolumeFluidEmissionShape::Sphere || e.shape == VolumeFluidEmissionShape::Cube ||
340 const size_t actorFree = e.actorCapacity > active.value() ? e.actorCapacity - active.value() : 0;
342 (!emitting_ && double(actorFree) <= std::floor(double(e.actorCapacity) * minimumPoolFraction))) {
361 : std::floor(double(e.shape == VolumeFluidEmissionShape::Disk ? e.extent.x : e.extent.y) / spacing);
369 if (e.shape == VolumeFluidEmissionShape::Disk && glm::dot(point, point) > e.extent.x * e.extent.x)
375 if (points.size() > maxPerStep) return invalidEmission("Jet work cap cannot fit a complete nozzle layer");
387 const auto rotation = [](glm::vec4 q) { return glm::normalize(glm::quat(q.w, q.x, q.y, q.z)); };
411 p.orientation = {worldOrientation.x, worldOrientation.y, worldOrientation.z, worldOrientation.w};
435 return DistributionResult::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, message, source));
437bool appendDistributionPoint(std::vector<VolumeFluidDistributionPoint>& output, const glm::vec3& position,
444Result<std::vector<VolumeFluidDistributionPoint>> buildVolumeFluidSphereDistribution(float radius, float spacing,
456 if (side * side * side > 65536) return distributionFailure("Sphere lattice exceeds 65536 candidates", source);
472 const double increment = 2.0 * std::asin(std::clamp(double(spacing) / (2.0 * radius), 0.0, 1.0));
486 if (candidates > 65536) return distributionFailure("Sphere lattice exceeds 65536 candidates", source);
497Result<std::vector<VolumeFluidDistributionPoint>> buildVolumeFluidCubeDistribution(glm::vec3 size, float spacing,
500 if (!finiteVector(size) || glm::any(glm::lessThanEqual(size, glm::vec3(0.f))) || !std::isfinite(spacing) ||
508 const uint64_t candidates = uint64_t(count.x + 1) * uint64_t(count.y + 1) * uint64_t(count.z + 1);
509 if (candidates > 65536) return distributionFailure("Cube lattice exceeds 65536 candidates", source);
515 if (surface && x != 0 && x != count.x && y != 0 && y != count.y && z != 0 && z != count.z) continue;
516 const glm::vec3 point(float(x) / count.x - .5f, float(y) / count.y - .5f, float(z) / count.z - .5f);
529Result<std::vector<VolumeFluidDistributionPoint>> buildVolumeFluidEdgeDistribution(float length, float spacing,
532 if (!std::isfinite(length) || length < 0.f || length > 10000.f || !std::isfinite(spacing) || spacing <= 0.f ||
537 if (amountValue > 4095.0) return distributionFailure("Edge distribution exceeds 4096 points", source);
544 output.push_back({{float(double(i) * separation - double(length) * .5), 0, 0}, glm::vec4(1), direction});
549Result<std::vector<VolumeFluidDistributionPoint>> buildVolumeFluidDiskDistribution(float radius, float spacing,
552 if (!std::isfinite(radius) || radius <= 0.f || radius > 10000.f || !std::isfinite(spacing) || spacing <= 0.f)
567 if (candidates > 65536) return distributionFailure("Disk lattice exceeds 65536 candidates", source);
608 glm::normalize(right * point.direction.x + up * point.direction.y + forward * point.direction.z);
617 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid emitter-wide description", source));
627 Diagnostic::error(DiagnosticCode::InvalidArgument, "Invalid emitter-wide description", source));
633Result<std::vector<VolumeFluidDistributionPoint>> buildVolumeFluidImageDistribution(std::span<const glm::vec4> pixels,
643 if (width == 0 || height == 0 || uint64_t(width) * height != pixels.size() || pixels.size() > 16777216 ||
644 !std::isfinite(pixelScale) || pixelScale <= 0.f || !std::isfinite(maximumSize) || maximumSize <= 0.f ||
645 !std::isfinite(spacing) || spacing <= 0.f || !std::isfinite(alphaThreshold) || alphaThreshold < 0.f ||
656 const double countX = std::floor(worldWidth / spacing), countY = std::floor(worldHeight / spacing);
669 const auto lower = pixels[size_t(y0) * width + x0] * (1.f - fx) + pixels[size_t(y0) * width + x1] * fx;
670 const auto upper = pixels[size_t(y1) * width + x0] * (1.f - fx) + pixels[size_t(y1) * width + x1] * fx;
693Result<void> restoreVolumeFluidEmitterCheckpoint(VolumeFluid& solver, VolumeFluidEmitter& controller,
698Result<void> restoreVolumeFluidEmitterCheckpoint(VolumeFluid& solver, VolumeFluidJetEmitter& controller,
723 if (s.schema != "eve.volume-fluid-emitter-state" || s.version != 1 || s.kind != kind || stream.fail() ||
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
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Bounded runtime stream controller with explicit snapshot/restore.
Definition VolumeFluidEmitter.h:207
VolumeFluidEmitterSnapshot snapshot() const
Copies controller state; caller checkpoints solver/configuration at the same step boundary.
Definition VolumeFluidEmitter.cpp:731
Result< unsigned > emitParticle(VolumeFluid &solver, const VolumeFluidEmission &emission, float offset, float dt)
Emits one particle with Fluid3DEmitter's normalized intra-step position offset.
Definition VolumeFluidEmitter.cpp:224
Result< unsigned > advanceBurst(VolumeFluid &solver, const VolumeFluidEmission &emission, unsigned count, float minimumPoolFraction=0.5f)
Advances Fluid3D's BURST emission lifecycle for one actor group.
Definition VolumeFluidEmitter.cpp:282
Result< unsigned > advance(VolumeFluid &solver, const VolumeFluidEmission &emission, float dt, float rate, unsigned maxPerStep=256, float minimumPoolFraction=0.5f)
Advances emission with at most maxPerStep particles; excess whole-particle credit is discarded.
Definition VolumeFluidEmitter.cpp:246
Result< void > restore(const VolumeFluidEmitterSnapshot &state)
Validates schema, kind and phase before atomic replacement; invokes no callbacks.
Definition VolumeFluidEmitter.cpp:734
Spacing-driven planar/distribution jet controller with independent, owned stream phase.
Definition VolumeFluidEmitter.h:255
Result< unsigned > advanceMoving(VolumeFluid &solver, const VolumeFluidEmission &emission, const VolumeFluidNozzlePose &begin, const VolumeFluidNozzlePose &end, float dt, unsigned maxPerStep=256, float minimumPoolFraction=0.5f, float inheritVelocity=0.f)
Emits using interpolated step-boundary rigid poses instead of description origin/direction.
Definition VolumeFluidEmitter.cpp:319
Result< unsigned > advance(VolumeFluid &solver, const VolumeFluidEmission &emission, float dt, unsigned maxPerStep=256, float minimumPoolFraction=0.5f)
Emits whole nozzle layers spaced by solver.spacing().
Definition VolumeFluidEmitter.cpp:308
Result< void > restore(const VolumeFluidEmitterSnapshot &state)
Validates schema, kind and phase before atomic replacement; invokes no callbacks.
Definition VolumeFluidEmitter.cpp:745
VolumeFluidEmitterSnapshot snapshot() const
Copies controller state; caller checkpoints solver/configuration at the same step boundary.
Definition VolumeFluidEmitter.cpp:742
CPU position-based free-volume fluid with a bounded spatial grid. @ownership Owns all particle state;...
Definition VolumeFluid.h:517
float spacing() const
Returns the rest lattice spacing without copying state.
Definition VolumeFluid.cpp:642
static Result< std::unique_ptr< VolumeFluid > > create(const VolumeFluidSettings &settings)
Validates settings before allocating an owning solver; errors publish no state.
Definition VolumeFluid.cpp:7
size_t availableCapacity() const
Returns unused pool capacity in constant time without allocating.
Definition VolumeFluid.cpp:641
VolumeFluidSnapshot snapshot() const
Returns complete owning state; scratch grids and last-step contacts are derived and omitted.
Definition VolumeFluidTools.cpp:629
Result< unsigned > actorParticleCount(unsigned actorGroup) const
Counts current live particles for one Fluid3D-compatible actor group.
Definition VolumeFluid.cpp:853
Result< void > emit(std::span< const VolumeFluidParticle > particles)
Atomically admits particles; rejects nonfinite, out-of-container or over-capacity input.
Definition VolumeFluid.cpp:24
std::vector< double > forward(const Policy &p, const Observation &o)
Forward.
Definition Learning.h:65
Result< std::vector< VolumeFluidDistributionPoint > > buildVolumeFluidEdgeDistribution(float length, float spacing, float radialVelocityDegrees)
Builds Fluid3D's edge lattice with per-sample radial velocity directions.
Definition VolumeFluidEmitter.cpp:529
Result< std::vector< VolumeFluidDistributionPoint > > buildVolumeFluidCubeDistribution(glm::vec3 size, float spacing, bool surface)
Builds an Fluid3D-compatible box surface or volume lattice during setup.
Definition VolumeFluidEmitter.cpp:497
@ Granular
VolumeFluidEmitterCheckpoint captureVolumeFluidEmitterCheckpoint(const VolumeFluid &solver, const VolumeFluidEmission &emission, const VolumeFluidEmitter &controller)
Captures one completed-step rate-emitter checkpoint without retaining references.
Definition VolumeFluidEmitter.cpp:681
Result< void > restoreVolumeFluidEmitterCheckpoint(VolumeFluid &solver, VolumeFluidEmitter &controller, const VolumeFluidEmitterCheckpoint &checkpoint)
Atomically restores solver and rate controller after validating the complete owning candidate.
Definition VolumeFluidEmitter.cpp:693
Result< std::vector< VolumeFluidDistributionPoint > > buildVolumeFluidDiskDistribution(float radius, float spacing, bool edgeEmission)
Builds Fluid3D's concentric disk or circumference-only distribution.
Definition VolumeFluidEmitter.cpp:549
Result< VolumeFluidEmission > composeVolumeFluidEmitterShapes(const VolumeFluidEmission &base, std::span< const VolumeFluidEmission > shapes)
Builds one emitter distribution from an ordered set of Fluid3D emitter shapes.
Definition VolumeFluidEmitter.cpp:579
@ Distribution
Result< std::vector< VolumeFluidDistributionPoint > > buildVolumeFluidSphereDistribution(float radius, float spacing, bool surface)
Builds an Fluid3D-compatible spherical surface or volume lattice during setup.
Definition VolumeFluidEmitter.cpp:444
Result< std::vector< VolumeFluidDistributionPoint > > buildVolumeFluidImageDistribution(std::span< const glm::vec4 > pixels, unsigned width, unsigned height, float pixelScale, float maximumSize, float spacing, float alphaThreshold)
Precomputes a bilinear alpha-masked image distribution on a spacing lattice.
Definition VolumeFluidEmitter.cpp:633
Result< VolumeFluidEmitterBlueprintMetrics > evaluateVolumeFluidEmitterBlueprint3D(float resolution, float restDensity, float smoothing)
Evaluates Fluid3DEmitterBlueprintBase/Fluid3DEmitterBlueprint formulas in 3D.
Definition VolumeFluidEmitter.cpp:145
Result< VolumeFluidEmitterBlueprintApplication3D > prepareVolumeFluidEmitterBlueprint3D(const VolumeFluidEmitterBlueprint3D &blueprint)
Atomically maps every Fluid3DEmitterBlueprint field to native 3D setup values.
Definition VolumeFluidEmitter.cpp:159
Result< VolumeFluidEmitterBlueprintApplication3D > prepareVolumeGranularEmitterBlueprint3D(const VolumeGranularEmitterBlueprint3D &blueprint)
Atomically maps an Fluid3DGranularEmitterBlueprint to owned native 3D setup values.
Definition VolumeFluidEmitter.cpp:195
Result< unsigned > emitVolumeFluidBurst(VolumeFluid &solver, const VolumeFluidEmission &e, unsigned count)
Generates at most 4096 particles and admits the entire burst atomically.
Definition VolumeFluidEmitter.cpp:216
@ InvalidArgument
Value-owned emission description; +Z is mapped to direction.
Definition VolumeFluidEmitter.h:105
VolumeFluidParticle prototype
Material/color/data/lifetime copied to emitted particles; position/velocity are generated.
Definition VolumeFluidEmitter.h:122
float speed
Nozzle speed and independent per-axis uniform native velocity jitter, m/s.
Definition VolumeFluidEmitter.h:112
std::vector< VolumeFluidDistributionPoint > distribution
Precomputed shape points, used only by Distribution; maximum 4096, copied by value.
Definition VolumeFluidEmitter.h:126
bool useShapeColor
Whether Distribution points replace prototype color, matching Fluid3DEmitter useShapeColor.
Definition VolumeFluidEmitter.h:116
unsigned actorCapacity
Maximum live particles owned by this emitter actor, matching Fluid3DEmitterBlueprintBase capacity.
Definition VolumeFluidEmitter.h:118
uint32_t seed
Explicit named emission RNG stream seed; never touches a global RNG.
Definition VolumeFluidEmitter.h:124
float granularRadiusRandomness
Granular radius reduction percentage in [0,100]; zero preserves the prototype radius.
Definition VolumeFluidEmitter.h:120
VolumeFluidEmissionShape shape
Definition VolumeFluidEmitter.h:106
Owning Fluid3DEmitterBlueprint values used to prepare a native 3D emitter.
Definition VolumeFluidEmitter.h:25
float diffusion
Definition VolumeFluidEmitter.h:30
float viscosity
Definition VolumeFluidEmitter.h:28
float buoyancy
Definition VolumeFluidEmitter.h:29
float vorticity
Definition VolumeFluidEmitter.h:29
glm::vec4 diffusionData
Definition VolumeFluidEmitter.h:31
float restDensity
Definition VolumeFluidEmitter.h:27
float resolution
Definition VolumeFluidEmitter.h:27
float atmosphericPressure
Definition VolumeFluidEmitter.h:29
float smoothing
Definition VolumeFluidEmitter.h:27
float surfaceTension
Definition VolumeFluidEmitter.h:28
unsigned capacity
Definition VolumeFluidEmitter.h:26
float atmosphericDrag
Definition VolumeFluidEmitter.h:29
Fully owned native setup prepared from one Fluid3D-emitter blueprint.
Definition VolumeFluidEmitter.h:147
VolumeFluidEmitterBlueprintMetrics metrics
Definition VolumeFluidEmitter.h:150
VolumeFluidEmission emission
Definition VolumeFluidEmitter.h:149
VolumeFluidSettings settings
Definition VolumeFluidEmitter.h:148
Exact 3D metrics derived by Fluid3DEmitterBlueprintBase from resolution and density.
Definition VolumeFluidEmitter.h:15
float particleSize
Recommended solver rest spacing and particle diameter in metres.
Definition VolumeFluidEmitter.h:17
Version-1 owning atomic checkpoint for a solver, emission description and controller.
Definition VolumeFluidEmitter.h:188
Version-1 owning state for rate (kind 0) or jet (kind 1) controllers.
Definition VolumeFluidEmitter.h:177
Owning world-space nozzle pose; rotation is a unit quaternion in XYZW order.
Definition VolumeFluidEmitter.h:197
unsigned actorGroup
Fluid3D-compatible actor group in [0, 0x00ffffff]; equal groups use selfCollide instead of filters.
Definition VolumeFluid.h:114
unsigned capacity
Maximum live particles; admission fails atomically at capacity.
Definition VolumeFluid.h:84
Owning Fluid3DGranularEmitterBlueprint values used to prepare a native 3D emitter.
Definition VolumeFluidEmitter.h:35
float randomness
Fluid3D radius-reduction percentage; runtime accepts the meaningful [0,100] range.
Definition VolumeFluidEmitter.h:39
float resolution
Definition VolumeFluidEmitter.h:37
float restDensity
Definition VolumeFluidEmitter.h:37
unsigned capacity
Definition VolumeFluidEmitter.h:36