载入中...
搜索中...
未找到
SurfaceFluidContracts.cpp
浏览该文件的文档.
2
3#include "common/Exception.h"
5
6#include <algorithm>
7#include <cmath>
8#include <utility>
9
10namespace eve::fluids {
11namespace {
12
14
15eve::Result<void> validateTick(const eve::SimulationStep& step, eve::SimulationTick lastTick, const char* path) {
16 const double seconds = step.delta.seconds();
17 if (!std::isfinite(seconds) || seconds < 0.0)
18 return eve::Result<void>::failure(eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "Surface-fluid duration must be finite and non-negative", path));
19 if (!(step.tick > lastTick))
21 eve::DiagnosticCode::PreconditionViolation, "Surface-fluid simulation tick must increase strictly", path));
22 return applied();
23}
24
25eve::Result<void> validateDuration(eve::Duration duration, const char* path) {
26 const double seconds = duration.seconds();
27 if (!std::isfinite(seconds) || seconds < 0.0)
28 return eve::Result<void>::failure(eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "Surface pose duration must be finite and non-negative", path));
29 return applied();
30}
31
32} // namespace
33
36 eve::DiagnosticCode::PreconditionViolation, "Surface-fluid adapter has no live borrowed solver", "fluids.surfaceSimulation.solver"));
37 auto valid = validateTick(stepValue, lastTick_, "fluids.surfaceSimulation.step");
38 if (!valid) return valid;
39 solver_->step(static_cast<float>(stepValue.delta.seconds()));
40 lastTick_ = stepValue.tick;
41 return applied();
42}
43
44int FluidSimulationAdapter::particleCount() const noexcept { return solver_ ? solver_->particleCount() : 0; }
45
46std::span<const FluidParticle> FluidSimulationAdapter::particles() const noexcept {
47 if (!solver_) return {};
48 const auto& values = solver_->particles();
49 const auto count = static_cast<std::size_t>(std::max(0, solver_->particleCount()));
50 return {values.data(), std::min(count, values.size())};
51}
52
54 const std::vector<std::uint32_t>& indices,
55 const std::vector<glm::vec2>& uvs) {
57 eve::DiagnosticCode::PreconditionViolation, "Surface-fluid adapter has no live borrowed solver", "fluids.surfaceConstraint.binding"));
58 if (!binding_->build(positions, indices, uvs))
59 return eve::Result<void>::failure(eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "Surface constraint topology is not a valid triangle mesh", "fluids.surfaceConstraint.topology"));
60 return applied();
61}
62
65 eve::DiagnosticCode::PreconditionViolation, "Surface-fluid adapter has no live borrowed solver", "fluids.surfaceConstraint.binding"));
66 binding_->setTransform(transform);
67 return applied();
68}
69
70eve::Result<void> FluidSurfaceConstraintAdapter::setDeformedPositions(const std::vector<glm::vec3>& worldPositions) {
72 eve::DiagnosticCode::PreconditionViolation, "Surface-fluid adapter has no live borrowed solver", "fluids.surfaceConstraint.binding"));
73 if (!binding_->setDeformedPositions(worldPositions))
74 return eve::Result<void>::failure(eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "Deformed surface vertex count does not match topology", "fluids.surfaceConstraint.pose"));
75 return applied();
76}
77
78bool FluidSurfaceConstraintAdapter::isValid() const noexcept { return binding_ && binding_->isValid(); }
79
81 eve::Duration poseDelta) const {
82 auto validDuration = validateDuration(poseDelta, "fluids.surfaceConstraint.evaluate.dt");
83 if (!validDuration) return eve::Result<SurfaceSample>::failure(validDuration.status());
84 if (!binding_ || !binding_->isValid())
86 eve::DiagnosticCode::PreconditionViolation, "Cannot evaluate an invalid surface constraint",
87 "fluids.surfaceConstraint.evaluate"));
88 if (location.triangle >= static_cast<std::uint32_t>(binding_->triangleCount()))
90 eve::DiagnosticCode::NotFound, "Surface location triangle is outside the bound topology",
91 "fluids.surfaceConstraint.evaluate.triangle"));
92 return eve::Result<SurfaceSample>::success(binding_->evaluate(location, static_cast<float>(poseDelta.seconds())));
93}
94
96 float maxDistance) const {
97 if (!binding_ || !binding_->isValid())
99 eve::DiagnosticCode::PreconditionViolation, "Cannot project against an invalid surface constraint",
100 "fluids.surfaceConstraint.project"));
101 SurfaceLocation location;
102 if (!binding_->project(worldPosition, maxDistance, location))
104 eve::DiagnosticCode::NotFound, "No surface location satisfies the projection distance",
105 "fluids.surfaceConstraint.project"));
107}
108
110 const glm::vec3& displacement,
111 int maxCrossings) const {
112 if (!binding_ || !binding_->isValid())
115 "Cannot walk an invalid surface constraint", "fluids.surfaceConstraint.walk"));
116 if (maxCrossings < 0)
118 eve::DiagnosticCode::InvalidArgument, "Surface traversal maxCrossings must be non-negative",
119 "fluids.surfaceConstraint.walk.maxCrossings"));
120 const auto result = binding_->walkAcrossSurface(start, displacement, maxCrossings);
121 if (!result.valid)
123 eve::DiagnosticCode::NotFound, "Surface traversal start is outside the bound topology",
124 "fluids.surfaceConstraint.walk.start"));
126}
127
129 bool preferGpu) {
130 if (params.width <= 0 || params.height <= 0) throw eve::Exception("Surface SSF output dimensions must be positive");
131 renderer_ = std::make_unique<FluidSurfaceRenderer>(params, preferGpu);
132}
133
135
137 float particleRadius) {
139 eve::DiagnosticCode::PreconditionViolation, "Surface-fluid adapter has no live borrowed solver", "fluids.screenSpaceReconstruction.renderer"));
140 if (!std::isfinite(particleRadius) || particleRadius <= 0.f)
141 return eve::Result<void>::failure(eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "Screen-space particle radius must be finite and positive", "fluids.screenSpaceReconstruction.particleRadius"));
142 for (const glm::vec3& position : positions) {
143 if (!std::isfinite(position.x) || !std::isfinite(position.y) || !std::isfinite(position.z))
144 return eve::Result<void>::failure(eve::Diagnostic::error(eve::DiagnosticCode::InvalidArgument, "Screen-space particle positions must be finite", "fluids.screenSpaceReconstruction.positions"));
145 }
146 const std::vector<glm::vec3> ownedPositions(positions.begin(), positions.end());
147 renderer_->render(ownedPositions, particleRadius);
148 return applied();
149}
150
151eve::Result<void> ScreenSpaceSurfaceReconstructionAdapter::occlude(std::span<const float> sceneDepth, float depthBias) {
153 eve::DiagnosticCode::PreconditionViolation, "Surface-fluid adapter has no live borrowed solver", "fluids.screenSpaceReconstruction.renderer"));
154 return renderer_->occludeWithSceneDepth(sceneDepth, depthBias);
155}
156
157int ScreenSpaceSurfaceReconstructionAdapter::width() const noexcept { return renderer_ ? renderer_->getWidth() : 0; }
158
159int ScreenSpaceSurfaceReconstructionAdapter::height() const noexcept { return renderer_ ? renderer_->getHeight() : 0; }
160
161std::span<const float> ScreenSpaceSurfaceReconstructionAdapter::depth() const noexcept {
162 return renderer_ ? std::span<const float>(renderer_->depth()) : std::span<const float>{};
163}
164
165std::span<const glm::vec3> ScreenSpaceSurfaceReconstructionAdapter::normals() const noexcept {
166 return renderer_ ? std::span<const glm::vec3>(renderer_->normals()) : std::span<const glm::vec3>{};
167}
168
169std::span<const float> ScreenSpaceSurfaceReconstructionAdapter::thickness() const noexcept {
170 return renderer_ ? std::span<const float>(renderer_->thickness()) : std::span<const float>{};
171}
172
173std::span<const std::uint8_t> ScreenSpaceSurfaceReconstructionAdapter::color() const noexcept {
174 return renderer_ ? std::span<const std::uint8_t>(renderer_->color()) : std::span<const std::uint8_t>{};
175}
176
177bool ScreenSpaceSurfaceReconstructionAdapter::usingGpu() const noexcept { return renderer_ && renderer_->usingGpu(); }
178
179} // namespace eve::fluids
Duration start
float duration
std::map< std::string, Var > values
std::vector< std::uint32_t > indices
std::vector< float > positions
std::array< float, 3 > position
bool valid
std::string path
Definition PlayHost.cpp:110
std::uint32_t count
Domain contracts separating surface simulation, constraints, and SSF presentation.
float step
Definition TreeMesh.cpp:314
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
Signed, fixed-resolution simulation duration in nanoseconds.
Definition Time.h:43
double seconds() const noexcept
Return this duration as seconds for legacy/presentation APIs.
Definition Time.cpp:28
EVENGINE_API_FOUNDATION public API.
Definition Exception.h:13
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
static Status success(StatusCode code=StatusCode::Ok)
Construct a successful status with an explicit non-error outcome.
Definition Status.h:81
eve::Result< void > step(const eve::SimulationStep &step) override
Step.
std::span< const FluidParticle > particles() const noexcept override
Particles.
int particleCount() const noexcept override
Particle count.
int particleCount() const
Particle count.
const std::vector< FluidParticle > & particles() const
Particles.
void step(float dt)
Advance the simulation by dt seconds (params.iterations substeps).
bool build(const std::vector< glm::vec3 > &positions, const std::vector< uint32_t > &indices, const std::vector< glm::vec2 > &uvs={})
Build topology and initialize the current and previous poses.
void setTransform(const glm::mat4 &transform)
Apply a new rigid pose and preserve the old pose for velocity queries.
SurfaceSample evaluate(const SurfaceLocation &location, float dt) const
Evaluate a surface address in the current and previous poses.
bool isValid() const
True when valid.
bool setDeformedPositions(const std::vector< glm::vec3 > &worldPositions)
Supply a new deformed world-space pose and preserve the previous pose.
int triangleCount() const
Triangle count.
SurfaceWalkResult walkAcrossSurface(const SurfaceLocation &start, const glm::vec3 &worldDisplacement, int maxCrossings=16) const
Move a location by a world-space displacement, crossing triangle edges.
bool project(const glm::vec3 &worldPosition, float maxDistance, SurfaceLocation &outLocation) const
Find the closest material point on the current surface.
bool isValid() const noexcept override
True when valid.
eve::Result< SurfaceLocation > project(const glm::vec3 &worldPosition, float maxDistance) const override
Project.
eve::Result< void > setDeformedPositions(const std::vector< glm::vec3 > &worldPositions) override
Sets the deformed positions.
eve::Result< void > setTransform(const glm::mat4 &transform) override
Sets the transform.
eve::Result< void > build(const std::vector< glm::vec3 > &positions, const std::vector< std::uint32_t > &indices, const std::vector< glm::vec2 > &uvs={}) override
Builds .
eve::Result< SurfaceWalkResult > walk(const SurfaceLocation &start, const glm::vec3 &displacement, int maxCrossings=16) const override
Walk.
eve::Result< SurfaceSample > evaluate(const SurfaceLocation &location, eve::Duration poseDelta) const override
Evaluate.
std::span< const glm::vec3 > normals() const noexcept override
Normals.
std::span< const float > depth() const noexcept override
Depth.
eve::Result< void > reconstruct(std::span< const glm::vec3 > positions, float particleRadius) override
Reconstruct.
~ScreenSpaceSurfaceReconstructionAdapter() override
Releases ScreenSpaceSurfaceReconstructionAdapter resources.
std::span< const float > thickness() const noexcept override
Thickness.
std::span< const std::uint8_t > color() const noexcept override
Color.
eve::Result< void > occlude(std::span< const float > sceneDepth, float depthBias=0.001f) override
Occlude.
ScreenSpaceSurfaceReconstructionAdapter(const FluidSurfaceParams &params, bool preferGpu)
Constructs a ScreenSpaceSurfaceReconstructionAdapter.
std::vector< ParamSpec > params
Result< T > applied(T value, std::vector< Diagnostic > diagnostics={})
Construct an Applied result with an owning payload and optional diagnostics.
GLSL compute kernels for the GPU surface-flow solver.
Definition FluidTarget.h:12
One deterministic fixed-step emitted by SimulationClock.
Definition Time.h:158
SimulationTick tick
Tick reached after this step is applied.
Definition Time.h:160
Duration delta
Fixed simulation duration for this step.
Definition Time.h:162
Camera + reconstruction tuning for the SSF pipeline.
Stable material-space address of a point on a triangle surface.