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