3#include <QtCore/QTimer>
14 return ++_requestIdCounter;
21 _pending.insert(requestId, QList<float>());
22 QTimer::singleShot(0,
this, [
this, requestId] {
23 if (_pending.remove(requestId)) {
24 emit patchHeightsFailed(requestId);
32 const double step = span / gridSize;
33 const int verticesPerEdge = gridSize + 1;
36 heights.reserve(qsizetype(verticesPerEdge) * verticesPerEdge);
38 for (
int row = 0; row < verticesPerEdge; row++) {
39 const double y = minCorner.y() + span - (row * step);
40 for (
int col = 0; col < verticesPerEdge; col++) {
41 const double x = minCorner.x() + (col * step);
46 _pending.insert(requestId, heights);
47 QTimer::singleShot(0,
this, [
this, requestId] { _deliver(requestId); });
53 _pending.remove(requestId);
74 const double y = minCorner.y() + span - (span * (row + 0.5) /
kSynthGridSize);
76 const double x = minCorner.x() + (span * (col + 0.5) /
kSynthGridSize);
83 QTimer::singleShot(0,
this, [
this, key, grid = std::move(grid)]()
mutable {
85 _heightField->insertTile(key, std::move(grid));
91void ProceduralHeightSource::_deliver(
int requestId)
93 const auto it = _pending.constFind(requestId);
94 if (it == _pending.constEnd()) {
97 const QList<float> heights = it.value();
111 const double normalized = (std::sin(world.x() * phase) * std::cos(world.y() * phase) + 1.0) / 2.0;
112 return static_cast<float>(normalized *
kAmplitude);
float heightAtWorld(const QPointF &world) const override
Height in meters at a world-space ground position.
static constexpr double kWavelength
hill spacing (world m)
static constexpr double kAmplitude
peak height (m)
float heightAtWorld(const QPointF &world) const override
Height in meters at a world-space ground position.
bool hasTile(const TileMath::TileKey &key) const
True when the backing pyramid holds this exact tile.
void patchHeightsReady(int requestId, const QList< float > &heights)
heights has (gridSize+1)^2 entries, row-major from the north-west corner
HeightField * _heightField
tile delivery target for requestTile (not owned)
HeightSource(QObject *parent=nullptr)
static constexpr int kSynthGridSize
samples per edge of a synthesized tile
void cancelRequest(int requestId) final
Cancel a pending request. No signal is emitted for a cancelled request.
virtual float heightAtWorld(const QPointF &world) const =0
Height in meters at a world-space ground position.
int requestPatchHeights(const TileMath::TileKey &key, int gridSize) final
Request the vertex height grid for a patch. Returns a request id (> 0).
bool requestTile(const TileMath::TileKey &key) override
QPointF tileMinCorner(const TileKey &key)
South-west (minimum x/y) corner of a tile in world meters.
bool isValidKey(const TileKey &key)
True if zoom is within [kMinZoom, kMaxZoom] and x/y address a tile at that zoom.
double tileSpanAtZoom(int zoom)
Edge length of one tile at zoom, in world meters.
Decoded elevation samples for one tile, row-major from the NW corner.
QList< float > heights
meters