载入中...
搜索中...
未找到
HexRoadMesh.cpp
浏览该文件的文档.
1#include "hexmap/HexMapMesh.h"
2
3#include "hexmap/HexCell.h"
5#include "hexmap/HexMetrics.h"
6#include "hexmap/HexNoise.h"
7
8#include <cmath>
9#include <cstdint>
10
11namespace eve::hexmap {
12namespace {
13
15struct SurfaceVertex {
16 HexVec3 position;
17 float u = 0.f;
18 float v = 0.f;
19};
20
27[[nodiscard]] bool isDegenerate(HexVec3 a, HexVec3 b, HexVec3 c) noexcept {
28 const HexVec3 ab = b - a;
29 const HexVec3 ac = c - a;
30 const HexVec3 normal{ab.y * ac.z - ab.z * ac.y, ab.z * ac.x - ab.x * ac.z, ab.x * ac.y - ab.y * ac.x};
31 return (normal.x * normal.x + normal.y * normal.y + normal.z * normal.z) <= 1e-8f;
32}
33
43void emitTriangle(HexMeshData& out, const SurfaceVertex& a, const SurfaceVertex& b, const SurfaceVertex& c,
44 const HexNoise& noise) {
45 const HexVec3 pa = noise.perturb(a.position);
46 const HexVec3 pb = noise.perturb(b.position);
47 const HexVec3 pc = noise.perturb(c.position);
48 if (isDegenerate(pa, pb, pc)) return;
49 out.addTriangle(out.addVertex(pa, a.u, a.v), out.addVertex(pb, b.u, b.v), out.addVertex(pc, c.u, c.v));
50}
51
58void emitQuad(HexMeshData& out, const SurfaceVertex& r0, const SurfaceVertex& r1, const SurfaceVertex& r2,
59 const SurfaceVertex& r3, const HexNoise& noise) {
60 emitTriangle(out, r0, r3, r1, noise);
61 emitTriangle(out, r1, r3, r2, noise);
62}
63
65[[nodiscard]] HexVec3 acrossDirection(HexVec3 forward) noexcept {
66 const float length = std::sqrt(forward.x * forward.x + forward.z * forward.z);
67 if (length <= 1e-6f) return HexVec3{0.f, 0.f, 0.f};
68 return HexVec3{forward.z / length, 0.f, -forward.x / length};
69}
70
72struct StripStation {
73 HexVec3 position;
74 HexVec3 across;
75 float halfWidth = 0.f;
76 float u = 0.f;
77};
78
92void emitSegment(HexMeshData& out, const StripStation& from, const StripStation& to, const HexNoise& noise) {
93 const SurfaceVertex minus0{from.position - from.across * from.halfWidth, from.u, 0.f};
94 const SurfaceVertex plus0{from.position + from.across * from.halfWidth, from.u, 1.f};
95 const SurfaceVertex plus1{to.position + to.across * to.halfWidth, to.u, 1.f};
96 const SurfaceVertex minus1{to.position - to.across * to.halfWidth, to.u, 0.f};
97 emitQuad(out, minus0, plus0, plus1, minus1, noise);
98}
99
100} // namespace
101
102void buildRoadMesh(const HexMap& map, std::int32_t chunkIndex, HexMeshData& out) {
103 out.clear();
104 if (chunkIndex < 0 || chunkIndex >= map.chunkCount()) {
105 out.finalize();
106 return;
107 }
108
109 const HexNoise& noise = map.noise();
111 // Lift the surface off the terrain so the two coplanar layers cannot z-fight.
112 constexpr float kRoadLift = 0.05f;
113
114 for (std::int32_t row = 0; row < HexMetrics::kChunkSizeZ; ++row) {
115 for (std::int32_t column = 0; column < HexMetrics::kChunkSizeX; ++column) {
116 const HexCoordinates coordinates = map.chunkCell(chunkIndex, column, row);
117 const HexCellData* data = map.cell(coordinates);
118 if (data == nullptr || !map.hasRoad(coordinates)) continue;
119
120 const HexVec3 start = map.cellPosition(coordinates);
121 const HexVec3 ground = map.cellGroundPosition(coordinates);
122
123 // Emit each edge once, from the chunk that owns that border.
124 for (std::int32_t i = 0; i <= static_cast<std::int32_t>(HexDirection::SE); ++i) {
125 const HexDirection direction = static_cast<HexDirection>(i);
126 if (!data->flags.hasRoad(direction)) continue;
127 HexCoordinates neighbour{};
128 if (!map.getNeighbor(coordinates, direction, neighbour)) continue;
129
130 const HexVec3 neighbourCentre = map.cellPosition(neighbour);
132 // The crossing sits halfway between the two surfaces so the ribbon bends with
133 // the slope instead of stepping at the border.
134 const HexVec3 crossing{ground.x + edgeMiddle.x, (start.y + neighbourCentre.y) * 0.5f,
135 ground.z + edgeMiddle.z};
136
137 const StripStation from{
138 {start.x, start.y + kRoadLift, start.z}, acrossDirection(crossing - start), halfWidth, 0.f};
139 const StripStation middle{{crossing.x, crossing.y + kRoadLift, crossing.z},
140 acrossDirection(neighbourCentre - start),
141 halfWidth,
142 0.5f};
143 const StripStation finish{{neighbourCentre.x, neighbourCentre.y + kRoadLift, neighbourCentre.z},
144 acrossDirection(neighbourCentre - crossing),
145 halfWidth,
146 1.f};
147 emitSegment(out, from, middle, noise);
148 emitSegment(out, middle, finish, noise);
149 }
150 }
151 }
152
153 out.finalize();
154}
155
156} // namespace eve::hexmap
Duration start
std::string from
float length
Definition CaveMesh.cpp:94
int column
float u
Definition Grass.cpp:233
std::uint32_t ab
std::uint32_t ac
Packed per-cell state records of the hex map.
Per-chunk mesh generation for every hex map surface.
CPU vertex/index container shared by the hex surface builders.
Pointy-top hex metrics, directions and vertex helpers.
Deterministic asset-free noise for hex perturbation and generation.
float v
HexVec3 across
std::int32_t c
HexCoordinates to
Cell the unit walks towards on this segment.
Definition HexUnits.cpp:64
std::array< float, 3 > position
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
Texture * normal
float halfWidth
RoadLaneDirection direction
An editable, chunked, pointy-top hex map.
Definition HexMap.h:72
std::int32_t chunkCount() const noexcept
Total number of chunks.
Definition HexMap.h:102
HexVec3 cellPosition(HexCoordinates coordinates) const noexcept
Cell centre including elevation and vertical perturbation.
Definition HexMap.cpp:170
const HexNoise & noise() const noexcept
Deterministic noise field shared by this map's mesh builders.
Definition HexMap.h:110
bool getNeighbor(HexCoordinates coordinates, HexDirection direction, HexCoordinates &out) const noexcept
Neighbour of coordinates in direction; false when it is off-grid.
Definition HexMap.cpp:87
const HexCellData * cell(HexCoordinates coordinates) const noexcept
Cell record, or null when outside the grid. @ownership Borrowed; the map owns the record....
Definition HexMap.cpp:79
HexVec3 cellGroundPosition(HexCoordinates coordinates) const noexcept
Cell centre at y = 0 (no elevation, no perturbation).
Definition HexMap.h:198
bool hasRoad(HexCoordinates c) const noexcept
Definition HexMap.cpp:336
HexCoordinates chunkCell(std::int32_t chunkIndex, std::int32_t column, std::int32_t row) const noexcept
Coordinates of the cell at (column, row) inside a chunk.
Definition HexMap.cpp:115
CPU-side triangle soup for one hex chunk surface.
Definition HexMeshData.h:24
void finalize() noexcept
Computes flat per-face normals. Must be called before upload.
void clear() noexcept
Removes every vertex and index, keeping the allocated capacity.
static HexVec3 solidEdgeMiddle(HexDirection d) noexcept
Midpoint of the solid edge of direction.
Definition HexMetrics.h:206
static constexpr int kChunkSizeZ
Chunk size in the Z dimension.
Definition HexMetrics.h:158
static constexpr float innerRadius() noexcept
Inner radius of a hex cell.
Definition HexMetrics.h:176
static constexpr float kSolidFactor
Factor of the solid, uniform-colour hex inscribed in a cell.
Definition HexMetrics.h:130
static constexpr int kChunkSizeX
Chunk size in the X dimension.
Definition HexMetrics.h:156
Deterministic four-channel value noise over the XZ plane.
Definition HexNoise.h:23
std::vector< double > forward(const Policy &p, const Observation &o)
Forward.
Definition Learning.h:65
void buildRoadMesh(const HexMap &map, std::int32_t chunkIndex, HexMeshData &out)
Builds the road surface of one chunk.
HexDirection
Hex facing directions, counter-clockwise from north-east.
Definition HexMetrics.h:59
One cell of the hex map: packed values plus packed flags.
Definition HexCell.h:244
Axial coordinates of one hex cell.
Minimal 3-component float vector used by the hex mesh builders.
Definition HexMetrics.h:18