]> git.localhorst.tv Git - blank.git/blob - src/world/Block.hpp
glm backwards compatibility
[blank.git] / src / world / Block.hpp
1 #ifndef BLANK_WORLD_BLOCK_HPP_
2 #define BLANK_WORLD_BLOCK_HPP_
3
4 #include "../graphics/glm.hpp"
5
6 #include <iosfwd>
7
8
9 namespace blank {
10
11 /// single 1x1x1 cube
12 struct Block {
13
14         using Type = unsigned short;
15
16         enum Face {
17                 FACE_UP,
18                 FACE_DOWN,
19                 FACE_RIGHT,
20                 FACE_LEFT,
21                 FACE_FRONT,
22                 FACE_BACK,
23                 FACE_COUNT,
24         };
25         enum Turn {
26                 TURN_NONE,
27                 TURN_LEFT,
28                 TURN_AROUND,
29                 TURN_RIGHT,
30                 TURN_COUNT,
31         };
32
33         static constexpr int ORIENT_COUNT = FACE_COUNT * TURN_COUNT;
34
35         Type type;
36         unsigned char orient;
37
38         constexpr explicit Block(Type type = 0, Face face = FACE_UP, Turn turn = TURN_NONE) noexcept
39         : type(type), orient(face * TURN_COUNT + turn) { }
40
41         const glm::mat4 &Transform() const noexcept { return orient2transform[orient]; }
42
43         Face GetFace() const noexcept { return Face(orient / TURN_COUNT); }
44         void SetFace(Face face) noexcept { orient = face * TURN_COUNT + GetTurn(); }
45         Turn GetTurn() const noexcept { return Turn(orient % TURN_COUNT); }
46         void SetTurn(Turn turn) noexcept { orient = GetFace() * TURN_COUNT + turn; }
47
48         Face OrientedFace(Face f) const noexcept { return orient2face[orient][f]; }
49
50         static Face Opposite(Face f) noexcept {
51                 return Face(f ^ 1);
52         }
53
54         static int Axis(Face f) noexcept {
55                 switch (f) {
56                         case FACE_UP:
57                         case FACE_DOWN:
58                                 return 1;
59                         default:
60                         case FACE_RIGHT:
61                         case FACE_LEFT:
62                                 return 0;
63                         case FACE_FRONT:
64                         case FACE_BACK:
65                                 return 2;
66                 }
67         }
68
69         /// returns 1 for pro-axis, -1 for retro-axis, 0 for invalid faces
70         static int Direction(Face f) noexcept {
71                 switch (f) {
72                         case FACE_RIGHT:
73                         case FACE_UP:
74                         case FACE_FRONT:
75                                 return 1;
76                         case FACE_LEFT:
77                         case FACE_DOWN:
78                         case FACE_BACK:
79                                 return -1;
80                         default:
81                                 return 0;
82                 }
83         }
84
85         static glm::ivec3 FaceNormal(Face face) noexcept {
86                 return face2normal[face];
87         }
88
89         static Face NormalFace(const glm::vec3 &norm) noexcept {
90                 const glm::vec3 anorm(glm::abs(norm));
91                 if (anorm.x > anorm.y) {
92                         if (anorm.x > anorm.z) {
93                                 return norm.x > 0.0f ? FACE_RIGHT : FACE_LEFT;
94                         } else {
95                                 return norm.z > 0.0f ? FACE_FRONT : FACE_BACK;
96                         }
97                 } else {
98                         if (anorm.y > anorm.z) {
99                                 return norm.y > 0.0f ? FACE_UP : FACE_DOWN;
100                         } else {
101                                 return norm.z > 0.0f ? FACE_FRONT : FACE_BACK;
102                         }
103                 }
104         }
105
106         struct FaceSet {
107
108                 explicit FaceSet(unsigned char v = 0)
109                 : value(v) { }
110
111                 bool IsSet(Face f) const {
112                         return value & Mask(f);
113                 }
114                 void Set(Face f) {
115                         value |= Mask(f);
116                 }
117                 void Unset(Face f) {
118                         value &= ~Mask(f);
119                 }
120
121                 void Clear() {
122                         value = 0;
123                 }
124                 void Fill() {
125                         value = Mask(FACE_COUNT) - 1;
126                 }
127
128                 bool Empty() const {
129                         return value == 0;
130                 }
131                 bool All() const {
132                         return value == Mask(FACE_COUNT) - 1;
133                 }
134
135                 unsigned char Mask(Face f) const {
136                         return 1 << f;
137                 }
138
139                 unsigned char value;
140
141         };
142
143 private:
144         static const glm::ivec3 face2normal[6];
145         static const glm::mat4 orient2transform[ORIENT_COUNT];
146         static const Face orient2face[ORIENT_COUNT][FACE_COUNT];
147
148 };
149
150 inline bool operator ==(const Block &a, const Block &b) {
151         return a.type == b.type && a.orient == b.orient;
152 }
153
154 inline bool operator !=(const Block &a, const Block &b) {
155         return !(a == b);
156 }
157
158 std::ostream &operator <<(std::ostream &, const Block &);
159 std::ostream &operator <<(std::ostream &, const Block::Face &);
160 std::ostream &operator <<(std::ostream &, const Block::Turn &);
161
162 }
163
164 #endif