载入中...
搜索中...
未找到
RoadRecipes.cpp
浏览该文件的文档.
2
3#include "image/ImageData.h"
7
8#include <algorithm>
9#include <cmath>
10
11namespace eve::procgen::road {
12namespace {
13
14RoadBakeOptions bakeOptionsFromParams(const Params& params) {
15 RoadBakeOptions options;
16 options.pathSegmentsPerEdge = std::max(4, params.getInt("pathSegments", 48));
17 options.turnSamples = std::max(4, params.getInt("turnSamples", 12));
18 options.includePiers = params.getBool("piers", true);
19 options.includeMarkings = params.getBool("markings", true);
20 options.includeNavigation = params.getBool("navigation", true);
21 options.includeJunctions = params.getBool("junctions", true);
22 options.includePlacements = params.getBool("placements", true);
23 options.junctionChordError = params.getFloat("junctionChordError", 0.10f);
24 options.sideObjectSpacing = params.getFloat("sideObjectSpacing", 8.f);
25 options.sideObjectOffset = params.getFloat("sideObjectOffset", 0.5f);
26 options.sideObjectClearance = params.getFloat("sideObjectClearance", 1.5f);
27 return options;
28}
29
30Result<RoadNetwork> networkFromParams(const Params& params) {
31 const std::string scene = params.getString("scene", "straight");
32 return RoadNetwork::makeScene(scene, params.getFloat("span", 36.f), params.getFloat("bridgeHeight", 6.f),
33 std::max(1, params.getInt("lanes", 2)), params.getSeed());
34}
35
36} // namespace
37
39 auto network = networkFromParams(params);
40 if (!network.ok()) return Result<RoadBakeResult>::failure(network.status());
41 return bakeRoadNetwork(network.value(), bakeOptionsFromParams(params));
42}
43
44bool generateRoadNetworkMesh(const Params& params, MeshBuild& out, std::string& error) {
45 auto baked = bakeRoadNetworkRecipe(params);
46 if (!baked.ok()) {
47 error = baked.status().describe();
48 return false;
49 }
50 out = std::move(baked.value().mesh);
51 return true;
52}
53
55 auto baked = bakeRoadNetworkRecipe(params);
56 if (!baked.ok()) return Result<RoadOverlay>::failure(baked.status());
57 return Result<RoadOverlay>::success(std::move(baked.value().overlay));
58}
59
60std::unique_ptr<image::ImageData> generateRoadMarkingsTexture(const Params& params, std::string& error) {
61 const int width = std::clamp(params.getWidth() > 0 ? params.getWidth() : params.getInt("width", 256), 8, 2048);
62 const int height = std::clamp(params.getHeight() > 0 ? params.getHeight() : params.getInt("height", 64), 8, 2048);
63 const float dashPeriod = std::max(0.05f, params.getFloat("dashPeriod", 0.18f));
64 const float dashDuty = std::clamp(params.getFloat("dashDuty", 0.45f), 0.05f, 0.95f);
65 const bool zebra = params.getBool("zebra", true);
66
67 auto image = std::make_unique<image::ImageData>(width, height, "RGBA8");
68 for (int y = 0; y < height; ++y) {
69 const float v = (static_cast<float>(y) + 0.5f) / static_cast<float>(height);
70 for (int x = 0; x < width; ++x) {
71 const float u = (static_cast<float>(x) + 0.5f) / static_cast<float>(width);
72 float r = 0.18f, g = 0.18f, b = 0.20f;
73
74 // White edge lines near v=0 and v=1.
75 if (v < 0.08f || v > 0.92f) {
76 r = g = b = 0.92f;
77 }
78 // Yellow dashed center.
79 else if (std::fabs(v - 0.5f) < 0.035f) {
80 const float phase = std::fmod(u, dashPeriod) / dashPeriod;
81 if (phase < dashDuty) {
82 r = 0.95f;
83 g = 0.75f;
84 b = 0.12f;
85 }
86 }
87 // Lane divider dashes at 1/4 and 3/4.
88 else if (std::fabs(v - 0.25f) < 0.02f || std::fabs(v - 0.75f) < 0.02f) {
89 const float phase = std::fmod(u + 0.05f, dashPeriod) / dashPeriod;
90 if (phase < dashDuty) r = g = b = 0.88f;
91 }
92
93 // Zebra band near u ends (intersection approach).
94 if (zebra && (u < 0.08f || u > 0.92f)) {
95 const int stripe = static_cast<int>(v * 12.f);
96 if ((stripe & 1) == 0) r = g = b = 0.95f;
97 }
98
99 // Direction arrow glyph in the middle third.
100 const float au = (u - 0.42f) / 0.16f;
101 const float av = (v - 0.5f) / 0.18f;
102 if (au >= 0.f && au <= 1.f && std::fabs(av) <= (1.f - au) * 0.55f + 0.08f) {
103 r = 0.95f;
104 g = 0.45f;
105 b = 0.08f;
106 }
107
108 image->setPixel(x, y, image::ImageData::Colorf{r, g, b, 1.f});
109 }
110 }
111 (void)error;
112 return image;
113}
114
116 RecipeDescriptor schema{"mesh.roadNetwork", "Procedural Road Network", "Mesh", {}};
117 schema.params.push_back(ParamDescriptor::integer("seed", "Seed", 1, 0, 2147483647));
118 schema.params.push_back(ParamDescriptor::choice("scene", "Scene", "straight",
119 {"straight", "curve", "bridge", "cross", "tee", "y", "fork",
120 "skew", "t-junction", "y-junction", "sloped-t", "curve-uphill",
121 "tight-turn", "roundabout", "interchange"}));
122 schema.params.push_back(ParamDescriptor::floating("span", "Span", 36.f, 16.f, 256.f, 1.f));
123 schema.params.push_back(ParamDescriptor::floating("bridgeHeight", "Bridge Height", 6.f, 1.f, 64.f, 0.5f));
124 schema.params.push_back(ParamDescriptor::integer("lanes", "Lanes", 2, 1, 4));
125 schema.params.push_back(ParamDescriptor::integer("pathSegments", "Path Segments", 32, 8, 256));
126 schema.params.push_back(ParamDescriptor::boolean("piers", "Piers", true));
127 schema.params.push_back(ParamDescriptor::boolean("markings", "Markings", true));
128 schema.params.push_back(ParamDescriptor::boolean("navigation", "Navigation Overlay", true));
129 schema.params.push_back(ParamDescriptor::boolean("junctions", "Junctions", true));
130 schema.params.push_back(ParamDescriptor::boolean("placements", "Decoration Placements", true));
131 schema.params.push_back(
132 ParamDescriptor::floating("sideObjectSpacing", "Side Object Spacing", 8.f, 0.25f, 100.f, 0.25f));
133 schema.params.push_back(
134 ParamDescriptor::floating("sideObjectOffset", "Side Object Offset", 0.5f, 0.f, 32.f, 0.1f));
135 schema.params.push_back(
136 ParamDescriptor::floating("sideObjectClearance", "Side Object Clearance", 1.5f, 0.f, 32.f, 0.1f));
137 schema.params.push_back(
138 ParamDescriptor::floating("junctionChordError", "Junction Curve Error", 0.10f, 0.01f, 1.f, 0.01f));
139 schema.params.push_back(
140 ParamDescriptor::floating("terrainBlendDistance", "Terrain Surface Blend", 2.f, 0.f, 64.f, 0.25f));
141 schema.params.push_back(ParamDescriptor::floating("chunkSize", "Render Chunk Size", 64.f, 4.f, 1024.f, 1.f));
142 schema.params.push_back(ParamDescriptor::integer("lodCount", "LOD Count", 3, 1, 4));
143 registry.registerRecipe(std::move(schema), generateRoadNetworkMesh);
144}
145
147 RecipeDescriptor schema = RecipeDescriptor::grid("tex.roadMarkings", "Road Markings Logic", "Road", 8, 8);
148 schema.params.push_back(ParamDescriptor::floating("dashPeriod", "Dash Period", 0.18f, 0.02f, 1.f, 0.01f));
149 schema.params.push_back(ParamDescriptor::floating("dashDuty", "Dash Duty", 0.45f, 0.05f, 0.95f, 0.01f));
150 schema.params.push_back(ParamDescriptor::boolean("zebra", "Zebra Ends", true));
151 registry.registerRecipe(std::move(schema), generateRoadMarkingsTexture);
152}
153
154} // namespace eve::procgen::road
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float phase
Definition CaveMesh.cpp:58
tensor::Graph g
Definition GpuGraph.cpp:7
vk::UniqueImage image
float u
Definition Grass.cpp:233
double r
float v
std::uint32_t height
std::uint32_t width
MeleePoint3 b
Definition MeleeHit.cpp:41
std::string error
Definition Package.cpp:60
std::weak_ptr< PrimitiveScene > scene
const SquirrelValueOptions & options
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
medialoader::Colorf Colorf
Definition ImageData.h:41
CPU triangle mesh from procedural mesh recipes (e.g. marching cubes). Positions/normals are xyz-packe...
Definition MeshBuild.h:19
EVENGINE_API_DOMAINS public API.
void registerRecipe(const std::string &id, MeshRecipeFn fn)
Register a recipe without metadata.
Owning, typed generation parameters.
Definition Params.h:27
EVENGINE_API_DOMAINS public API.
void registerRecipe(const std::string &id, TextureRecipeFn fn)
Register a recipe without metadata.
static Result< RoadNetwork > makeScene(const std::string &scene, float span=36.f, float bridgeHeight=6.f, int lanes=2, std::uint32_t seed=1)
Dispatch a named debug/demo scene.
std::vector< ParamSpec > params
Result< RoadOverlay > generateRoadNetworkOverlay(const Params &params)
Bake navigation overlay for the same Params used by mesh.roadNetwork.
std::unique_ptr< image::ImageData > generateRoadMarkingsTexture(const Params &params, std::string &error)
Pure-function road marking atlas (asphalt + edge + dashed center + zebra).
Result< RoadBakeResult > bakeRoadNetwork(const RoadNetwork &network, const RoadBakeOptions &options)
Bake every edge, junction platform, pier, marking and navigation overlay.
Result< RoadBakeResult > bakeRoadNetworkRecipe(const Params &params)
Build the shared road recipe once for mesh, navigation and artifact projections.
bool generateRoadNetworkMesh(const Params &params, MeshBuild &out, std::string &error)
Generate a multi-level interchange mesh from Params (span/height/lanes/seed).
void registerRoadMeshRecipes(MeshRecipeRegistry &registry)
Registers road mesh recipes.
void registerRoadTextureRecipes(TextureRecipeRegistry &registry)
Registers road texture recipes.
static ParamDescriptor boolean(std::string key, std::string label, bool defaultValue)
Construct a Boolean descriptor stored as zero or one in Params.
static ParamDescriptor choice(std::string key, std::string label, std::string defaultValue, std::vector< std::string > choices)
Construct a finite-choice string descriptor.
static ParamDescriptor floating(std::string key, std::string label, float defaultValue, float minimum, float maximum, float step)
Construct a bounded floating-point descriptor.
static ParamDescriptor integer(std::string key, std::string label, int defaultValue, int minimum, int maximum, int step=1)
Construct a bounded integer descriptor.
Complete metadata and parameter schema shared by every procgen recipe family.
Definition ParamSchema.h:52
static RecipeDescriptor grid(std::string id, std::string displayName, std::string category, int minimumWidth, int minimumHeight, int maximumWidth=4096, int maximumHeight=4096)
Create a schema with common seed, width and height parameters.
std::vector< ParamDescriptor > params
Definition ParamSchema.h:56