载入中...
搜索中...
未找到
CaveConstrictionScour.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <cmath>
5
6namespace eve::procgen {
7namespace {
8
9CaveHydrologyVec3 subtract(CaveHydrologyVec3 a, CaveHydrologyVec3 b) { return {a.x - b.x, a.y - b.y, a.z - b.z}; }
10
11CaveHydrologyVec3 add(CaveHydrologyVec3 a, CaveHydrologyVec3 b) { return {a.x + b.x, a.y + b.y, a.z + b.z}; }
12
13CaveHydrologyVec3 multiply(CaveHydrologyVec3 value, float scale) {
14 return {value.x * scale, value.y * scale, value.z * scale};
15}
16
17float dot(CaveHydrologyVec3 a, CaveHydrologyVec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
18
19CaveHydrologyVec3 normalize(CaveHydrologyVec3 value) {
20 const float length = std::sqrt(dot(value, value));
21 return length > 1e-6f ? multiply(value, 1.f / length) : CaveHydrologyVec3{1.f, 0.f, 0.f};
22}
23
24float smoothstep(float lo, float hi, float value) {
25 const float t = std::clamp((value - lo) / std::max(hi - lo, 1e-6f), 0.f, 1.f);
26 return t * t * (3.f - 2.f * t);
27}
28
29void appendPathSites(const std::vector<CaveHydrologyPoint>& path, const std::vector<float>& weights,
30 std::vector<CaveConstrictionScourSite>& sites) {
31 if (path.size() < 5) return;
32 for (size_t i = 2; i + 2 < path.size(); ++i) {
33 const float shoulderRadius =
34 0.25f * (path[i - 2].radius + path[i - 1].radius + path[i + 1].radius + path[i + 2].radius);
35 const float constrictionRatio =
36 std::clamp((shoulderRadius - path[i].radius) / std::max(shoulderRadius, 1e-6f), 0.f, 1.f);
37 if (constrictionRatio < 0.06f || path[i].radius > path[i - 1].radius || path[i].radius > path[i + 1].radius)
38 continue;
39
40 const CaveHydrologyVec3 tangent = normalize(subtract(path[i + 1].position, path[i - 1].position));
41 CaveHydrologyVec3 lateral = normalize({-tangent.z, 0.f, tangent.x});
42 if (std::fabs(tangent.y) > 0.94f) lateral = {0.f, 0.f, 1.f};
43 const float hydraulicIntensity = i < weights.size() ? weights[i] : 1.f;
44 const float dischargeState = std::clamp((hydraulicIntensity - 0.25f) / 1.35f, 0.f, 1.f);
45 const float optimalConstriction = 0.35f + 0.15f * dischargeState;
46 const float optimalOffset = (constrictionRatio - optimalConstriction) / 0.16f;
47 const float plungingEfficiency =
48 smoothstep(0.08f, 0.22f, constrictionRatio) * std::exp(-0.5f * optimalOffset * optimalOffset);
49 const float poolScale = shoulderRadius * (0.9f + 0.55f * constrictionRatio);
50 CaveHydrologyVec3 center = add(path[i].position, multiply(tangent, shoulderRadius * 0.9f));
51 center.y -= shoulderRadius * (0.25f + 0.45f * constrictionRatio);
52 sites.push_back({path[i].position, center, tangent, lateral, poolScale * 2.4f, poolScale * 1.2f,
53 poolScale * 1.05f, constrictionRatio, hydraulicIntensity, optimalConstriction,
54 plungingEfficiency});
55 }
56}
57
58} // namespace
59
60std::vector<CaveConstrictionScourSite> createCaveConstrictionScourSites(
61 const std::vector<CaveHydrologyPoint>& trunk, const std::vector<CaveHydrologyBranch>& branches,
62 const CaveHydrologyWeights& hydrology) {
63 std::vector<CaveConstrictionScourSite> sites;
64 appendPathSites(trunk, hydrology.trunk, sites);
65 for (size_t i = 0; i < branches.size(); ++i) {
66 const std::vector<float> empty;
67 appendPathSites(branches[i].points, i < hydrology.branches.size() ? hydrology.branches[i] : empty, sites);
68 }
69 return sites;
70}
71
73 const std::vector<CaveConstrictionScourSite>& sites) {
75 for (size_t i = 0; i < sites.size(); ++i) {
76 const CaveConstrictionScourSite& site = sites[i];
77 const CaveHydrologyVec3 delta = subtract(point, site.poolCenter);
78 const float along = dot(delta, site.tangent);
79 const float lateral = dot(delta, site.lateral);
80 const float vertical = delta.y;
81 const float normalizedDistance =
82 std::sqrt((along * along) / std::max(site.alongRadius * site.alongRadius, 1e-6f) +
83 (lateral * lateral) / std::max(site.lateralRadius * site.lateralRadius, 1e-6f) +
84 (vertical * vertical) / std::max(site.depthRadius * site.depthRadius, 1e-6f));
85 const float envelope = 1.f - smoothstep(0.12f, 1.f, normalizedDistance);
86 const float flow = std::clamp(site.hydraulicIntensity, 0.25f, 1.6f);
87 const float bedBias = 1.f - smoothstep(-0.05f, 0.7f, vertical / std::max(site.depthRadius, 1e-6f));
88 const float exitPosition = along / std::max(site.alongRadius, 1e-6f);
89 const float poolEntranceStress =
90 0.55f + 0.45f * std::exp(-0.5f * std::pow((exitPosition + 0.35f) / 0.32f, 2.f));
91 const float exitBias = smoothstep(0.05f, 0.65f, exitPosition) *
92 (1.f - smoothstep(0.65f, 1.f, std::fabs(lateral) / std::max(site.lateralRadius, 1e-6f)));
93 const float bedScour = envelope * bedBias * site.plungingEfficiency * poolEntranceStress * flow;
94 const float exitWidening = envelope * exitBias * site.plungingEfficiency * flow * 0.82f;
95 const float erosion = std::max(bedScour, exitWidening);
96 if (erosion > result.erosion) {
97 result = {erosion, bedScour, exitWidening, site.constrictionRatio, site.plungingEfficiency, int(i)};
98 }
99 }
100 return result;
101}
102
103} // namespace eve::procgen
double value
Vec3 tangent
Definition CaveMesh.cpp:80
float length
Definition CaveMesh.cpp:94
std::array< float, 3 > position
std::array< float, 3 > scale
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
float radius
std::string path
Definition PlayHost.cpp:110
std::shared_ptr< const std::vector< glm::vec2 > > points
float t
float weights[3]
glm::vec3 point
Vec2 normalize(const Vec2 &a)
Normalize.
Definition UrbanTypes.h:44
double dot(const Vec2 &a, const Vec2 &b)
Dot.
Definition UrbanTypes.h:38
std::vector< CaveConstrictionScourSite > createCaveConstrictionScourSites(const std::vector< CaveHydrologyPoint > &trunk, const std::vector< CaveHydrologyBranch > &branches, const CaveHydrologyWeights &hydrology)
Derive scour sites from local radius minima in the authoritative hydrology paths.
CaveConstrictionScourSample sampleCaveConstrictionScour(CaveHydrologyVec3 point, const std::vector< CaveConstrictionScourSite > &sites)
Sample bed scour downstream of a constriction and lateral erosion near the pool exit.
Local plunging-flow scour and exit-widening response.
One flow-driven constriction-pool-widening sequence derived from passage geometry.
CaveHydrologyVec3 public API.
CaveHydrologyWeights public API.
std::vector< std::vector< float > > branches