载入中...
搜索中...
未找到
TerrainSediment.cpp
浏览该文件的文档.
1#include <numbers>
5
6namespace eve::procgen {
8 const Heightmap& velocityZ, const TerrainWaterSettings& water,
10 using namespace raster_detail;
11 auto sameShape = [&](const Heightmap& map) {
12 return validRaster(map) && map.getWidth() == heights.getWidth() && map.getHeight() == heights.getHeight();
13 };
14 auto positive = [](float v) { return std::isfinite(v) && v > 0; };
15 auto nonnegative = [](float v) { return std::isfinite(v) && v >= 0; };
16 if (&heights == &sediment || !validRaster(heights) || !sameShape(sediment) || !sameShape(velocityX) ||
17 !sameShape(velocityZ) ||
18 std::any_of(heights.data().begin(), heights.data().end(), [](float v) { return v < 0; }) ||
19 !positive(water.spacingX) || !positive(water.spacingZ) || !nonnegative(water.dt) || !std::isfinite(s.effect) ||
20 !nonnegative(s.depositRate) || !nonnegative(s.bankDeposit) || !nonnegative(s.bedDeposit))
21 return invalid(
22 "terrain.sediment: distinct matching finite outputs, nonnegative heights and valid coefficients required");
23 const int width = heights.getWidth(), height = heights.getHeight();
24 std::vector<float> nextHeight(heights.data().size()), nextSediment(sediment.data().size());
25 auto sampleSediment = [&](int x, int z) -> double {
26 return x < 0 || z < 0 || x >= width || z >= height ? 0 : sediment.height(x, z);
27 };
28 for (int z = 0; z < height; ++z)
29 for (int x = 0; x < width; ++x) {
30 const size_t i = size_t(z) * width + x;
31 const int left = std::max(x - 1, 0), right = std::min(x + 1, width - 1);
32 const int top = std::max(z - 1, 0), bottom = std::min(z + 1, height - 1);
33 const double dx =
34 (double(heights.height(right, bottom)) + 2.0 * heights.height(right, z) + heights.height(right, top) -
35 heights.height(left, bottom) - 2.0 * heights.height(left, z) - heights.height(left, top)) /
36 8;
37 const double dz =
38 (double(heights.height(left, top)) + 2.0 * heights.height(x, top) + heights.height(right, top) -
39 heights.height(left, bottom) - 2.0 * heights.height(x, bottom) - heights.height(right, bottom)) /
40 8;
41 // Source normal is normalize(dx,length(dx,dz),dz), giving this Y component for nonzero gradient.
42 const double slope = dx == 0 && dz == 0 ? 0 : std::numbers::sqrt2 / 2;
43 const double speed = std::hypot(double(velocityX.data()[i]), double(velocityZ.data()[i]));
44 const double deposited = double(water.dt) * std::lerp(double(s.bankDeposit), double(s.bedDeposit), slope) *
45 s.depositRate / std::max(speed, 0.05);
46 const double reactedSediment = std::max(double(sediment.data()[i]) - s.effect * deposited, 0.0);
47 const double newHeight = std::max(double(heights.data()[i]) + s.effect * deposited, 0.0);
48 const double bx =
49 std::clamp(double(x) - double(water.dt) * velocityX.data()[i] * water.spacingX, 0.0, double(width - 1));
50 const double bz = std::clamp(double(z) - double(water.dt) * velocityZ.data()[i] * water.spacingZ, 0.0,
51 double(height - 1));
52 const int x0 = int(bx), z0 = int(bz), x1 = x0 + 1, z1 = z0 + 1;
53 const double sx = (bx - x0) / width, tz = (bz - z0) / height;
54 // Preserve the source shader's exact weights/indexing; this is not standard bilinear advection.
55 const double transported = (1 - sx) * ((1 - tz) * sampleSediment(x0, z0) + tz * sampleSediment(x0, z1)) +
56 sx * (tz * sampleSediment(x1, x0) + tz * sampleSediment(x1, z1));
57 const double newSediment = reactedSediment + transported;
58 if (!isRepresentable(newHeight) || !isRepresentable(newSediment))
59 return invalid("terrain.sediment: output exceeds finite float range");
60 nextHeight[i] = float(newHeight);
61 nextSediment[i] = float(newSediment);
62 }
63 int changed = 0;
64 for (size_t i = 0; i < nextHeight.size(); ++i)
65 changed += nextHeight[i] != heights.data()[i] || nextSediment[i] != sediment.data()[i];
66 heights.data().swap(nextHeight);
67 sediment.data().swap(nextSediment);
68 return Result<int>::success(changed);
69}
70} // namespace eve::procgen
SQInteger top
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
const std::string & s
int bz
Definition CaveMesh.cpp:114
int bx
Definition CaveMesh.cpp:114
float v
HexVec3 left
HexVec3 right
std::uint32_t height
std::uint32_t width
float dz
float dx
TerrainWaterField water
Heightmap sediment
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
float height(int x, int y) const
Height.
Definition Heightmap.cpp:28
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.
EVENGINE_API_DOMAINS Result< int > applyTerrainSediment(Heightmap &heights, Heightmap &sediment, const Heightmap &velocityX, const Heightmap &velocityZ, const TerrainWaterSettings &water, const TerrainSedimentSettings &settings)
Apply the source sediment reaction and backtrace equations with atomic dual output.
Effective sediment coefficients from Hydraulic.compute, after UI conversion. The source hardcodes har...
Explicit constants for the source hydraulic water-flow equations, after UI unit conversion.