载入中...
搜索中...
未找到
CaveObstacleScour.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <cmath>
5
6namespace eve::procgen {
7namespace {
8
9CaveHydrologyVec3 add(CaveHydrologyVec3 a, CaveHydrologyVec3 b) { return {a.x + b.x, a.y + b.y, a.z + b.z}; }
10
11CaveHydrologyVec3 subtract(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
19float length(CaveHydrologyVec3 value) { return std::sqrt(dot(value, value)); }
20
21CaveHydrologyVec3 normalize(CaveHydrologyVec3 value) {
22 const float magnitude = length(value);
23 return magnitude > 1e-6f ? multiply(value, 1.f / magnitude) : CaveHydrologyVec3{1.f, 0.f, 0.f};
24}
25
26float smoothstep(float lo, float hi, float value) {
27 const float t = std::clamp((value - lo) / std::max(hi - lo, 1e-6f), 0.f, 1.f);
28 return t * t * (3.f - 2.f * t);
29}
30
31float ellipsoid(CaveHydrologyVec3 point, CaveHydrologyVec3 center, const CaveObstacleScourSite& site, float alongRadius,
32 float lateralRadius, float depthRadius) {
33 const CaveHydrologyVec3 delta = subtract(point, center);
34 const float along = dot(delta, site.tangent) / std::max(alongRadius, 1e-6f);
35 const float lateral = dot(delta, site.lateral) / std::max(lateralRadius, 1e-6f);
36 const float vertical = delta.y / std::max(depthRadius, 1e-6f);
37 return 1.f - smoothstep(0.12f, 1.f, std::sqrt(along * along + lateral * lateral + vertical * vertical));
38}
39
40} // namespace
41
42std::vector<CaveObstacleScourSite> createCaveObstacleScourSites(const CaveBreakdownSet& breakdown,
43 const std::vector<CaveHydrologyPoint>& trunk,
44 const std::vector<float>& hydraulicWeights,
45 float sedimentLoad, float wallRoughness) {
46 std::vector<CaveObstacleScourSite> sites;
47 if (breakdown.events.empty() || trunk.size() < 2 || sedimentLoad <= 0.f) return sites;
48 const float tools = smoothstep(0.025f, 0.28f, sedimentLoad);
49 const float cover = std::clamp(sedimentLoad * sedimentLoad * 0.68f, 0.f, 0.68f);
50 const float roughnessRetention = 1.f - 0.72f * smoothstep(0.12f, 0.82f, wallRoughness);
51 for (const CaveBreakdownEvent& event : breakdown.events) {
52 for (const CaveBreakdownBlock& block : event.blocks) {
53 const CaveHydrologyVec3 blockCenter{block.x, block.y, block.z};
54 size_t nearestSegment = 0;
55 float nearestDistance = 1e9f;
56 CaveHydrologyVec3 nearestPoint;
57 for (size_t segment = 0; segment + 1 < trunk.size(); ++segment) {
58 const CaveHydrologyVec3 pathDelta = subtract(trunk[segment + 1].position, trunk[segment].position);
59 const float length2 = dot(pathDelta, pathDelta);
60 const float t =
61 length2 > 1e-8f
62 ? std::clamp(dot(subtract(blockCenter, trunk[segment].position), pathDelta) / length2, 0.f, 1.f)
63 : 0.f;
64 const CaveHydrologyVec3 closest = add(trunk[segment].position, multiply(pathDelta, t));
65 const float distance = length(subtract(blockCenter, closest));
66 if (distance < nearestDistance) {
67 nearestDistance = distance;
68 nearestSegment = segment;
69 nearestPoint = closest;
70 }
71 }
72 const float passageRadius = 0.5f * (trunk[nearestSegment].radius + trunk[nearestSegment + 1].radius);
73 if (nearestDistance > passageRadius * 1.65f) continue;
75 normalize(subtract(trunk[nearestSegment + 1].position, trunk[nearestSegment].position));
76 CaveHydrologyVec3 lateral = normalize({-tangent.z, 0.f, tangent.x});
77 if (std::fabs(tangent.y) > 0.94f) lateral = {0.f, 0.f, 1.f};
78 const float hydraulic = nearestSegment < hydraulicWeights.size() ? hydraulicWeights[nearestSegment] : 1.f;
79 const float protrusion = 2.f * block.hy / std::max(passageRadius, 1e-6f);
80 const float potential = tools * (1.f - cover) * roughnessRetention * smoothstep(0.08f, 0.48f, protrusion) *
81 std::pow(std::clamp(hydraulic, 0.25f, 1.6f), 1.2f);
82 if (potential <= 0.01f) continue;
83 const float obstacleWidth = std::max(block.hx, block.hz);
84 CaveHydrologyVec3 frontCenter = add(blockCenter, multiply(tangent, -obstacleWidth * 0.85f));
85 CaveHydrologyVec3 wakeCenter = add(blockCenter, multiply(tangent, obstacleWidth * 1.4f));
86 frontCenter.y = nearestPoint.y - passageRadius * 0.88f;
87 wakeCenter.y = frontCenter.y + obstacleWidth * 0.12f;
88 sites.push_back({blockCenter, frontCenter, wakeCenter, tangent, lateral, obstacleWidth * 1.15f,
89 obstacleWidth * 1.45f, obstacleWidth * 0.82f, obstacleWidth * 2.35f, potential,
90 roughnessRetention});
91 }
92 }
93 return sites;
94}
95
97 const std::vector<CaveObstacleScourSite>& sites) {
99 for (size_t i = 0; i < sites.size(); ++i) {
100 const CaveObstacleScourSite& site = sites[i];
101 const CaveHydrologyVec3 left = add(site.frontCenter, multiply(site.lateral, site.frontLateralRadius * 0.42f));
102 const CaveHydrologyVec3 right = add(site.frontCenter, multiply(site.lateral, -site.frontLateralRadius * 0.42f));
103 const float leftLobe =
104 ellipsoid(point, left, site, site.frontAlongRadius, site.frontLateralRadius * 0.68f, site.depthRadius);
105 const float rightLobe =
106 ellipsoid(point, right, site, site.frontAlongRadius, site.frontLateralRadius * 0.68f, site.depthRadius);
107 const float horseshoe = std::max(leftLobe, rightLobe) * site.erosionPotential;
108 const float wake = ellipsoid(point, site.wakeCenter, site, site.wakeAlongRadius,
109 site.frontLateralRadius * 0.72f, site.depthRadius * 0.52f) *
110 site.erosionPotential * 0.58f;
111 const float erosion = std::max(horseshoe, wake);
112 if (erosion > result.erosion) result = {erosion, horseshoe, wake, site.roughnessRetention, int(i)};
113 }
114 return result;
115}
116
117} // namespace eve::procgen
double value
Vec3 tangent
Definition CaveMesh.cpp:80
float length
Definition CaveMesh.cpp:94
HexVec3 left
HexVec3 right
std::array< float, 3 > position
std::array< float, 3 > scale
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
float distance
float t
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
CaveObstacleScourSample sampleCaveObstacleScour(CaveHydrologyVec3 point, const std::vector< CaveObstacleScourSite > &sites)
Sample deep upstream horseshoe scour and shallower elongated wake erosion.
std::vector< CaveObstacleScourSite > createCaveObstacleScourSites(const CaveBreakdownSet &breakdown, const std::vector< CaveHydrologyPoint > &trunk, const std::vector< float > &hydraulicWeights, float sedimentLoad, float wallRoughness)
Couple landed breakdown blocks to the nearest authoritative cave-stream segment.
CaveBreakdownBlock public API.
CaveBreakdownEvent public API.
CaveBreakdownSet public API.
std::vector< CaveBreakdownEvent > events
CaveHydrologyVec3 public API.
Local upstream horseshoe and downstream wake erosion response.
One landed breakdown block coupled to a horseshoe-vortex and wake scour footprint.