21 density.size() !=
size_t(
nx) *
size_t(
ny) *
size_t(
nz) ||
22 (rateField !=
nullptr && rateField->size() != density.size()))
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));
31 for (
int iteration = 0; iteration <
iterations; ++iteration) {
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) {
38 if (std::fabs(
value) > band)
continue;
40 auto at = [&](
int ox,
int oy,
int oz) {
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;
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)) /
58 const float curvatureTimesGradient = hxx + hyy + hzz - normalHessian;
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) {
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.