]> git.localhorst.tv Git - blank.git/blob - src/world/block.cpp
04209e1ac0ecb5bdf8b09baf537f56f88419f7f4
[blank.git] / src / world / block.cpp
1 #include "Block.hpp"
2 #include "BlockType.hpp"
3 #include "BlockTypeRegistry.hpp"
4
5 #include "../io/TokenStreamReader.hpp"
6 #include "../model/ShapeRegistry.hpp"
7 #include "../shared/ResourceIndex.hpp"
8
9 #include <iostream>
10 #include <glm/gtx/euler_angles.hpp>
11 #include <glm/gtx/transform.hpp>
12
13
14 namespace blank {
15
16 std::ostream &operator <<(std::ostream &out, const Block &block) {
17         return out << "Block(" << block.type << ", " << block.GetFace() << ", " << block.GetTurn() << ')';
18 }
19
20 std::ostream &operator <<(std::ostream &out, const Block::Face &face) {
21         switch (face) {
22                 case Block::FACE_UP:
23                         out << "FACE_UP";
24                         break;
25                 case Block::FACE_DOWN:
26                         out << "FACE_DOWN";
27                         break;
28                 case Block::FACE_RIGHT:
29                         out << "FACE_RIGHT";
30                         break;
31                 case Block::FACE_LEFT:
32                         out << "FACE_LEFT";
33                         break;
34                 case Block::FACE_FRONT:
35                         out << "FACE_FRONT";
36                         break;
37                 case Block::FACE_BACK:
38                         out << "FACE_BACK";
39                         break;
40                 default:
41                 case Block::FACE_COUNT:
42                         out << "invalid Block::Face";
43                         break;
44         }
45         return out;
46 }
47
48 std::ostream &operator <<(std::ostream &out, const Block::Turn &turn) {
49         switch (turn) {
50                 case Block::TURN_NONE:
51                         out << "TURN_NONE";
52                         break;
53                 case Block::TURN_LEFT:
54                         out << "TURN_LEFT";
55                         break;
56                 case Block::TURN_AROUND:
57                         out << "TURN_AROUND";
58                         break;
59                 case Block::TURN_RIGHT:
60                         out << "TURN_RIGHT";
61                         break;
62                 default:
63                 case Block::TURN_COUNT:
64                         out << "invalid Block::Turn";
65                         break;
66         }
67         return out;
68 }
69
70
71 BlockType::BlockType() noexcept
72 : shape(nullptr)
73 , textures()
74 , hsl_mod(0.0f, 1.0f, 1.0f)
75 , rgb_mod(1.0f, 1.0f, 1.0f)
76 , outline_color(-1, -1, -1)
77 , label("some block")
78 , place_sound(-1)
79 , remove_sound(-1)
80 , id(0)
81 , luminosity(0)
82 , visible(true)
83 , block_light(true)
84 , collision(true)
85 , collide_block(true)
86 , generate(false)
87 , min_solidity(0.5f)
88 , mid_solidity(0.75f)
89 , max_solidity(1.0f)
90 , min_humidity(-1.0f)
91 , mid_humidity(0.0f)
92 , max_humidity(1.0f)
93 , min_temperature(-1.0f)
94 , mid_temperature(0.0f)
95 , max_temperature(1.0f)
96 , min_richness(-1.0f)
97 , mid_richness(0.0f)
98 , max_richness(1.0f)
99 , commonness(1.0f) {
100
101 }
102
103 void BlockType::Read(
104         TokenStreamReader &in,
105         ResourceIndex &snd_index,
106         ResourceIndex &tex_index,
107         const ShapeRegistry &shapes
108 ) {
109         std::string name;
110         in.Skip(Token::ANGLE_BRACKET_OPEN);
111         while (in.Peek().type != Token::ANGLE_BRACKET_CLOSE) {
112                 in.ReadIdentifier(name);
113                 in.Skip(Token::EQUALS);
114                 if (name == "visible") {
115                         visible = in.GetBool();
116                 } else if (name == "texture") {
117                         in.ReadString(name);
118                         textures.push_back(tex_index.GetID(name));
119                 } else if (name == "textures") {
120                         in.Skip(Token::BRACKET_OPEN);
121                         while (in.Peek().type != Token::BRACKET_CLOSE) {
122                                 in.ReadString(name);
123                                 textures.push_back(tex_index.GetID(name));
124                                 if (in.Peek().type == Token::COMMA) {
125                                         in.Skip(Token::COMMA);
126                                 }
127                         }
128                         in.Skip(Token::BRACKET_CLOSE);
129                 } else if (name == "rgb_mod") {
130                         in.ReadVec(rgb_mod);
131                 } else if (name == "hsl_mod") {
132                         in.ReadVec(hsl_mod);
133                 } else if (name == "outline") {
134                         in.ReadVec(outline_color);
135                 } else if (name == "label") {
136                         in.ReadString(label);
137                 } else if (name == "place_sound") {
138                         in.ReadString(name);
139                         place_sound = snd_index.GetID(name);
140                 } else if (name == "remove_sound") {
141                         in.ReadString(name);
142                         remove_sound = snd_index.GetID(name);
143                 } else if (name == "luminosity") {
144                         luminosity = in.GetInt();
145                 } else if (name == "block_light") {
146                         block_light = in.GetBool();
147                 } else if (name == "collision") {
148                         collision = in.GetBool();
149                 } else if (name == "collide_block") {
150                         collide_block = in.GetBool();
151                 } else if (name == "generate") {
152                         generate = in.GetBool();
153                 } else if (name == "min_solidity") {
154                         min_solidity = in.GetFloat();
155                 } else if (name == "mid_solidity") {
156                         mid_solidity = in.GetFloat();
157                 } else if (name == "max_solidity") {
158                         max_solidity = in.GetFloat();
159                 } else if (name == "min_humidity") {
160                         min_humidity = in.GetFloat();
161                 } else if (name == "mid_humidity") {
162                         mid_humidity = in.GetFloat();
163                 } else if (name == "max_humidity") {
164                         max_humidity = in.GetFloat();
165                 } else if (name == "min_temperature") {
166                         min_temperature = in.GetFloat();
167                 } else if (name == "mid_temperature") {
168                         mid_temperature = in.GetFloat();
169                 } else if (name == "max_temperature") {
170                         max_temperature = in.GetFloat();
171                 } else if (name == "min_richness") {
172                         min_richness = in.GetFloat();
173                 } else if (name == "mid_richness") {
174                         mid_richness = in.GetFloat();
175                 } else if (name == "max_richness") {
176                         max_richness = in.GetFloat();
177                 } else if (name == "commonness") {
178                         commonness = in.GetFloat();
179                 } else if (name == "shape") {
180                         in.ReadIdentifier(name);
181                         shape = &shapes.Get(name);
182                 } else {
183                         std::cerr << "warning: unknown block type property " << name << std::endl;
184                         while (in.Peek().type != Token::SEMICOLON) {
185                                 in.Next();
186                         }
187                 }
188                 in.Skip(Token::SEMICOLON);
189         }
190         in.Skip(Token::ANGLE_BRACKET_CLOSE);
191 }
192
193 void BlockType::FillEntityMesh(
194         EntityMesh::Buffer &buf,
195         const glm::mat4 &transform
196 ) const noexcept {
197         if (!shape) return;
198         shape->Fill(buf, transform, textures);
199         buf.hsl_mods.insert(buf.hsl_mods.end(), shape->VertexCount(), hsl_mod);
200         buf.rgb_mods.insert(buf.rgb_mods.end(), shape->VertexCount(), rgb_mod);
201 }
202
203 void BlockType::FillBlockMesh(
204         BlockMesh::Buffer &buf,
205         const glm::mat4 &transform,
206         BlockMesh::Index idx_offset
207 ) const noexcept {
208         if (!shape) return;
209         shape->Fill(buf, transform, textures, idx_offset);
210         buf.hsl_mods.insert(buf.hsl_mods.end(), shape->VertexCount(), hsl_mod);
211         buf.rgb_mods.insert(buf.rgb_mods.end(), shape->VertexCount(), rgb_mod);
212 }
213
214 void BlockType::OutlinePrimitiveMesh(PrimitiveMesh::Buffer &buf) const noexcept {
215         if (!shape) return;
216         shape->Outline(buf);
217         buf.colors.insert(buf.colors.end(), shape->OutlineCount(), glm::vec4(outline_color, 1.0f));
218 }
219
220
221 BlockTypeRegistry::BlockTypeRegistry() {
222         BlockType air;
223         air.visible = false;
224         air.block_light = false;
225         air.collision = false;
226         air.collide_block = false;
227         Add(air);
228 }
229
230 Block::Type BlockTypeRegistry::Add(const BlockType &t) {
231         int id = types.size();
232         types.push_back(t);
233         types.back().id = id;
234         return id;
235 }
236
237
238 const glm::mat4 Block::orient2transform[ORIENT_COUNT] = {
239         {  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,  1, }, // face: up,    turn: none
240         {  0,  0, -1,  0,  0,  1,  0,  0,  1,  0,  0,  0,  0,  0,  0,  1, }, // face: up,    turn: left
241         { -1,  0,  0,  0,  0,  1,  0,  0,  0,  0, -1,  0,  0,  0,  0,  1, }, // face: up,    turn: around
242         {  0,  0,  1,  0,  0,  1,  0,  0, -1,  0,  0,  0,  0,  0,  0,  1, }, // face: up,    turn: right
243         {  1,  0,  0,  0,  0, -1,  0,  0,  0,  0, -1,  0,  0,  0,  0,  1, }, // face: down,  turn: none
244         {  0,  0, -1,  0,  0, -1,  0,  0, -1,  0,  0,  0,  0,  0,  0,  1, }, // face: down,  turn: left
245         { -1,  0,  0,  0,  0, -1,  0,  0,  0,  0,  1,  0,  0,  0,  0,  1, }, // face: down,  turn: around
246         {  0,  0,  1,  0,  0, -1,  0,  0,  1,  0,  0,  0,  0,  0,  0,  1, }, // face: down,  turn: right
247         {  0, -1,  0,  0,  1,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  1, }, // face: right, turn: none
248         {  0, -1,  0,  0,  0,  0, -1,  0,  1,  0,  0,  0,  0,  0,  0,  1, }, // face: right, turn: left
249         {  0, -1,  0,  0, -1,  0,  0,  0,  0,  0, -1,  0,  0,  0,  0,  1, }, // face: right, turn: around
250         {  0, -1,  0,  0,  0,  0,  1,  0, -1,  0,  0,  0,  0,  0,  0,  1, }, // face: right, turn: right
251         {  0,  1,  0,  0, -1,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  1, }, // face: left,  turn: none
252         {  0,  1,  0,  0,  0,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  1, }, // face: left,  turn: left
253         {  0,  1,  0,  0,  1,  0,  0,  0,  0,  0, -1,  0,  0,  0,  0,  1, }, // face: left,  turn: around
254         {  0,  1,  0,  0,  0,  0, -1,  0, -1,  0,  0,  0,  0,  0,  0,  1, }, // face: left,  turn: right
255         {  1,  0,  0,  0,  0,  0,  1,  0,  0, -1,  0,  0,  0,  0,  0,  1, }, // face: front, turn: none
256         {  0,  0, -1,  0,  1,  0,  0,  0,  0, -1,  0,  0,  0,  0,  0,  1, }, // face: front, turn: left
257         { -1,  0,  0,  0,  0,  0, -1,  0,  0, -1,  0,  0,  0,  0,  0,  1, }, // face: front, turn: around
258         {  0,  0,  1,  0, -1,  0,  0,  0,  0, -1,  0,  0,  0,  0,  0,  1, }, // face: front, turn: right
259         {  1,  0,  0,  0,  0,  0, -1,  0,  0,  1,  0,  0,  0,  0,  0,  1, }, // face: back,  turn: none
260         {  0,  0, -1,  0, -1,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  1, }, // face: back,  turn: left
261         { -1,  0,  0,  0,  0,  0,  1,  0,  0,  1,  0,  0,  0,  0,  0,  1, }, // face: back,  turn: around
262         {  0,  0,  1,  0,  1,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  1, }, // face: back,  turn: right
263 };
264
265 const glm::ivec3 Block::face2normal[FACE_COUNT] = {
266         {  0,  1,  0 },
267         {  0, -1,  0 },
268         {  1,  0,  0 },
269         { -1,  0,  0 },
270         {  0,  0,  1 },
271         {  0,  0, -1 },
272 };
273
274 const Block::Face Block::orient2face[ORIENT_COUNT][FACE_COUNT] = {
275         { FACE_UP,    FACE_DOWN,  FACE_RIGHT, FACE_LEFT,  FACE_FRONT, FACE_BACK,  }, // face: up,    turn: none
276         { FACE_UP,    FACE_DOWN,  FACE_FRONT, FACE_BACK,  FACE_LEFT,  FACE_RIGHT, }, // face: up,    turn: left
277         { FACE_UP,    FACE_DOWN,  FACE_LEFT,  FACE_RIGHT, FACE_BACK,  FACE_FRONT, }, // face: up,    turn: around
278         { FACE_UP,    FACE_DOWN,  FACE_BACK,  FACE_FRONT, FACE_RIGHT, FACE_LEFT,  }, // face: up,    turn: right
279         { FACE_DOWN,  FACE_UP,    FACE_RIGHT, FACE_LEFT,  FACE_BACK,  FACE_FRONT, }, // face: down,  turn: none
280         { FACE_DOWN,  FACE_UP,    FACE_BACK,  FACE_FRONT, FACE_LEFT,  FACE_RIGHT, }, // face: down,  turn: left
281         { FACE_DOWN,  FACE_UP,    FACE_LEFT,  FACE_RIGHT, FACE_FRONT, FACE_BACK,  }, // face: down,  turn: around
282         { FACE_DOWN,  FACE_UP,    FACE_FRONT, FACE_BACK,  FACE_RIGHT, FACE_LEFT,  }, // face: down,  turn: right
283         { FACE_LEFT,  FACE_RIGHT, FACE_UP,    FACE_DOWN,  FACE_FRONT, FACE_BACK,  }, // face: right, turn: none
284         { FACE_LEFT,  FACE_RIGHT, FACE_FRONT, FACE_BACK,  FACE_DOWN,  FACE_UP,    }, // face: right, turn: left
285         { FACE_LEFT,  FACE_RIGHT, FACE_DOWN,  FACE_UP,    FACE_BACK,  FACE_FRONT, }, // face: right, turn: around
286         { FACE_LEFT,  FACE_RIGHT, FACE_BACK,  FACE_FRONT, FACE_UP,    FACE_DOWN,  }, // face: right, turn: right
287         { FACE_RIGHT, FACE_LEFT,  FACE_DOWN,  FACE_UP,    FACE_FRONT, FACE_BACK,  }, // face: left,  turn: none
288         { FACE_RIGHT, FACE_LEFT,  FACE_FRONT, FACE_BACK,  FACE_UP,    FACE_DOWN,  }, // face: left,  turn: left
289         { FACE_RIGHT, FACE_LEFT,  FACE_UP,    FACE_DOWN,  FACE_BACK,  FACE_FRONT, }, // face: left,  turn: around
290         { FACE_RIGHT, FACE_LEFT,  FACE_BACK,  FACE_FRONT, FACE_DOWN,  FACE_UP,    }, // face: left,  turn: right
291         { FACE_BACK,  FACE_FRONT, FACE_RIGHT, FACE_LEFT,  FACE_UP,    FACE_DOWN,  }, // face: front, turn: none
292         { FACE_BACK,  FACE_FRONT, FACE_UP,    FACE_DOWN,  FACE_LEFT,  FACE_RIGHT, }, // face: front, turn: left
293         { FACE_BACK,  FACE_FRONT, FACE_LEFT,  FACE_RIGHT, FACE_DOWN,  FACE_UP,    }, // face: front, turn: around
294         { FACE_BACK,  FACE_FRONT, FACE_DOWN,  FACE_UP,    FACE_RIGHT, FACE_LEFT,  }, // face: front, turn: right
295         { FACE_FRONT, FACE_BACK,  FACE_RIGHT, FACE_LEFT,  FACE_DOWN,  FACE_UP,    }, // face: back,  turn: none
296         { FACE_FRONT, FACE_BACK,  FACE_DOWN,  FACE_UP,    FACE_LEFT,  FACE_RIGHT, }, // face: back,  turn: left
297         { FACE_FRONT, FACE_BACK,  FACE_LEFT,  FACE_RIGHT, FACE_UP,    FACE_DOWN,  }, // face: back,  turn: around
298         { FACE_FRONT, FACE_BACK,  FACE_UP,    FACE_DOWN,  FACE_RIGHT, FACE_LEFT,  }, // face: back,  turn: right
299 };
300
301 }