载入中...
搜索中...
未找到
CaveSurfaceEvolution.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
15} // namespace
16
17CaveSurfaceEvolutionResult evolveSurface(std::vector<float>& density, const std::vector<float>* rateField, int nx,
18 int ny, int nz, float strength, int iterations) {
20 if (strength <= 0.f || iterations <= 0 || nx < 3 || ny < 3 || nz < 3 ||
21 density.size() != size_t(nx) * size_t(ny) * size_t(nz) ||
22 (rateField != nullptr && rateField->size() != density.size()))
23 return result;
24
25 const float hx = 2.f / float(nx - 1), hy = 2.f / float(ny - 1), hz = 2.f / float(nz - 1);
26 const float cellScale = std::min({hx, hy, hz});
27 const float band = cellScale * 2.5f;
28 std::vector<float> source(density.size());
29 std::vector<uint8_t> affected(density.size(), uint8_t(0));
30
31 for (int iteration = 0; iteration < iterations; ++iteration) {
32 source = density;
33 for (int z = 1; z < nz - 1; ++z) {
34 for (int y = 1; y < ny - 1; ++y) {
35 for (int x = 1; x < nx - 1; ++x) {
36 const size_t center = voxelIndex(x, y, z, nx, ny);
37 const float value = source[center];
38 if (std::fabs(value) > band) continue;
39
40 auto at = [&](int ox, int oy, int oz) {
41 return source[voxelIndex(x + ox, y + oy, z + oz, nx, ny)];
42 };
43 const float gx = (at(1, 0, 0) - at(-1, 0, 0)) / (2.f * hx);
44 const float gy = (at(0, 1, 0) - at(0, -1, 0)) / (2.f * hy);
45 const float gz = (at(0, 0, 1) - at(0, 0, -1)) / (2.f * hz);
46 const float gradient2 = gx * gx + gy * gy + gz * gz;
47 if (gradient2 < 1e-8f) continue;
48
49 const float hxx = (at(1, 0, 0) - 2.f * value + at(-1, 0, 0)) / (hx * hx);
50 const float hyy = (at(0, 1, 0) - 2.f * value + at(0, -1, 0)) / (hy * hy);
51 const float hzz = (at(0, 0, 1) - 2.f * value + at(0, 0, -1)) / (hz * hz);
52 const float hxy = (at(1, 1, 0) - at(1, -1, 0) - at(-1, 1, 0) + at(-1, -1, 0)) / (4.f * hx * hy);
53 const float hxz = (at(1, 0, 1) - at(1, 0, -1) - at(-1, 0, 1) + at(-1, 0, -1)) / (4.f * hx * hz);
54 const float hyz = (at(0, 1, 1) - at(0, 1, -1) - at(0, -1, 1) + at(0, -1, -1)) / (4.f * hy * hz);
55 const float normalHessian = (gx * gx * hxx + gy * gy * hyy + gz * gz * hzz +
56 2.f * (gx * gy * hxy + gx * gz * hxz + gy * gz * hyz)) /
57 gradient2;
58 const float curvatureTimesGradient = hxx + hyy + hzz - normalHessian;
59
60 // The field is negative in cave air and positive in rock. Positive
61 // curvature therefore identifies exposed convex cavity walls. Retreat
62 // those sites, while leaving concave shelters and sharp scallop crests
63 // to the directional erosion model.
64 const float normalizedCurvature = std::max(0.f, curvatureTimesGradient * cellScale);
65 if (normalizedCurvature <= 1e-5f) continue;
66 const float surfaceWeight = 1.f - std::clamp(std::fabs(value) / band, 0.f, 1.f);
67 const float rateMultiplier =
68 rateField == nullptr ? 1.f : std::clamp((*rateField)[center], 0.25f, 2.5f);
69 const float retreat = strength * cellScale * 0.12f * surfaceWeight *
70 std::min(normalizedCurvature, 1.5f) * rateMultiplier / float(iterations);
71 density[center] -= retreat;
72 if (affected[center] == 0) {
73 affected[center] = 1;
74 ++result.affectedVoxels;
75 }
76 result.maximumRetreat = std::max(result.maximumRetreat, retreat);
77 result.totalRetreat += retreat;
78 result.minimumRateMultiplier = std::min(result.minimumRateMultiplier, rateMultiplier);
79 result.maximumRateMultiplier = std::max(result.maximumRateMultiplier, rateMultiplier);
80 }
81 }
82 }
83 }
84 return result;
85}
86
87CaveSurfaceEvolutionResult evolveCaveSurfaceByCurvature(std::vector<float>& density, int nx, int ny, int nz,
88 float strength, int iterations) {
89 return evolveSurface(density, nullptr, nx, ny, nz, strength, iterations);
90}
91
93 const std::vector<float>& rateField, int nx, int ny, int nz,
94 float strength, int iterations) {
95 return evolveSurface(density, &rateField, nx, ny, nz, strength, iterations);
96}
97
98} // namespace eve::procgen
double value
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
float nx
float nz
float ny
int iterations
Definition TreeMesh.cpp:311
const UnitySourceAsset & source
std::size_t at
double oy
double ox
CaveSurfaceEvolutionResult evolveSurface(std::vector< float > &density, const std::vector< float > *rateField, int nx, int ny, int nz, float strength, int iterations)
CaveSurfaceEvolutionResult evolveCaveSurfaceByCurvature(std::vector< float > &density, int nx, int ny, int nz, float strength, int iterations)
Evolve cave surface by curvature.
CaveSurfaceEvolutionResult public API.