]> git.localhorst.tv Git - blank.git/blob - src/geometry/Location.hpp
fix box/box normal
[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> constexpr typename Location<T>::CoarseScalar Location<T>::scale;
64 template<class T> constexpr typename Location<T>::FineScalar Location<T>::fscale;
65
66 template<class T>
67 inline Location<T> &Location<T>::Correct() noexcept {
68         while (block.x >= fscale) {
69                 block.x -= fscale;
70                 ++chunk.x;
71         }
72         while (block.x < 0) {
73                 block.x += fscale;
74                 --chunk.x;
75         }
76         while (block.y >= fscale) {
77                 block.y -= fscale;
78                 ++chunk.y;
79         }
80         while (block.y < 0) {
81                 block.y += fscale;
82                 --chunk.y;
83         }
84         while (block.z >= fscale) {
85                 block.z -= fscale;
86                 ++chunk.z;
87         }
88         while (block.z < 0) {
89                 block.z += fscale;
90                 --chunk.z;
91         }
92         return *this;
93 }
94
95 template<class T>
96 inline Location<T> &Location<T>::Sanitize() noexcept {
97         Coarse diff = Coarse(block) / Extent();
98         chunk += diff;
99         block -= diff * Extent();
100         // may leave negative coordinates in block
101         return Correct();
102 }
103
104 using ExactLocation = Location<float>;
105 using RoughLocation = Location<int>;
106
107 }
108
109 #endif