载入中...
搜索中...
未找到
CavePotholes.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, const CavePotholeSite& site, CaveHydrologyVec3 center, float scale) {
32 const CaveHydrologyVec3 delta = subtract(point, center);
33 const float along = dot(delta, site.tangent) / std::max(site.alongRadius * scale, 1e-6f);
34 const float lateral = dot(delta, site.lateral) / std::max(site.lateralRadius * scale, 1e-6f);
35 const float vertical = delta.y / std::max(site.depthRadius * scale, 1e-6f);
36 return 1.f - smoothstep(0.12f, 1.f, std::sqrt(along * along + lateral * lateral + vertical * vertical));
37}
38
39} // namespace
40
41std::vector<CavePotholeSite> createCavePotholeSites(const std::vector<CaveHydrologyPoint>& trunk,
42 const std::vector<float>& hydraulicWeights,
43 const std::vector<CaveFracture>& fractures,
44 float apertureVariability, float stressControl, float sedimentLoad,
45 float gravelSize, uint32_t seed) {
46 std::vector<CavePotholeSite> sites;
47 if (trunk.size() < 2 || fractures.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 for (size_t segment = 0; segment + 1 < trunk.size(); ++segment) {
51 const CaveHydrologyVec3 delta = subtract(trunk[segment + 1].position, trunk[segment].position);
52 const CaveHydrologyVec3 tangent = normalize(delta);
53 CaveHydrologyVec3 lateral = normalize({-tangent.z, 0.f, tangent.x});
54 if (std::fabs(tangent.y) > 0.94f) lateral = {0.f, 0.f, 1.f};
55 const float hydraulic = segment < hydraulicWeights.size() ? hydraulicWeights[segment] : 1.f;
56 if (hydraulic < 0.32f) continue;
57 for (int sampleIndex = 1; sampleIndex <= 8; ++sampleIndex) {
58 const float t = float(sampleIndex) / 9.f;
59 const CaveHydrologyVec3 pathPoint = add(trunk[segment].position, multiply(delta, t));
60 float strongest = 0.f;
61 float second = 0.f;
62 for (const CaveFracture& fracture : fractures) {
63 const CaveFractureSample fractureSample = sampleCaveFracture(
64 {pathPoint.x, pathPoint.y, pathPoint.z, fracture, apertureVariability, stressControl, seed});
65 if (fractureSample.mask > strongest) {
66 second = strongest;
67 strongest = fractureSample.mask;
68 } else {
69 second = std::max(second, fractureSample.mask);
70 }
71 }
72 const float intersection = strongest * second;
73 if (intersection < 0.055f) continue;
74 const float radius = trunk[segment].radius + (trunk[segment + 1].radius - trunk[segment].radius) * t;
75 CaveHydrologyVec3 center = pathPoint;
76 center.y -= radius * 0.88f;
77 const float minimumSpacing = radius * 1.45f;
78 if (!sites.empty() && length(subtract(center, sites.back().center)) < minimumSpacing) continue;
79 const float potential = smoothstep(0.04f, 0.42f, intersection) * tools * (1.f - cover) *
80 std::pow(std::clamp(hydraulic, 0.25f, 1.6f), 1.2f);
81 const float footprint = radius * (0.42f + 0.18f * potential);
82 sites.push_back({center, tangent, lateral, footprint * 1.12f, footprint, footprint * 1.28f, intersection,
83 potential, std::clamp(gravelSize, 0.f, 1.f)});
84 break;
85 }
86 }
87 return sites;
88}
89
90CavePotholeSample sampleCavePotholeErosion(CaveHydrologyVec3 point, const std::vector<CavePotholeSite>& sites) {
91 CavePotholeSample result;
92 for (size_t i = 0; i < sites.size(); ++i) {
93 const CavePotholeSite& site = sites[i];
94 const float fineTools = 1.f - site.gravelSize;
95 const float downstreamBias = fineTools * 2.f - 1.f;
96 const CaveHydrologyVec3 primaryCenter =
97 add(site.center, multiply(site.tangent, site.alongRadius * downstreamBias * 0.22f));
98 const float spread = 0.72f + fineTools * 0.38f;
99 const float wallAndBed = ellipsoid(point, site, primaryCenter, spread) * site.erosionPotential;
100 CaveHydrologyVec3 secondaryCenter = site.center;
101 secondaryCenter.y -= site.depthRadius * 0.72f;
102 const float secondary = ellipsoid(point, site, secondaryCenter, 0.46f) * site.erosionPotential *
103 smoothstep(0.38f, 0.82f, site.erosionPotential) * 0.72f;
104 const float erosion = std::max(wallAndBed, secondary);
105 if (erosion > result.erosion) result = {erosion, wallAndBed, secondary, downstreamBias, int(i)};
106 }
107 return result;
108}
109
110} // namespace eve::procgen
double value
Vec3 tangent
Definition CaveMesh.cpp:80
float length
Definition CaveMesh.cpp:94
std::int32_t second
int secondary
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::uint32_t seed
Definition PointSet.cpp:807
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
std::vector< CavePotholeSite > createCavePotholeSites(const std::vector< CaveHydrologyPoint > &trunk, const std::vector< float > &hydraulicWeights, const std::vector< CaveFracture > &fractures, float apertureVariability, float stressControl, float sedimentLoad, float gravelSize, uint32_t seed)
Derive eddy-pothole sites from intersections of existing fracture planes along the trunk bed.
CaveFractureSample sampleCaveFracture(const CaveFractureInput &input)
Sample a spatially correlated fracture aperture and stress-split dissolution front.
CavePotholeSample sampleCavePotholeErosion(CaveHydrologyVec3 point, const std::vector< CavePotholeSite > &sites)
Sample gravel-size-dependent pothole abrasion around derived sites.
Observable local state of a sampled dissolving fracture.
One deterministic structural fracture plane in normalized cave space.
CaveHydrologyVec3 public API.
Local primary and compound pothole erosion response.
One fracture-seeded, sediment-driven eddy pothole on a cave-stream bed.