载入中...
搜索中...
未找到
RoadTraffic.cpp
浏览该文件的文档.
2
3#include "common/Diagnostic.h"
4
5#include <algorithm>
6#include <cmath>
7#include <string>
8#include <vector>
9
11namespace {
12
13struct Approach {
14 const RoadEdge* edge = nullptr;
15 const RoadNode* node = nullptr;
16 SplinePath spline;
17 float length = 0.f;
18 float socketDistance = 0.f;
19 float halfWidth = 0.f;
21};
22
23const char* controlRole(RoadJunctionControl control) {
24 switch (control) {
25 case RoadJunctionControl::Yield: return "junction.control.yield";
26 case RoadJunctionControl::Stop: return "junction.control.stop";
27 case RoadJunctionControl::Signal: return "junction.control.signal";
29 }
30 return "junction.control.uncontrolled";
31}
32
33} // namespace
34
36 const RoadBakeOptions& options) {
37 std::vector<Approach> approaches;
38 for (const auto& node : network.nodes()) {
39 if (node.junctionControl == RoadJunctionControl::Uncontrolled) continue;
40 const auto incidentCount = std::count_if(network.edges().begin(), network.edges().end(),
41 [&](const RoadEdge& edge) {
42 return edge.from == node.id || edge.to == node.id;
43 });
44 if (incidentCount < 2) continue;
45
46 int maximumPriority = 0;
47 bool hasIncidentEdge = false;
48 for (const auto& edge : network.edges()) {
49 if (edge.from != node.id && edge.to != node.id) continue;
50 maximumPriority = hasIncidentEdge ? std::max(maximumPriority, edge.style.trafficPriority)
51 : edge.style.trafficPriority;
52 hasIncidentEdge = true;
53 }
54
55 bool hasLowerPriority = false;
56 for (const auto& edge : network.edges())
57 if ((edge.from == node.id || edge.to == node.id) && edge.style.trafficPriority < maximumPriority)
58 hasLowerPriority = true;
59
60 for (const auto& edge : network.edges()) {
62 if (edge.to == node.id && edge.lanesForward > 0)
64 else if (edge.from == node.id && edge.lanesBackward > 0)
66 else
67 continue;
68 if (node.junctionControl == RoadJunctionControl::Yield && hasLowerPriority &&
69 edge.style.trafficPriority == maximumPriority)
70 continue;
71
73 if (!spline.ok()) return Result<void>::failure(spline.status());
74 auto length = spline.value().lengthResult(32);
75 if (!length.ok()) return Result<void>::failure(length.status());
76 auto profile = makeRoadProfile(edge.style, edge.lanesForward, edge.lanesBackward);
77 if (!profile.ok()) return Result<void>::failure(profile.status());
78 approaches.push_back({&edge, &node, std::move(spline).takeValue(), length.value(),
80 profile.value().halfWidth, direction});
81 }
82 }
83
84 if (static_cast<std::size_t>(placements.getCount()) + approaches.size() >
85 static_cast<std::size_t>(options.maximumPlacements))
87 "road traffic-control anchors exceed the placement budget",
88 "placements", {}, "procgen.road"));
89
90 for (const auto& approach : approaches) {
91 const bool forward = approach.direction == RoadLaneDirection::Forward;
92 const float distance = forward ? approach.length - approach.socketDistance : approach.socketDistance;
93 auto frame = approach.spline.travelFrameResult(distance, "clamp", 32);
94 if (!frame.ok()) return Result<void>::failure(frame.status());
95 const auto& f = frame.value();
96 const float directionSign = forward ? 1.f : -1.f;
97 const float lateral = (forward ? 1.f : -1.f) * (approach.halfWidth + options.sideObjectOffset);
98 const float dx = f.forwardX * directionSign;
99 const float dy = f.forwardY * directionSign;
100 const float dz = f.forwardZ * directionSign;
101 const int row = placements.add(f.sample.x + f.sideX * lateral, f.sample.y + f.sideY * lateral,
102 f.sample.z + f.sideZ * lateral);
103 placements.setNormal(row, f.upX, f.upY, f.upZ);
104 placements.setYaw(row, std::atan2(dx, dz) * 57.2957795f);
105 const char* role = controlRole(approach.node->junctionControl);
106 placements.setPointSeed(row, deriveSeed(approach.node->id,
107 std::string(role) + std::to_string(approach.edge->id)));
108 const std::uint64_t ordinal = static_cast<std::uint64_t>(approach.edge->id) * 2u +
109 static_cast<std::uint64_t>(approach.direction) + 1u;
110 auto status = placements.trySetPointId(
111 row, derivePointId(0x4a43545200000000ull | approach.node->id, ordinal));
112 if (!status.ok()) return status;
113 status = placements.trySetStringAttribute(row, "road_role", role);
114 if (!status.ok()) return status;
115 status = placements.trySetIntAttribute(row, "road_node_id", approach.node->id);
116 if (!status.ok()) return status;
117 status = placements.trySetIntAttribute(row, "road_edge_id", approach.edge->id);
118 if (!status.ok()) return status;
119 status = placements.trySetIntAttribute(row, "road_side", 1);
120 if (!status.ok()) return status;
121 status = placements.trySetIntAttribute(row, "traffic_priority", approach.edge->style.trafficPriority);
122 if (!status.ok()) return status;
123 status = placements.trySetIntAttribute(row, "road_lane_direction", static_cast<int>(approach.direction));
124 if (!status.ok()) return status;
125 status = placements.trySetFloatAttribute(row, "road_distance", distance);
126 if (!status.ok()) return status;
127 status = placements.trySetVectorAttribute(row, "road_direction", dx, dy, dz);
128 if (!status.ok()) return status;
129 }
130 return Result<void>::success();
131}
132
133} // namespace eve::procgen::road::detail
float length
Definition CaveMesh.cpp:94
Stable, structured diagnostics shared by engine modules.
wgpu::PopErrorScopeStatus status
float distance
float f
float halfWidth
const RoadNode * node
RoadLaneDirection direction
float socketDistance
SplinePath spline
const RoadEdge * edge
float dz
float dy
float dx
const SquirrelValueOptions & options
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
const T & value() const &
Borrow the value from a const lvalue after checking success.
Definition Result.h:308
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Script-friendly collection of attributed 3D samples.
Definition PointSet.h:59
Result< void > trySetPointId(int index, std::uint64_t id)
Assign a unique non-zero point identity without mutating on failure.
Definition PointSet.cpp:294
int add(float x, float y, float z)
Definition PointSet.cpp:97
Result< void > trySetStringAttribute(int index, const std::string &name, const std::string &value)
Canonical checked string metadata write.
Definition PointSet.cpp:421
Result< void > trySetVectorAttribute(int index, const std::string &name, float x, float y, float z)
Canonical checked vector metadata write.
Definition PointSet.cpp:391
void setYaw(int index, float yaw)
Sets the yaw.
Definition PointSet.cpp:155
void setPointSeed(int index, uint32_t seed)
Sets the point seed.
Definition PointSet.cpp:281
void setNormal(int index, float x, float y, float z)
Sets the normal.
Definition PointSet.cpp:134
Result< void > trySetIntAttribute(int index, const std::string &name, std::int64_t value)
Canonical checked signed integer metadata write.
Definition PointSet.cpp:351
int getCount() const
Returns the count.
Definition PointSet.cpp:48
Result< void > trySetFloatAttribute(int index, const std::string &name, float value)
Canonical checked float metadata write.
Definition PointSet.cpp:331
Owning directed road graph with lane connectivity.
Definition RoadNetwork.h:19
const std::vector< RoadEdge > & edges() const noexcept
Edges.
const std::vector< RoadNode > & nodes() const noexcept
Nodes.
float junctionSocketDistanceForBake(const RoadNetwork &network, const RoadNode &node, const RoadEdge &edge, float pathLength)
Result< void > bakeTrafficControlPoints(PointSet &placements, const RoadNetwork &network, const RoadBakeOptions &options)
Result< SplinePath > edgeSplineForBake(const RoadEdge &edge)
Result< RoadProfile > makeRoadProfile(const RoadStyle &style, int lanesForward, int lanesBackward)
Build a mathematical road cross-section for the given lane counts.
RoadJunctionControl
Authoritative traffic-control policy applied to every approach of one junction node.
Definition RoadTypes.h:43
@ Signal
Every incoming approach is controlled by a traffic signal.
@ Stop
Every incoming approach receives a stop control.
@ Uncontrolled
Edge trafficPriority resolves right-of-way without a mandatory stop.
@ Yield
Lower-priority approaches yield; equal-priority approaches all yield.
RoadLaneDirection
Travel direction of a lane relative to the authored edge centerline.
Definition RoadTypes.h:79
@ Forward
Travels from RoadEdge::from to RoadEdge::to.
@ Backward
Travels from RoadEdge::to to RoadEdge::from.
std::uint64_t derivePointId(std::uint64_t namespaceId, std::uint64_t ordinal)
Deterministically derive a non-zero stable point identity.
Definition PointSet.cpp:469
uint32_t deriveSeed(uint32_t parent, const std::string &scope)
Stable label-based seed derivation; independent pipeline branches do not perturb each other.
Definition PointSet.cpp:459
Options for baking a road network into mesh + navigation overlays.
Definition RoadBake.h:43
Directed centerline edge with optional reverse lanes.
Definition RoadTypes.h:61
std::string id
Definition Widget.h:17