]> git.localhorst.tv Git - blank.git/blob - src/geometry/Location.hpp
7dbff69a55bf9e3bceabbb827102868627708272
[blank.git] / src / geometry / Location.hpp
1 #ifndef BLANK_GEOMETRY_LOCATION_HPP_
2 #define BLANK_GEOMETRY_LOCATION_HPP_
3
4 #include <glm/glm.hpp>
5
6
7 namespace blank {
8
9 template<class T>
10 struct Location {
11
12         using Coarse = glm::ivec3;
13         using CoarseScalar = int;
14         using Fine = glm::tvec3<T>;
15         using FineScalar = T;
16         using Self = Location<T>;
17
18
19         Coarse chunk;
20         Fine block;
21
22
23         /// scale of coarse vs fine coordinates
24         static constexpr CoarseScalar scale = 16;
25         /// scale with same type as fine
26         static constexpr FineScalar fscale = scale;
27         /// scale in three dimensions
28         static Coarse Extent() noexcept { return Coarse(scale); }
29         /// extent with same type as fine
30         static Fine FExtent() noexcept { return Fine(fscale); }
31
32
33         Location() noexcept : chunk(CoarseScalar(0)), block(FineScalar(0)) { }
34         Location(const Coarse &c, const Fine &b) noexcept : chunk(c), block(b) { }
35
36         /// from absolute position
37         /// not sanitized
38         explicit Location(const Fine &b) noexcept : chunk(CoarseScalar(0)), block(b) { }
39
40         /// make sure fine coordinates are within [0,scale)
41         /// use this if block isn't too far out of range
42         Self &Correct() noexcept;
43         /// use this if block is way out of range
44         Self &Sanitize() noexcept;
45
46         /// resolve absolute position
47         Fine Absolute() const noexcept {
48                 return Fine(chunk * Extent()) + block;
49         }
50         /// get location relative to given coarse coordinates
51         Self Relative(const Coarse &reference) const noexcept {
52                 return Self(chunk - reference, block);
53         }
54         /// get difference between this and given location
55         /// (= this - given, points from given to this)
56         /// returned location is not sanitized
57         Self Difference(const Location &other) const noexcept {
58                 return Self(chunk - other.chunk, block - other.block);
59         }
60
61 };
62
63 template<class T>
64 inline Location<T> &Location<T>::Correct() noexcept {
65         while (block.x >= fscale) {
66                 block.x -= fscale;
67                 ++chunk.x;
68         }
69         while (block.x < 0) {
70                 block.x += fscale;
71                 --chunk.x;
72         }
73         while (block.y >= fscale) {
74                 block.y -= fscale;
75                 ++chunk.y;
76         }
77         while (block.y < 0) {
78                 block.y += fscale;
79                 --chunk.y;
80         }
81         while (block.z >= fscale) {
82                 block.z -= fscale;
83                 ++chunk.z;
84         }
85         while (block.z < 0) {
86                 block.z += fscale;
87                 --chunk.z;
88         }
89         return *this;
90 }
91
92 template<class T>
93 inline Location<T> &Location<T>::Sanitize() noexcept {
94         Coarse diff = Coarse(block) / Extent();
95         chunk += diff;
96         block -= diff * Extent();
97         // may leave negative coordinates in block
98         return Correct();
99 }
100
101 using ExactLocation = Location<float>;
102 using RoughLocation = Location<int>;
103
104 }
105
106 #endif