TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
60 / 60
100.0%
Branches:
38 / 38
100.0%
Functions:
5 / 5
100.0%

noise/worley.h
Line Branch Exec Source
1 /// @file
2 /// @brief Worley cellular noise in 2D and 3D: feature-point distances and Voronoi cell values.
3 #pragma once
4
5 #include "terraingen/noise/hash.h"
6 #include "terraingen/noise/lattice.h"
7
8 namespace terraingen {
9
10 /// Distances from a point to its nearest and second-nearest feature points, and the random value
11 /// of the nearest point's Voronoi cell.
12 struct WorleyDistances {
13 float f1 = 0.0f; ///< Distance to the nearest feature point (F1), in lattice units.
14 float f2 = 0.0f; ///< Distance to the second-nearest feature point (F2), in lattice units.
15 float value = 0.0f; ///< Value of the nearest point's cell, uniform in [-1, 1).
16 };
17
18 namespace detail {
19
20 /// The squared gap along one axis between a fraction `f` of the centre cell and the cell `d`
21 /// cells away.
22 5775630 inline float CellGapSquared(int32_t d, float f) {
23 5775630 float gap = 0.0f;
24
2/2
✓ Branch 0 taken 2416335 times.
✓ Branch 1 taken 3359295 times.
5775630 if (d > 0) {
25 2416335 gap = float(d) - f;
26
2/2
✓ Branch 0 taken 2416335 times.
✓ Branch 1 taken 942960 times.
3359295 } else if (d < 0) {
27 2416335 gap = f - float(d + 1);
28 }
29 5775630 return gap * gap;
30 }
31
32 } // namespace detail
33
34 /// Worley cellular distances at a lattice cell plus fraction, one feature point per cell,
35 /// searching the 5 x 5 cells around it: F1 and the cell value are exact, F2 exact but for rare
36 /// configurations.
37 /// @param fx Fraction in x, in [0, 1).
38 /// @param fy Fraction in y, in [0, 1).
39 /// @return F1 in [0, sqrt(2)] and F2 >= F1.
40 4110453 inline WorleyDistances Worley2(int32_t ix, int32_t iy, float fx, float fy, uint32_t seed) {
41 4110453 float d1 = 1e30f;
42 4110453 float d2 = 1e30f;
43 4110453 uint32_t nearest = 0u;
44
2/2
✓ Branch 0 taken 20552265 times.
✓ Branch 1 taken 4110453 times.
24662718 for (int32_t dy = -2; dy <= 2; ++dy) {
45
2/2
✓ Branch 0 taken 102761325 times.
✓ Branch 1 taken 20552265 times.
123313590 for (int32_t dx = -2; dx <= 2; ++dx) {
46 const UVec3 h =
47 102761325 Pcg3dHash(detail::SeededLatticeKey2(uint32_t(ix + dx), uint32_t(iy + dy), seed));
48 102761325 const float px = float(dx) + HashToUnitFloat(h.y) - fx;
49 102761325 const float py = float(dy) + HashToUnitFloat(h.z) - fy;
50 102761325 const float d = px * px + py * py;
51
2/2
✓ Branch 0 taken 25858586 times.
✓ Branch 1 taken 76902739 times.
102761325 if (d < d1) {
52 25858586 d2 = d1;
53 25858586 d1 = d;
54 25858586 nearest = h.x;
55
2/2
✓ Branch 0 taken 10874536 times.
✓ Branch 1 taken 66028203 times.
76902739 } else if (d < d2) {
56 10874536 d2 = d;
57 }
58 }
59 }
60 4110453 const WorleyDistances distances = {sqrt(d1), sqrt(d2), 2.0f * HashToUnitFloat(nearest) - 1.0f};
61 4110453 return distances;
62 }
63
64 /// Worley cellular distances at a point in lattice units.
65 /// @return F1 in [0, sqrt(2)] and F2 >= F1.
66 4110453 inline WorleyDistances Worley2(float x, float y, uint32_t seed) {
67 4110453 const LatticePoint2 point = SplitLattice2(x, y);
68 4110453 return Worley2(point.ix, point.iy, point.fx, point.fy, seed);
69 }
70
71 /// Worley cellular distances in 3D, one feature point per cell: the 3 x 3 x 3 cells around the
72 /// point, then the outer shell of the 5 x 5 x 5 cells where a cell could still be nearer than F2.
73 /// F1 and the cell value are exact, F2 exact but for rare configurations.
74 /// @return F1 in [0, sqrt(3)] and F2 >= F1.
75 19645 inline WorleyDistances Worley3(LatticePoint3 point, uint32_t seed) {
76 19645 const uint32_t seedKey = PcgHash(seed);
77 19645 float d1 = 1e30f;
78 19645 float d2 = 1e30f;
79 19645 uint32_t nearest = 0u;
80
2/2
✓ Branch 0 taken 39290 times.
✓ Branch 1 taken 19645 times.
58935 for (int32_t shell = 0; shell < 2; ++shell) {
81
2/2
✓ Branch 0 taken 196450 times.
✓ Branch 1 taken 39290 times.
235740 for (int32_t dz = -2; dz <= 2; ++dz) {
82
2/2
✓ Branch 0 taken 982250 times.
✓ Branch 1 taken 196450 times.
1178700 for (int32_t dy = -2; dy <= 2; ++dy) {
83
2/2
✓ Branch 0 taken 4911250 times.
✓ Branch 1 taken 982250 times.
5893500 for (int32_t dx = -2; dx <= 2; ++dx) {
84
6/6
✓ Branch 0 taken 2946750 times.
✓ Branch 1 taken 1964500 times.
✓ Branch 2 taken 1768050 times.
✓ Branch 3 taken 1178700 times.
✓ Branch 4 taken 1060830 times.
✓ Branch 5 taken 707220 times.
4911250 const bool inner = abs(dx) <= 1 && abs(dy) <= 1 && abs(dz) <= 1;
85
2/2
✓ Branch 0 taken 2455625 times.
✓ Branch 1 taken 2455625 times.
4911250 if (inner != (shell == 0)) {
86 4380647 continue;
87 }
88
4/4
✓ Branch 0 taken 1925210 times.
✓ Branch 1 taken 530415 times.
✓ Branch 3 taken 1925022 times.
✓ Branch 4 taken 530603 times.
4380835 if (shell == 1 && detail::CellGapSquared(dx, point.fx) +
89
2/2
✓ Branch 1 taken 1925022 times.
✓ Branch 2 taken 188 times.
3850420 detail::CellGapSquared(dy, point.fy) +
90 1925210 detail::CellGapSquared(dz, point.fz) >=
91 d2) {
92 1925022 continue;
93 }
94 530603 const UVec3 h = Pcg3dHash(detail::CellularLatticeKey3(
95 530603 uint32_t(point.ix + dx), uint32_t(point.iy + dy), uint32_t(point.iz + dz),
96 seedKey));
97 530603 const float px = float(dx) + HashToUnitFloat(h.x) - point.fx;
98 530603 const float py = float(dy) + HashToUnitFloat(h.y) - point.fy;
99 530603 const float pz = float(dz) + HashToUnitFloat(h.z) - point.fz;
100 530603 const float d = px * px + py * py + pz * pz;
101
2/2
✓ Branch 0 taken 96606 times.
✓ Branch 1 taken 433997 times.
530603 if (d < d1) {
102 96606 d2 = d1;
103 96606 d1 = d;
104 96606 nearest = PcgHash(h.x ^ h.y ^ h.z);
105
2/2
✓ Branch 0 taken 55895 times.
✓ Branch 1 taken 378102 times.
433997 } else if (d < d2) {
106 55895 d2 = d;
107 }
108 }
109 }
110 }
111 }
112 19645 const WorleyDistances distances = {sqrt(d1), sqrt(d2), 2.0f * HashToUnitFloat(nearest) - 1.0f};
113 19645 return distances;
114 }
115
116 /// Worley cellular distances in 3D at a point in lattice units.
117 /// @return F1 in [0, sqrt(3)] and F2 >= F1.
118 7400 inline WorleyDistances Worley3(float x, float y, float z, uint32_t seed) {
119 7400 return Worley3(SplitLattice3(x, y, z), seed);
120 }
121
122 } // namespace terraingen
123