载入中...
搜索中...
未找到
TerrainErosion.cpp
浏览该文件的文档.
3
4#include <array>
5
6namespace eve::procgen {
8 using namespace raster_detail;
9 if (&heights == &sediment || !validRaster(heights) || !validRaster(sediment) ||
10 heights.getWidth() != sediment.getWidth() || heights.getHeight() != sediment.getHeight() ||
11 std::any_of(heights.data().begin(), heights.data().end(), [](float h) { return h < 0; }) ||
12 !std::isfinite(settings.spacingX) || settings.spacingX <= 0 || !std::isfinite(settings.spacingZ) ||
13 settings.spacingZ <= 0 || !std::isfinite(settings.heightScale) || settings.heightScale <= 0 ||
14 !std::isfinite(settings.reposeSlope) || settings.reposeSlope < 0 || !std::isfinite(settings.dt) ||
15 settings.dt < 0 || settings.iterations < 0)
16 return invalid(
17 "terrain.thermal: distinct matching rasters, nonnegative heights, positive scales and nonnegative "
18 "simulation controls required");
19 if (settings.iterations == 0 || settings.dt == 0) return Result<int>::success(0);
20 const int width = heights.getWidth(), height = heights.getHeight();
21 const double diagonal = std::hypot(double(settings.spacingX), double(settings.spacingZ));
22 Heightmap current = heights;
23 auto sedimentResult = sediment.data();
24 std::vector<float> next(heights.data().size());
25 for (int iteration = 0; iteration < settings.iterations; ++iteration) {
26 for (int y = 0; y < height; ++y) {
27 for (int x = 0; x < width; ++x) {
28 const int left = std::max(x - 1, 0), right = std::min(x + 1, width - 1);
29 const int top = std::min(y + 1, height - 1), bottom = std::max(y - 1, 0);
30 const size_t index = size_t(y) * width + x;
31 const double original = current.data()[index];
32 const std::array<float, 8> neighbors = {current.height(left, y), current.height(right, y),
33 current.height(x, top), current.height(x, bottom),
34 current.height(left, top), current.height(right, top),
35 current.height(left, bottom), current.height(right, bottom)};
36 double sum = 0;
37 for (int n = 0; n < 8; ++n) {
38 const double dh = double(settings.heightScale) * (original - neighbors[n]);
39 const double distance = n < 2 ? settings.spacingX : n < 4 ? settings.spacingZ : diagonal;
40 if (std::abs(dh / distance) > settings.reposeSlope) sum += dh * (n < 4 ? 1.0 : 0.707);
41 }
42 const double movement = std::clamp(0.0625 * settings.dt * sum, -0.5 * original, 0.5 * original);
43 const double newHeight = original - movement, newSediment = double(sedimentResult[index]) + movement;
44 if (!isRepresentable(newHeight) || !isRepresentable(newSediment))
45 return invalid("terrain.thermal: output exceeds finite float range");
46 next[index] = float(newHeight);
47 sedimentResult[index] = float(newSediment);
48 }
49 }
50 current.data().swap(next);
51 }
52 int changed = 0;
53 for (size_t i = 0; i < sedimentResult.size(); ++i)
54 changed += heights.data()[i] != current.data()[i] || sediment.data()[i] != sedimentResult[i];
55 heights.data().swap(current.data());
56 sediment.data().swap(sedimentResult);
57 return Result<int>::success(changed);
58}
59} // namespace eve::procgen
SQInteger top
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
glm::vec3 n
Definition Grass.cpp:63
HexVec3 left
HexVec3 right
int h
std::uint32_t height
std::uint32_t width
float distance
bool diagonal
double current
TerrainThermalSettings settings
Heightmap sediment
uint32_t index
float bottom
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
In-memory terrain heightmap: a dense float grid (row-major, index = y * width + x) materialized from ...
Definition Heightmap.h:21
int getHeight() const
Returns the height.
Definition Heightmap.cpp:17
const std::vector< float > & data() const
Data.
Definition Heightmap.h:48
int getWidth() const
Returns the width.
Definition Heightmap.cpp:16
bool validRaster(const Heightmap &map)
Valid raster.
Result< int > invalid(std::string message)
Invalid.
bool isRepresentable(double value)
True when representable.
Result< int > applyTerrainThermal(Heightmap &heights, Heightmap &sediment, const TerrainThermalSettings &settings)
Apply the source thermal equation, publishing height and sediment together.
Explicit simulation controls for the Pcg eight-neighbor thermal kernel. Height differences are multip...