13 data_.assign(
size_t(width_) *
size_t(height_), 0.f);
20 return x >= 0 &&
y >= 0 &&
x < width_ &&
y < height_;
25 data_[size_t(
y * width_ +
x)] =
h;
30 return data_[size_t(
y * width_ +
x)];
34float lerpHeight(
float a,
float b,
float t) {
return a + (
b -
a) *
t; }
38 if (width_ <= 0 || height_ <= 0)
return 0.f;
39 const float fx = std::clamp(
x, 0.f,
float(width_ - 1));
40 const float fy = std::clamp(
y, 0.f,
float(height_ - 1));
41 const int x0 = int(std::floor(fx));
42 const int y0 = int(std::floor(fy));
43 const int x1 = std::min(x0 + 1, width_ - 1);
44 const int y1 = std::min(y0 + 1, height_ - 1);
45 const float tx = fx - float(x0);
46 const float ty = fy - float(y0);
47 const float top = lerpHeight(data_[
size_t(y0 * width_ + x0)], data_[
size_t(y0 * width_ + x1)], tx);
48 const float bot = lerpHeight(data_[
size_t(y1 * width_ + x0)], data_[
size_t(y1 * width_ + x1)], tx);
49 return lerpHeight(
top, bot, ty);
53 if (width_ <= 0 || height_ <= 0)
return 0.f;
54 float px = std::fmod(
x,
float(width_));
55 float py = std::fmod(
y,
float(height_));
56 if (
px < 0.f)
px += float(width_);
57 if (
py < 0.f)
py += float(height_);
58 const int x0 = int(std::floor(
px));
59 const int y0 = int(std::floor(
py));
60 const int x1 = (x0 + 1) % width_;
61 const int y1 = (y0 + 1) % height_;
62 const float tx =
px - float(x0);
63 const float ty =
py - float(y0);
64 const float top = lerpHeight(data_[
size_t(y0 * width_ + x0)], data_[
size_t(y0 * width_ + x1)], tx);
65 const float bot = lerpHeight(data_[
size_t(y1 * width_ + x0)], data_[
size_t(y1 * width_ + x1)], tx);
66 return lerpHeight(
top, bot, ty);
71 if (
local.getWorldWidth() <= 0 ||
local.getWorldHeight() <= 0) {
75 const auto fn =
local.asFunction();
85 if (width_ <= 0 || height_ <= 0)
return false;
86 out.
resize(width_, height_);
87 for (
int y = 0;
y < height_; ++
y) {
88 for (
int x = 0;
x < width_; ++
x) {
vk::UniqueSampler sampler
Intermediate 2D generation result. cells store semantic ids (see Semantic.h), not tile GIDs — convert...
void resize(int width, int height)
Resize.
void setCell(int x, int y, int semantic)
Sets the cell.
In-memory terrain heightmap: a dense float grid (row-major, index = y * width + x) materialized from ...
int getHeight() const
Returns the height.
float sampleBilinear(float x, float y) const
Bilinear height at continuous coordinate within [0, w) x [0, h).
Heightmap()=default
Heightmap.
bool toGrid(Grid2D &out, const TerrainBands &bands) const
Classify heights into a semantic Grid2D (source for tilemap generation).
void resize(int width, int height)
Resize.
float height(int x, int y) const
Height.
float sampleBilinearSeamless(float x, float y) const
Bilinear height with wrap-around (seamless tiling).
void setHeight(int x, int y, float h)
Sets the height.
static Heightmap generate(const TerrainSampler &sampler, int width, int height)
Materialize a Heightmap by sampling sampler at every pixel center.
int getWidth() const
Returns the width.
bool inBounds(int x, int y) const
In bounds.
Deterministic terrain height sampling (Red Blob Games / Perlin fBm recipe).
void setWorldSize(int width, int height)
Sets the world size.
SettlementPipeline::Stage fn
uint32_t semanticAt(float height) const
Semantic at.