util/cube_faces.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /// @file | ||
| 2 | /// @brief The two cube layouts directions are gridded on: `CubeSphereCells`' faces and Gaskell's | ||
| 3 | /// ICQ faces. | ||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "terraingen/util/geometry.h" | ||
| 7 | |||
| 8 | #include <array> | ||
| 9 | #include <cstddef> | ||
| 10 | |||
| 11 | namespace terraingen::detail { | ||
| 12 | |||
| 13 | /// A cube face: its outward normal and the axes its first and second coordinates run along. | ||
| 14 | struct CubeFace { | ||
| 15 | Vec3d normal; | ||
| 16 | Vec3d u; | ||
| 17 | Vec3d v; | ||
| 18 | }; | ||
| 19 | |||
| 20 | /// The faces of `CubeSphereCells`: +x, -x, +y, -y, +z and -z, in order. | ||
| 21 | constexpr std::array<CubeFace, 6> kCubeFaces{{ | ||
| 22 | {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}, | ||
| 23 | {{-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}}, | ||
| 24 | {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}}, | ||
| 25 | {{0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, 1.0}}, | ||
| 26 | {{0.0, 0.0, 1.0}, {0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}}, | ||
| 27 | {{0.0, 0.0, -1.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0}}, | ||
| 28 | }}; | ||
| 29 | |||
| 30 | /// Gaskell's ICQ faces 1 to 6, centred on +z, -y, -x, +y, +x and -z, with `u` the direction I runs | ||
| 31 | /// along and `v` the direction J runs along; measured from his published models. | ||
| 32 | constexpr std::array<CubeFace, 6> kIcqFaces{{ | ||
| 33 | {{0.0, 0.0, 1.0}, {1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}}, | ||
| 34 | {{0.0, -1.0, 0.0}, {1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}}, | ||
| 35 | {{-1.0, 0.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, -1.0}}, | ||
| 36 | {{0.0, 1.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 0.0, -1.0}}, | ||
| 37 | {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, -1.0}}, | ||
| 38 | {{0.0, 0.0, -1.0}, {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}}, | ||
| 39 | }}; | ||
| 40 | |||
| 41 | /// The point `normal + a u + b v` on the plane of `face`, for gnomonic coordinates `a` and `b`. | ||
| 42 | 6013547 | inline Vec3d CubeFacePoint(const CubeFace& face, double a, double b) { | |
| 43 | 6013547 | return {face.normal.x + a * face.u.x + b * face.v.x, | |
| 44 | 6013547 | face.normal.y + a * face.u.y + b * face.v.y, | |
| 45 | 6013547 | face.normal.z + a * face.u.z + b * face.v.z}; | |
| 46 | } | ||
| 47 | |||
| 48 | /// The index in `faces` of the face a nonzero `direction` points through: the one whose normal it | ||
| 49 | /// is closest to, the first such face on ties. | ||
| 50 | 8124192 | inline std::size_t CubeFaceOf(const std::array<CubeFace, 6>& faces, const Vec3d& direction) { | |
| 51 | 8124192 | std::size_t face = 0; | |
| 52 | 8124192 | double best = -2.0; | |
| 53 | 113738688 | for (std::size_t f = 0; f < faces.size(); ++f) { | |
| 54 | 48745152 | const double along = Dot(direction, faces[f].normal); | |
| 55 | 48745152 | if (along > best) { | |
| 56 | 20154247 | best = along; | |
| 57 | 20154247 | face = f; | |
| 58 | } | ||
| 59 | } | ||
| 60 | 8124192 | return face; | |
| 61 | } | ||
| 62 | |||
| 63 | } // namespace terraingen::detail | ||
| 64 |