载入中...
搜索中...
未找到
CaveReactivePatchiness.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <cmath>
5#include <cstddef>
6#include <cstdint>
7
8namespace eve::procgen {
9namespace {
10
11size_t voxelIndex(int x, int y, int z, int nx, int ny) {
12 return size_t(x) + size_t(y) * size_t(nx) + size_t(z) * size_t(nx) * size_t(ny);
13}
14
15uint64_t mixBits(uint64_t value) {
16 value ^= value >> 30u;
17 value *= 0xbf58476d1ce4e5b9ULL;
18 value ^= value >> 27u;
19 value *= 0x94d049bb133111ebULL;
20 return value ^ (value >> 31u);
21}
22
23float latticeValue(int x, int y, int z, uint64_t seed) {
24 uint64_t key = seed ^ (uint64_t(uint32_t(x)) * 0x9e3779b185ebca87ULL);
25 key ^= uint64_t(uint32_t(y)) * 0xc2b2ae3d27d4eb4fULL;
26 key ^= uint64_t(uint32_t(z)) * 0x165667b19e3779f9ULL;
27 return float(mixBits(key) >> 40u) * (2.f / 16777215.f) - 1.f;
28}
29
30float smooth(float value) { return value * value * (3.f - 2.f * value); }
31
32float lerp(float a, float b, float t) { return a + (b - a) * t; }
33
34float valueNoise(float x, float y, float z, float frequency, uint64_t seed) {
35 x *= frequency;
36 y *= frequency;
37 z *= frequency;
38 const int x0 = int(std::floor(x)), y0 = int(std::floor(y)), z0 = int(std::floor(z));
39 const float tx = smooth(x - float(x0)), ty = smooth(y - float(y0)), tz = smooth(z - float(z0));
40 const float x00 = lerp(latticeValue(x0, y0, z0, seed), latticeValue(x0 + 1, y0, z0, seed), tx);
41 const float x10 = lerp(latticeValue(x0, y0 + 1, z0, seed), latticeValue(x0 + 1, y0 + 1, z0, seed), tx);
42 const float x01 = lerp(latticeValue(x0, y0, z0 + 1, seed), latticeValue(x0 + 1, y0, z0 + 1, seed), tx);
43 const float x11 = lerp(latticeValue(x0, y0 + 1, z0 + 1, seed), latticeValue(x0 + 1, y0 + 1, z0 + 1, seed), tx);
44 return lerp(lerp(x00, x10, ty), lerp(x01, x11, ty), tz);
45}
46
47float dot(const CaveHydrologyVec3& a, const CaveHydrologyVec3& b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
48
49CaveHydrologyVec3 normalize(CaveHydrologyVec3 value) {
50 const float length = std::sqrt(dot(value, value));
51 if (length <= 1e-6f) return {1.f, 0.f, 0.f};
52 return {value.x / length, value.y / length, value.z / length};
53}
54
55CaveHydrologyVec3 add(CaveHydrologyVec3 a, CaveHydrologyVec3 b) { return {a.x + b.x, a.y + b.y, a.z + b.z}; }
56
57CaveHydrologyVec3 mul(CaveHydrologyVec3 value, float scale) {
58 return {value.x * scale, value.y * scale, value.z * scale};
59}
60
61CaveHydrologyVec3 transverse(CaveHydrologyVec3 tangent) {
62 CaveHydrologyVec3 value{-tangent.z, 0.f, tangent.x};
63 if (dot(value, value) <= 1e-6f) value = {1.f, 0.f, 0.f};
64 return normalize(value);
65}
66
67CaveHydrologyVec3 flowWarp(CaveHydrologyVec3 position, CaveHydrologyVec3 tangent) {
68 constexpr float longitudinalScale = 0.28f;
70 return add(position, mul(tangent, dot(position, tangent) * (longitudinalScale - 1.f)));
71}
72
73float patchRate(CaveHydrologyVec3 position, CaveHydrologyVec3 tangent, uint64_t seed) {
74 const CaveHydrologyVec3 warped = flowWarp(position, tangent);
75 const float broad = valueNoise(warped.x, warped.y, warped.z, 3.25f, seed ^ 0x7265616374697665ULL);
76 const float detail = valueNoise(warped.x, warped.y, warped.z, 7.5f, seed ^ 0x7061746368657321ULL);
77 const float spectrum = std::clamp(broad * 0.72f + detail * 0.28f, -1.f, 1.f);
78 const float normalized = smooth(spectrum * 0.5f + 0.5f);
79 return 0.35f + normalized * 1.65f;
80}
81
82} // namespace
83
85 const std::vector<float>& rateField,
86 const std::vector<CaveHydrologyVec3>& flowField,
87 int nx, int ny, int nz, float strength,
88 uint64_t seed, int iterations) {
90 if (strength <= 0.f || iterations <= 0 || nx < 5 || ny < 5 || nz < 5 || density.size() != rateField.size() ||
91 density.size() != flowField.size() || density.size() != size_t(nx) * size_t(ny) * size_t(nz))
92 return result;
93
94 const float hx = 2.f / float(nx - 1), hy = 2.f / float(ny - 1), hz = 2.f / float(nz - 1);
95 const float cellScale = std::min({hx, hy, hz});
96 const float band = cellScale * 2.5f;
97 std::vector<float> source(density.size());
98 std::vector<uint8_t> affected(density.size(), uint8_t(0));
99 float coherenceTotal = 0.f;
100 float flowCoherenceTotal = 0.f;
101 float transverseCoherenceTotal = 0.f;
102 int coherenceSamples = 0;
103
104 for (int iteration = 0; iteration < iterations; ++iteration) {
105 source = density;
106 for (int z = 2; z < nz - 2; ++z) {
107 for (int y = 2; y < ny - 2; ++y) {
108 for (int x = 2; x < nx - 2; ++x) {
109 const size_t center = voxelIndex(x, y, z, nx, ny);
110 const float value = source[center];
111 if (std::fabs(value) > band) continue;
112 const float px = float(x) / float(nx - 1) * 2.f - 1.f;
113 const float py = float(y) / float(ny - 1) * 2.f - 1.f;
114 const float pz = float(z) / float(nz - 1) * 2.f - 1.f;
116 const CaveHydrologyVec3 flow = normalize(flowField[center]);
117 const CaveHydrologyVec3 across = transverse(flow);
118 const float localPatchRate = patchRate(position, flow, seed);
119 const float adjacentPatchRate = patchRate({px + hx, py, pz}, flow, seed);
120 const float flowPatchRate = patchRate(add(position, mul(flow, cellScale)), flow, seed);
121 const float transversePatchRate = patchRate(add(position, mul(across, cellScale)), flow, seed);
122 coherenceTotal += 1.f - std::min(std::fabs(localPatchRate - adjacentPatchRate) / 1.65f, 1.f);
123 flowCoherenceTotal += 1.f - std::min(std::fabs(localPatchRate - flowPatchRate) / 1.65f, 1.f);
124 transverseCoherenceTotal +=
125 1.f - std::min(std::fabs(localPatchRate - transversePatchRate) / 1.65f, 1.f);
126 ++coherenceSamples;
127
128 const float surfaceWeight = 1.f - std::clamp(std::fabs(value) / band, 0.f, 1.f);
129 const float accessRate = std::clamp(rateField[center], 0.25f, 2.5f);
130 const float coupledPatchRate = 1.f + strength * (localPatchRate - 1.f);
131 const float retreat = strength * cellScale * 0.032f * surfaceWeight * accessRate *
132 coupledPatchRate / float(iterations);
133 if (retreat <= 1e-7f) continue;
134 density[center] -= retreat;
135 if (affected[center] == 0) {
136 affected[center] = 1;
137 ++result.affectedVoxels;
138 }
139 result.maximumRetreat = std::max(result.maximumRetreat, retreat);
140 result.totalRetreat += retreat;
141 result.minimumPatchRate = std::min(result.minimumPatchRate, coupledPatchRate);
142 result.maximumPatchRate = std::max(result.maximumPatchRate, coupledPatchRate);
143 }
144 }
145 }
146 }
147 if (coherenceSamples > 0) {
148 result.meanNeighborCoherence = coherenceTotal / float(coherenceSamples);
149 result.meanFlowCoherence = flowCoherenceTotal / float(coherenceSamples);
150 result.meanTransverseCoherence = transverseCoherenceTotal / float(coherenceSamples);
151 const float flowDifference = std::max(1.f - result.meanFlowCoherence, 1e-6f);
152 const float transverseDifference = std::max(1.f - result.meanTransverseCoherence, 1e-6f);
153 result.channelAnisotropy = transverseDifference / flowDifference;
154 }
155 return result;
156}
157
158} // namespace eve::procgen
double value
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
Vec3 tangent
Definition CaveMesh.cpp:80
float length
Definition CaveMesh.cpp:94
float py
float nx
float nz
float ny
float pz
std::uint32_t key
HexVec3 across
std::vector< Colorf > px
std::array< float, 3 > position
std::array< float, 3 > scale
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
std::uint32_t seed
Definition PointSet.cpp:807
int detail
float t
int iterations
Definition TreeMesh.cpp:311
const UnitySourceAsset & source
constexpr HexVec3 lerp(HexVec3 a, HexVec3 b, float t) noexcept
Linear interpolation between two positions.
Definition HexMetrics.h:51
Vec2 normalize(const Vec2 &a)
Normalize.
Definition UrbanTypes.h:44
double dot(const Vec2 &a, const Vec2 &b)
Dot.
Definition UrbanTypes.h:38
CaveReactivePatchinessResult evolveCaveSurfaceByCorrelatedReactivity(std::vector< float > &density, const std::vector< float > &rateField, const std::vector< CaveHydrologyVec3 > &flowField, int nx, int ny, int nz, float strength, uint64_t seed, int iterations)
Retreat a cave surface through a deterministic, multiscale correlated reactivity field.
CaveHydrologyVec3 public API.
Diagnostics from spatially correlated heterogeneous cave-wall dissolution.