layers/craters/rays.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "terraingen/layers/craters/rays.h" | ||
| 2 | |||
| 3 | #include "terraingen/random/stream.h" | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <cmath> | ||
| 7 | #include <numbers> | ||
| 8 | #include <stdexcept> | ||
| 9 | |||
| 10 | namespace terraingen { | ||
| 11 | |||
| 12 | namespace { | ||
| 13 | |||
| 14 | constexpr std::uint32_t kRayStream = 0x52415953u; | ||
| 15 | |||
| 16 | } // namespace | ||
| 17 | |||
| 18 | 71 | void ValidateRayLayout(const RayLayout& layout) { | |
| 19 | 71 | ValidateValueDistribution(layout.count); | |
| 20 | 71 | ValidateValueDistribution(layout.widthDegrees); | |
| 21 | 71 | if (layout.count.Lowest() < 0.0 || layout.count.Highest() > 64.0) { | |
| 22 | 2 | throw std::invalid_argument("Craters must have 0 to 64 rays"); | |
| 23 | } | ||
| 24 | 69 | if (!(layout.widthDegrees.Lowest() > 0.0 && layout.widthDegrees.Highest() < 180.0)) { | |
| 25 | 3 | throw std::invalid_argument("Ray widths must be in (0, 180) degrees"); | |
| 26 | } | ||
| 27 | 66 | } | |
| 28 | |||
| 29 | 1766 | std::vector<RayDirection> RayDirections(const Crater& crater, const RayLayout& layout) { | |
| 30 | 1766 | const IdWords id = SplitId(crater.id); | |
| 31 | 1766 | RandomStream random(layout.seed, kRayStream, id.low, id.high); | |
| 32 | 1766 | const double c1 = random.NextDouble(); | |
| 33 | 1766 | const double c2 = random.NextDouble(); | |
| 34 | 1766 | const auto count = static_cast<int>(std::lround(layout.count.Sample(c1, c2))); | |
| 35 | 1766 | std::vector<RayDirection> rays; | |
| 36 | 1766 | rays.reserve(static_cast<std::size_t>(std::max(count, 0))); | |
| 37 | 18984 | for (int i = 0; i < count; ++i) { | |
| 38 | 17218 | RayDirection ray; | |
| 39 | 17218 | ray.azimuth = 2.0 * std::numbers::pi * random.NextDouble(); | |
| 40 | 17218 | const double w1 = random.NextDouble(); | |
| 41 | 17218 | const double w2 = random.NextDouble(); | |
| 42 | 17218 | ray.sinHalfWidth = | |
| 43 | 17218 | std::sin(0.5 * layout.widthDegrees.Sample(w1, w2) * std::numbers::pi / 180.0); | |
| 44 | 17218 | ray.key = random.NextU32(); | |
| 45 | 17218 | rays.push_back(ray); | |
| 46 | } | ||
| 47 | 3532 | return rays; | |
| 48 | } | ||
| 49 | |||
| 50 | } // namespace terraingen | ||
| 51 |