]> git.localhorst.tv Git - blank.git/blob - src/world/Block.hpp
74af3e4ab4bbf025e342674e6bc7eff986bf2d7a
[blank.git] / src / world / Block.hpp
1 #ifndef BLANK_WORLD_BLOCK_HPP_
2 #define BLANK_WORLD_BLOCK_HPP_
3
4 #include <glm/glm.hpp>
5
6
7 namespace blank {
8
9 /// single 1x1x1 cube
10 struct Block {
11
12         using Type = unsigned short;
13         using Pos = glm::vec3;
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         static glm::tvec3<int> FaceNormal(Face face) noexcept {
69                 return face2normal[face];
70         }
71
72         static Face NormalFace(const glm::vec3 &norm) noexcept {
73                 const glm::vec3 anorm(abs(norm));
74                 if (anorm.x > anorm.y) {
75                         if (anorm.x > anorm.z) {
76                                 return norm.x > 0.0f ? FACE_RIGHT : FACE_LEFT;
77                         } else {
78                                 return norm.z > 0.0f ? FACE_FRONT : FACE_BACK;
79                         }
80                 } else {
81                         if (anorm.y > anorm.z) {
82                                 return norm.y > 0.0f ? FACE_UP : FACE_DOWN;
83                         } else {
84                                 return norm.z > 0.0f ? FACE_FRONT : FACE_BACK;
85                         }
86                 }
87         }
88
89         struct FaceSet {
90
91                 explicit FaceSet(unsigned char v = 0)
92                 : value(v) { }
93
94                 bool IsSet(Face f) const {
95                         return value & Mask(f);
96                 }
97                 void Set(Face f) {
98                         value |= Mask(f);
99                 }
100                 void Unset(Face f) {
101                         value |= ~Mask(f);
102                 }
103
104                 void Clear() {
105                         value = 0;
106                 }
107                 void Fill() {
108                         value = Mask(FACE_COUNT) - 1;
109                 }
110
111                 bool Empty() const {
112                         return value == 0;
113                 }
114                 bool All() const {
115                         return value == Mask(FACE_COUNT) - 1;
116                 }
117
118                 unsigned char Mask(Face f) const {
119                         return 1 << f;
120                 }
121
122                 unsigned char value;
123
124         };
125
126 private:
127         static const glm::tvec3<int> face2normal[6];
128         static const glm::mat4 orient2transform[ORIENT_COUNT];
129         static const Face orient2face[ORIENT_COUNT][FACE_COUNT];
130
131 };
132
133 }
134
135 #endif