TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
65 / 65
100.0%
Branches:
53 / 56
94.6%
Functions:
2 / 2
100.0%

pipeline/body_mesh.cpp
Line Branch Exec Source
1 #include "terraingen/pipeline/body_mesh.h"
2
3 #include "terraingen/util/cells.h"
4 #include "terraingen/util/checks.h"
5
6 #include <numbers>
7 #include <stdexcept>
8 #include <vector>
9
10 namespace terraingen {
11
12 17 TriangleMesh BodyMesh(const Terrain& terrain, std::size_t cellsPerFace, double spacing,
13 unsigned threads) {
14
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 15 times.
17 if (!terrain.surface.IsBody()) {
15
1/1
✓ Branch 2 taken 2 times.
2 throw std::invalid_argument("A body mesh needs a terrain on a sphere");
16 }
17
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 14 times.
15 if (cellsPerFace == 0) {
18
1/1
✓ Branch 2 taken 1 time.
1 throw std::invalid_argument("A body mesh needs at least one cell per face");
19 }
20
1/1
✓ Branch 2 taken 13 times.
14 RequireNonNegative(spacing, "Sample spacing");
21 13 const double radius = terrain.surface.Radius();
22 13 const double quarter = std::numbers::pi / 4.0;
23 13 const double step = 2.0 * quarter / static_cast<double>(cellsPerFace);
24
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 12 times.
13 const double sampled = spacing > 0.0 ? spacing : radius * step;
25 13 const std::size_t side = cellsPerFace + 1;
26
1/1
✓ Branch 1 taken 13 times.
26 std::vector<Vec3d> directions(6 * side * side);
27
1/1
✓ Branch 2 taken 13 times.
13 std::vector<Vec2d> points(directions.size());
28
2/2
✓ Branch 1 taken 203982 times.
✓ Branch 2 taken 13 times.
203995 for (std::size_t v = 0; v < directions.size(); ++v) {
29 203982 const auto face = static_cast<int>(v / (side * side));
30 203982 const std::size_t i = v % side;
31 203982 const std::size_t j = (v / side) % side;
32 203982 directions[v] = CubeSphereCells::Direction(face, -quarter + static_cast<double>(i) * step,
33
1/1
✓ Branch 1 taken 203982 times.
203982 -quarter + static_cast<double>(j) * step);
34
1/1
✓ Branch 2 taken 203982 times.
203982 points[v] = terrain.surface.PointOf(directions[v]);
35 }
36
1/1
✓ Branch 2 taken 13 times.
13 const std::vector<float> heights = EvaluatePoints(terrain, points, sampled, threads);
37 13 TriangleMesh mesh;
38
1/1
✓ Branch 2 taken 13 times.
13 mesh.positions.resize(directions.size());
39
2/2
✓ Branch 1 taken 203982 times.
✓ Branch 2 taken 13 times.
203995 for (std::size_t v = 0; v < directions.size(); ++v) {
40
1/1
✓ Branch 2 taken 203982 times.
203982 const double r = terrain.surface.RadiusAt(points[v]) +
41
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 203982 times.
203982 (std::isnan(heights[v]) ? 0.0 : static_cast<double>(heights[v]));
42 203982 mesh.positions[v] = directions[v] * r;
43 }
44
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 13 times.
91 for (std::size_t face = 0; face < 6; ++face) {
45 78 const auto base = static_cast<std::uint32_t>(face * side * side);
46
2/2
✓ Branch 0 taken 2604 times.
✓ Branch 1 taken 78 times.
2682 for (std::size_t j = 0; j < cellsPerFace; ++j) {
47
2/2
✓ Branch 0 taken 198696 times.
✓ Branch 1 taken 2604 times.
201300 for (std::size_t i = 0; i < cellsPerFace; ++i) {
48 198696 const auto a = static_cast<std::uint32_t>(base + j * side + i);
49 198696 const auto b = a + 1u;
50 198696 const auto c = static_cast<std::uint32_t>(a + side);
51 198696 const auto d = c + 1u;
52
1/1
✓ Branch 1 taken 198696 times.
198696 mesh.triangles.push_back({a, b, d});
53
1/1
✓ Branch 1 taken 198696 times.
198696 mesh.triangles.push_back({a, d, c});
54 }
55 }
56 }
57 26 return mesh;
58 13 }
59
60 7 IcqModel BodyIcq(const Terrain& terrain, std::size_t q, double spacing, unsigned threads) {
61
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 6 times.
7 if (!terrain.surface.IsBody()) {
62
1/1
✓ Branch 2 taken 1 time.
1 throw std::invalid_argument("An ICQ model needs a terrain on a body");
63 }
64
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 5 times.
6 if (q == 0) {
65
1/1
✓ Branch 2 taken 1 time.
1 throw std::invalid_argument("An ICQ model needs Q > 0");
66 }
67
1/1
✓ Branch 2 taken 4 times.
5 RequireNonNegative(spacing, "Sample spacing");
68 const double sampled =
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 spacing > 0.0 ? spacing
70 4 : terrain.surface.Radius() * std::numbers::pi / 2.0 / static_cast<double>(q);
71 4 IcqModel model;
72 4 model.q = q;
73
1/1
✓ Branch 1 taken 4 times.
4 model.vertices.resize(6 * (q + 1) * (q + 1));
74
1/1
✓ Branch 2 taken 4 times.
8 std::vector<Vec3d> directions(model.vertices.size());
75
1/1
✓ Branch 2 taken 4 times.
4 std::vector<Vec2d> points(model.vertices.size());
76
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 4 times.
28 for (std::size_t face = 1; face <= 6; ++face) {
77
2/2
✓ Branch 0 taken 516 times.
✓ Branch 1 taken 24 times.
540 for (std::size_t j = 0; j <= q; ++j) {
78
2/2
✓ Branch 0 taken 26280 times.
✓ Branch 1 taken 516 times.
26796 for (std::size_t i = 0; i <= q; ++i) {
79 26280 const std::size_t k = model.Index(i, j, face);
80
1/1
✓ Branch 1 taken 26280 times.
26280 directions[k] = IcqDirection(q, i, j, face);
81
1/1
✓ Branch 2 taken 26280 times.
26280 points[k] = terrain.surface.PointOf(directions[k]);
82 }
83 }
84 }
85
1/1
✓ Branch 2 taken 4 times.
4 const std::vector<float> heights = EvaluatePoints(terrain, points, sampled, threads);
86
2/2
✓ Branch 1 taken 26280 times.
✓ Branch 2 taken 4 times.
26284 for (std::size_t k = 0; k < model.vertices.size(); ++k) {
87
1/1
✓ Branch 2 taken 26280 times.
26280 const double r = terrain.surface.RadiusAt(points[k]) +
88
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 26280 times.
26280 (std::isnan(heights[k]) ? 0.0 : static_cast<double>(heights[k]));
89 26280 model.vertices[k] = directions[k] * r;
90 }
91 8 return model;
92 4 }
93
94 } // namespace terraingen
95