载入中...
搜索中...
未找到
PcgRuntimeStamper.cpp
浏览该文件的文档.
2
4
5#include <algorithm>
6#include <cmath>
7
8namespace eve::procgen {
9namespace {
10template <typename T> Result<T> invalid(const std::string& message) {
12 "procgen.pcgRuntimeStamper"));
13}
14
15bool validRaster(const Heightmap& map) {
16 return map.getWidth() > 0 && map.getHeight() > 0 &&
17 std::all_of(map.data().begin(), map.data().end(), [](float value) { return std::isfinite(value); });
18}
19} // namespace
20
21Result<void> PcgRuntimeStamper::configure(std::string stampAddress, bool showGui, bool showDebug) {
22 std::replace(stampAddress.begin(), stampAddress.end(), '\\', '/');
23 if (stampAddress.empty()) return invalid<void>("stamp resource address must not be empty");
24 address_ = std::move(stampAddress);
25 showGui_ = showGui;
26 showDebug_ = showDebug;
27 stamp_ = {};
28 progress_.clear();
30 return Result<void>::success();
31}
32
33Result<void> PcgRuntimeStamper::loadStamp(const Heightmap& stamp, const std::string& resourceName) {
34 if (status_ == PcgRuntimeStampStatus::Idle)
35 return invalid<void>("configure must be called before loading a stamp");
36 if (!validRaster(stamp)) {
37 progress_ = "Failed to load stamp";
39 return invalid<void>("stamp resource must be a finite nonempty raster");
40 }
41 stamp_ = stamp;
42 progress_ = "Loaded stamp at " + resourceName;
44 return Result<void>::success();
45}
46
48 if (status_ == PcgRuntimeStampStatus::Idle)
49 return invalid<void>("configure must be called before reporting a missing stamp");
50 progress_ = "Failed to load stamp at " + address_;
52 return invalid<void>(progress_);
53}
54
55Result<int> PcgRuntimeStamper::execute(Heightmap& target, double originX, double originZ,
56 double spacingX, double spacingZ) {
57 if (status_ != PcgRuntimeStampStatus::Loaded || !validRaster(stamp_))
58 return invalid<int>("a valid stamp resource must be loaded before execution");
59 if (!validRaster(target) || !std::isfinite(originX) || !std::isfinite(originZ) ||
60 !std::isfinite(spacingX) || !std::isfinite(spacingZ) || spacingX <= 0.0 || spacingZ <= 0.0)
61 return invalid<int>("finite nonempty terrain and positive grid spacing are required");
62
63 Heightmap candidate = target;
64 std::fill(candidate.data().begin(), candidate.data().end(), 0.0F);
65 Heightmap distanceMask(stamp_.getWidth(), stamp_.getHeight());
66 const double halfX = std::max(0.5, double(stamp_.getWidth() - 1) * 0.5);
67 const double halfY = std::max(0.5, double(stamp_.getHeight() - 1) * 0.5);
68 for (int y = 0; y < distanceMask.getHeight(); ++y) {
69 for (int x = 0; x < distanceMask.getWidth(); ++x) {
70 const double nx = (x - double(stamp_.getWidth() - 1) * 0.5) / halfX;
71 const double ny = (y - double(stamp_.getHeight() - 1) * 0.5) / halfY;
72 distanceMask.setHeight(x, y, float(std::max(0.0, 1.0 - std::sqrt(nx * nx + ny * ny))));
73 }
74 }
75 Heightmap one(1, 1);
76 one.setHeight(0, 0, 1.0F);
78 settings.originX = originX;
79 settings.originZ = originZ;
80 settings.spacingX = spacingX;
81 settings.spacingZ = spacingZ;
82 settings.centerX = originX + double(target.getWidth() - 1) * spacingX * 0.5;
83 settings.centerZ = originZ + double(target.getHeight() - 1) * spacingZ * 0.5;
84 settings.width = std::max(spacingX, double(target.getWidth() - 1) * spacingX);
85 settings.depth = std::max(spacingZ, double(target.getHeight() - 1) * spacingZ);
86 settings.rotation = 0.0;
87 settings.amplitude = 6.0F;
89 auto result = applyTerrainStamp(candidate, stamp_, settings, one, distanceMask);
90 if (!result.ok()) {
91 progress_ = "Failed to load stamp";
93 return result;
94 }
95 target = std::move(candidate);
96 progress_ = "Stamp progress: 1";
98 return result;
99}
100
101Result<void> PcgRuntimeStamper::updateLayout(double screenWidth, double screenHeight) {
102 if (!std::isfinite(screenWidth) || !std::isfinite(screenHeight) || screenWidth < 0.0 || screenHeight < 0.0)
103 return invalid<void>("finite non-negative screen dimensions are required");
104 labelX_ = screenWidth * 0.5;
105 labelY_ = screenHeight - 20.0;
106 return Result<void>::success();
107}
108
109} // namespace eve::procgen
LogicalId target
double value
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float nx
float ny
std::string message
TerrainThermalSettings settings
Heightmap stamp
double spacingZ
double spacingX
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
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
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
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
void setHeight(int x, int y, float h)
Sets the height.
Definition Heightmap.cpp:23
int getWidth() const
Returns the width.
Definition Heightmap.cpp:16
const std::string & stampAddress() const noexcept
Return the normalized resource address.
Result< void > configure(std::string stampAddress, bool showGui=true, bool showDebug=true)
Set the resource address and presentation flags; backslashes are normalized to slashes.
Result< void > updateLayout(double screenWidth, double screenHeight)
Recompute Pcg's 300x20 bottom-centred progress-label rectangle.
Result< void > reportMissingStamp()
Record the same missing-resource failure exposed by Pcg RuntimeStamper.
Result< void > loadStamp(const Heightmap &stamp, const std::string &resourceName)
Copy a decoded stamp resource into the controller.
Result< int > execute(Heightmap &target, double originX=0.0, double originZ=0.0, double spacingX=1.0, double spacingZ=1.0)
Flatten target to zero, fit the stamp to its complete grid, and apply height 6 with a linear radial m...
bool validRaster(const Heightmap &map)
Valid raster.
Result< int > invalid(std::string message)
Invalid.
Result< int > applyTerrainStamp(Heightmap &target, const Heightmap &stamp, const TerrainStampSettings &s, const Heightmap &localMask, const Heightmap &globalMask)
Apply a rotated, bilinearly sampled stamp; publish only after all checks succeed.
Value configuration for a rectangular stamp in world X/Z coordinates.