layers/boulders/boulder.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /// @file | ||
| 2 | /// @brief `Boulder`, the record of one placed boulder. | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #include "terraingen/util/geometry.h" | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <cmath> | ||
| 9 | #include <cstdint> | ||
| 10 | #include <optional> | ||
| 11 | |||
| 12 | namespace terraingen { | ||
| 13 | |||
| 14 | /// Which of its axes a boulder stands on end along, the one turned to the vertical. | ||
| 15 | enum class BoulderRest : std::uint8_t { | ||
| 16 | Face, ///< On its broadest face: its short axis up. | ||
| 17 | Side, ///< On a side: its intermediate axis up. | ||
| 18 | End, ///< On an end: its long axis up. | ||
| 19 | }; | ||
| 20 | |||
| 21 | /// A plane that sand-laden wind has cut across a boulder's windward side: a ventifact facet. | ||
| 22 | /// Rock above the plane is gone. | ||
| 23 | struct BoulderFacet { | ||
| 24 | /// Direction the facet faces (upwind), radians counter-clockwise from east. | ||
| 25 | 9642 | double azimuth = 0.0; | |
| 26 | 9642 | double angle = 0.0; ///< Slope of the facet from horizontal, radians, in (0, 90) deg. | |
| 27 | /// Distance (m) toward `azimuth` from the boulder's centre at which the facet meets the surface | ||
| 28 | /// the boulder stands on. | ||
| 29 | 9642 | double reach = 0.0; | |
| 30 | |||
| 31 | /// The facet's height (m) above that surface at east and north `offset` metres from the | ||
| 32 | /// boulder's centre, negative beyond `reach`. | ||
| 33 | 70136 | double HeightAt(const Vec2d& offset) const { | |
| 34 | 70136 | const double along = offset.x * std::cos(azimuth) + offset.y * std::sin(azimuth); | |
| 35 | 70136 | return (reach - along) * std::tan(angle); | |
| 36 | } | ||
| 37 | |||
| 38 | 9642 | bool operator==(const BoulderFacet&) const = default; | |
| 39 | }; | ||
| 40 | |||
| 41 | /// One boulder: where it stands, how large it is and how it lies, in surface coordinates | ||
| 42 | /// and metres. | ||
| 43 | struct Boulder { | ||
| 44 | 4821 | double x = 0.0; ///< Surface x of its centre. | |
| 45 | 4821 | double y = 0.0; ///< Surface y of its centre. | |
| 46 | 4821 | double diameter = 0.0; ///< Length of its long axis: its largest horizontal extent on its face. | |
| 47 | /// Length of its short axis, buried part included: its full height resting on its face. | ||
| 48 | 4821 | double height = 0.0; | |
| 49 | 4821 | double burial = 0.0; ///< Share of its vertical extent below the surface, in [0, 1). | |
| 50 | 4821 | double yaw = 0.0; ///< Rotation about the vertical, radians counter-clockwise from east. | |
| 51 | 4821 | double lean = 0.0; ///< Tilt of the boulder's vertical axis from the vertical, radians. | |
| 52 | 4821 | std::uint64_t id = 0; ///< Stable ID, keyed like crater IDs. | |
| 53 | 4821 | BoulderRest rest = BoulderRest::Face; ///< Which axis it stands along. | |
| 54 | 4821 | double tilt = 0.0; ///< Angle of its up axis from the vertical, after lean, radians. | |
| 55 | 4821 | double tiltAzimuth = 0.0; ///< Direction its up axis tips toward, radians from east. | |
| 56 | /// Height of the ground beneath its centre before any boulders, when the layer knows it. | ||
| 57 | 4821 | std::optional<double> ground{}; | |
| 58 | /// Placed as a 3D model of its own rather than drawn into the heights | ||
| 59 | /// (`BoulderModelThreshold`). | ||
| 60 | 4821 | bool model = false; | |
| 61 | /// How worn it is, from 0 (fresh) to 1: its crater's wear for a crater block, uniform between | ||
| 62 | /// craters. | ||
| 63 | 4821 | double wear = 0.0; | |
| 64 | /// For a fragment, the ID of the boulder it broke from; 0 for a whole boulder. | ||
| 65 | 4821 | std::uint64_t parent = 0; | |
| 66 | 4821 | std::uint32_t piece = 0; ///< For a fragment, which piece of its parent it is. | |
| 67 | /// Its ventifact facets, the first `facetCount` of them (`BoulderVentifacts`). | ||
| 68 | 4821 | std::array<BoulderFacet, 2> facets{}; | |
| 69 | 4821 | std::uint8_t facetCount = 0; ///< How many facets it has, 0 to 2. | |
| 70 | |||
| 71 | /// Height of the top above the surface it stands on, `height` (1 - `burial`), in metres. | ||
| 72 | 556812 | double ExposedHeight() const { | |
| 73 | 556812 | return height * (1.0 - burial); | |
| 74 | } | ||
| 75 | |||
| 76 | /// `top`, a height (m) of the boulder above the surface at east and north `offset` metres from | ||
| 77 | /// its centre, lowered to its facets and not below 0. | ||
| 78 | 526524 | double CutByFacets(const Vec2d& offset, double top) const { | |
| 79 | 526546 | for (std::uint8_t k = 0; k < facetCount; ++k) { | |
| 80 | 22 | top = std::fmin(top, facets[k].HeightAt(offset)); | |
| 81 | } | ||
| 82 | 526524 | return std::fmax(top, 0.0); | |
| 83 | } | ||
| 84 | |||
| 85 | 4821 | bool operator==(const Boulder&) const = default; | |
| 86 | }; | ||
| 87 | |||
| 88 | } // namespace terraingen | ||
| 89 |