载入中...
搜索中...
未找到
SurfaceWetnessField.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <cmath>
5
6namespace eve::fluids {
7
9 triangles_ = binding.triangles();
10 values_.assign(size_t(binding.vertexCount()), 0.f);
11 neighbors_.assign(values_.size(), {});
12 edges_.clear();
13 if (values_.empty() || triangles_.empty()) return false;
14 for (const glm::uvec3& tri : triangles_) {
15 const int ids[3] = {int(tri.x), int(tri.y), int(tri.z)};
16 for (int edge = 0; edge < 3; ++edge) {
17 auto& list = neighbors_[size_t(ids[edge])];
18 const int other = ids[(edge + 1) % 3];
19 if (std::find(list.begin(), list.end(), other) == list.end()) list.push_back(other);
20 auto& reverse = neighbors_[size_t(other)];
21 if (std::find(reverse.begin(), reverse.end(), ids[edge]) == reverse.end())
22 reverse.push_back(ids[edge]);
23 const uint32_t a = uint32_t(std::min(ids[edge], other));
24 const uint32_t b = uint32_t(std::max(ids[edge], other));
25 const std::pair<uint32_t, uint32_t> pair{a, b};
26 if (std::find(edges_.begin(), edges_.end(), pair) == edges_.end()) edges_.push_back(pair);
27 }
28 }
29 return true;
30}
31
32void SurfaceWetnessField::deposit(const SurfaceLocation& location, float amount) {
33 if (location.triangle >= triangles_.size() || amount <= 0.f) return;
34 const glm::uvec3 tri = triangles_[location.triangle];
35 const glm::vec3 bary = glm::max(location.barycentric, glm::vec3(0.f));
36 values_[tri.x] += amount * bary.x;
37 values_[tri.y] += amount * bary.y;
38 values_[tri.z] += amount * bary.z;
39}
40
42 if (values_.empty() || dt <= 0.f) return;
43 dt = std::min(dt, 0.1f);
44 std::vector<float> next = values_;
45 const float diffusion = std::clamp(params.diffusion * dt, 0.f, 1.f);
46 const float evaporation = std::exp(-std::max(0.f, params.evaporation) * dt);
47 const float maximum = std::max(0.f, params.maxWetness);
48 // Antisymmetric edge flux preserves total film mass before evaporation/clamping.
49 for (const auto& [a, b] : edges_) {
50 const float degree = float(std::max(neighbors_[a].size(), neighbors_[b].size()));
51 const float flux = diffusion * (values_[b] - values_[a]) / std::max(1.f, degree);
52 next[a] += flux;
53 next[b] -= flux;
54 }
55 for (float& value : next)
56 value = std::clamp(value * evaporation, 0.f, maximum);
57 values_.swap(next);
58}
59
60float SurfaceWetnessField::sample(const SurfaceLocation& location) const {
61 if (location.triangle >= triangles_.size()) return 0.f;
62 const glm::uvec3 tri = triangles_[location.triangle];
63 return values_[tri.x] * location.barycentric.x + values_[tri.y] * location.barycentric.y +
64 values_[tri.z] * location.barycentric.z;
65}
66
67void SurfaceWetnessField::clear() { std::fill(values_.begin(), values_.end(), 0.f); }
68
69} // namespace eve::fluids
double value
float maximum[3]
glm::uvec4 ids
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
eve::action::ActionVfxBinding binding
const RoadEdge * edge
float size
Definition TreeMesh.cpp:156
glm::vec4 bary
Dynamic triangle surface used to bind films and droplets to deforming meshes.
void step(float dt, const SurfaceWetnessParams &params={})
Diffuse and evaporate the field by dt seconds.
void clear()
Reset all wetness to zero.
float sample(const SurfaceLocation &location) const
Sample.
void deposit(const SurfaceLocation &location, float amount)
Deposit a wet trace at a material-space location.
bool build(const FluidSurfaceBinding &binding)
Initialize the field from a surface topology.
std::vector< ParamSpec > params
GLSL compute kernels for the GPU surface-flow solver.
Definition FluidTarget.h:12
Stable material-space address of a point on a triangle surface.
Parameters controlling persistent wet-film traces on a triangle surface.