]> git.localhorst.tv Git - blank.git/blob - src/world/Block.hpp
5f52d173882903af05a8346561842d0f77006f52
[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         using Pos = glm::vec3;
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         static glm::ivec3 FaceNormal(Face face) noexcept {
70                 return face2normal[face];
71         }
72
73         static Face NormalFace(const glm::vec3 &norm) noexcept {
74                 const glm::vec3 anorm(abs(norm));
75                 if (anorm.x > anorm.y) {
76                         if (anorm.x > anorm.z) {
77                                 return norm.x > 0.0f ? FACE_RIGHT : FACE_LEFT;
78                         } else {
79                                 return norm.z > 0.0f ? FACE_FRONT : FACE_BACK;
80                         }
81                 } else {
82                         if (anorm.y > anorm.z) {
83                                 return norm.y > 0.0f ? FACE_UP : FACE_DOWN;
84                         } else {
85                                 return norm.z > 0.0f ? FACE_FRONT : FACE_BACK;
86                         }
87                 }
88         }
89
90         struct FaceSet {
91
92                 explicit FaceSet(unsigned char v = 0)
93                 : value(v) { }
94
95                 bool IsSet(Face f) const {
96                         return value & Mask(f);
97                 }
98                 void Set(Face f) {
99                         value |= Mask(f);
100                 }
101                 void Unset(Face f) {
102                         value &= ~Mask(f);
103                 }
104
105                 void Clear() {
106                         value = 0;
107                 }
108                 void Fill() {
109                         value = Mask(FACE_COUNT) - 1;
110                 }
111
112                 bool Empty() const {
113                         return value == 0;
114                 }
115                 bool All() const {
116                         return value == Mask(FACE_COUNT) - 1;
117                 }
118
119                 unsigned char Mask(Face f) const {
120                         return 1 << f;
121                 }
122
123                 unsigned char value;
124
125         };
126
127 private:
128         static const glm::ivec3 face2normal[6];
129         static const glm::mat4 orient2transform[ORIENT_COUNT];
130         static const Face orient2face[ORIENT_COUNT][FACE_COUNT];
131
132 };
133
134 inline bool operator ==(const Block &a, const Block &b) {
135         return a.type == b.type && a.orient == b.orient;
136 }
137
138 inline bool operator !=(const Block &a, const Block &b) {
139         return !(a == b);
140 }
141
142 std::ostream &operator <<(std::ostream &, const Block &);
143 std::ostream &operator <<(std::ostream &, const Block::Face &);
144 std::ostream &operator <<(std::ostream &, const Block::Turn &);
145
146 }
147
148 #endif