载入中...
搜索中...
未找到
CaveSurfaceReactivity.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <array>
5#include <cmath>
6#include <cstddef>
7#include <cstdint>
8
9namespace eve::procgen {
10namespace {
11
12struct Normal {
13 float x = 0.f;
14 float y = 0.f;
15 float z = 0.f;
16 bool valid = false;
17};
18
19size_t voxelIndex(int x, int y, int z, int nx, int ny) {
20 return size_t(x) + size_t(y) * size_t(nx) + size_t(z) * size_t(nx) * size_t(ny);
21}
22
23Normal densityNormal(const std::vector<float>& density, int x, int y, int z, int nx, int ny, float hx, float hy,
24 float hz) {
25 const float gx = (density[voxelIndex(x + 1, y, z, nx, ny)] - density[voxelIndex(x - 1, y, z, nx, ny)]) / (2.f * hx);
26 const float gy = (density[voxelIndex(x, y + 1, z, nx, ny)] - density[voxelIndex(x, y - 1, z, nx, ny)]) / (2.f * hy);
27 const float gz = (density[voxelIndex(x, y, z + 1, nx, ny)] - density[voxelIndex(x, y, z - 1, nx, ny)]) / (2.f * hz);
28 const float length = std::sqrt(gx * gx + gy * gy + gz * gz);
29 if (length <= 1e-6f) return {};
30 return {gx / length, gy / length, gz / length, true};
31}
32
33} // namespace
34
36 const std::vector<float>& rateField, int nx, int ny, int nz,
37 float strength, int iterations) {
39 if (strength <= 0.f || iterations <= 0 || nx < 5 || ny < 5 || nz < 5 || density.size() != rateField.size() ||
40 density.size() != size_t(nx) * size_t(ny) * size_t(nz))
41 return result;
42
43 const float hx = 2.f / float(nx - 1), hy = 2.f / float(ny - 1), hz = 2.f / float(nz - 1);
44 const float cellScale = std::min({hx, hy, hz});
45 const float band = cellScale * 2.5f;
46 const std::array<std::array<int, 3>, 6> offsets = {
47 {{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}}};
48 std::vector<float> source(density.size());
49 std::vector<uint8_t> affected(density.size(), uint8_t(0));
50
51 for (int iteration = 0; iteration < iterations; ++iteration) {
52 source = density;
53 for (int z = 2; z < nz - 2; ++z) {
54 for (int y = 2; y < ny - 2; ++y) {
55 for (int x = 2; x < nx - 2; ++x) {
56 const size_t center = voxelIndex(x, y, z, nx, ny);
57 const float value = source[center];
58 if (std::fabs(value) > band) continue;
59 const Normal centerNormal = densityNormal(source, x, y, z, nx, ny, hx, hy, hz);
60 if (!centerNormal.valid) continue;
61
62 float dispersion = 0.f;
63 int samples = 0;
64 for (const auto& offset : offsets) {
65 const int sx = x + offset[0], sy = y + offset[1], sz = z + offset[2];
66 if (std::fabs(source[voxelIndex(sx, sy, sz, nx, ny)]) > band * 1.5f) continue;
67 const Normal neighbor = densityNormal(source, sx, sy, sz, nx, ny, hx, hy, hz);
68 if (!neighbor.valid) continue;
69 const float alignment = std::fabs(centerNormal.x * neighbor.x + centerNormal.y * neighbor.y +
70 centerNormal.z * neighbor.z);
71 dispersion += 1.f - std::clamp(alignment, 0.f, 1.f);
72 ++samples;
73 }
74 if (samples < 2) continue;
75 const float normalDispersion = std::clamp(std::sqrt(dispersion / float(samples)) * 1.8f, 0.f, 1.f);
76 if (normalDispersion <= 1e-4f) continue;
77
78 const float surfaceWeight = 1.f - std::clamp(std::fabs(value) / band, 0.f, 1.f);
79 const float rateMultiplier = std::clamp(rateField[center], 0.25f, 2.5f);
80 const float retreat = strength * cellScale * 0.045f * surfaceWeight * normalDispersion *
81 rateMultiplier / float(iterations);
82 density[center] -= retreat;
83 if (affected[center] == 0) {
84 affected[center] = 1;
85 ++result.affectedVoxels;
86 }
87 result.maximumRetreat = std::max(result.maximumRetreat, retreat);
88 result.totalRetreat += retreat;
89 result.maximumNormalDispersion = std::max(result.maximumNormalDispersion, normalDispersion);
90 result.minimumRateMultiplier = std::min(result.minimumRateMultiplier, rateMultiplier);
91 result.maximumRateMultiplier = std::max(result.maximumRateMultiplier, rateMultiplier);
92 }
93 }
94 }
95 }
96 return result;
97}
98
99} // namespace eve::procgen
double value
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
float length
Definition CaveMesh.cpp:94
float nx
float nz
float ny
size_t offset
bool valid
int iterations
Definition TreeMesh.cpp:311
const UnitySourceAsset & source
CaveSurfaceReactivityResult evolveCaveSurfaceByReactivity(std::vector< float > &density, const std::vector< float > &rateField, int nx, int ny, int nz, float strength, int iterations)
Retreat rough, highly reactive surface sites using rotation-invariant normal dispersion.
Diagnostics from geometry-controlled cave-surface dissolution.