]> git.localhorst.tv Git - blank.git/blob - src/model/shape.cpp
merge common parts of pre- and unload states
[blank.git] / src / model / shape.cpp
1 #include "Shape.hpp"
2 #include "shapes.hpp"
3
4
5 namespace blank {
6
7 void Shape::Vertices(
8         EntityModel::Buffer &out,
9         float tex_offset
10 ) const {
11         for (const auto &pos : vtx_pos) {
12                 out.vertices.emplace_back(pos);
13         }
14         for (const auto &coord : vtx_tex_coords) {
15                 out.tex_coords.emplace_back(coord.x, coord.y, coord.z + tex_offset);
16         }
17         for (const auto &nrm : vtx_nrm) {
18                 out.normals.emplace_back(nrm);
19         }
20         for (auto idx : vtx_idx) {
21                 out.indices.emplace_back(idx);
22         }
23 }
24
25 void Shape::Vertices(
26         EntityModel::Buffer &out,
27         const glm::mat4 &transform,
28         float tex_offset,
29         EntityModel::Index idx_offset
30 ) const {
31         for (const auto &pos : vtx_pos) {
32                 out.vertices.emplace_back(transform * glm::vec4(pos, 1.0f));
33         }
34         for (const auto &coord : vtx_tex_coords) {
35                 out.tex_coords.emplace_back(coord.x, coord.y, coord.z + tex_offset);
36         }
37         for (const auto &nrm : vtx_nrm) {
38                 out.normals.emplace_back(transform * glm::vec4(nrm, 0.0f));
39         }
40         for (auto idx : vtx_idx) {
41                 out.indices.emplace_back(idx_offset + idx);
42         }
43 }
44
45 void Shape::Vertices(
46         BlockModel::Buffer &out,
47         const glm::mat4 &transform,
48         float tex_offset,
49         BlockModel::Index idx_offset
50 ) const {
51         for (const auto &pos : vtx_pos) {
52                 out.vertices.emplace_back(transform * glm::vec4(pos, 1.0f));
53         }
54         for (const auto &coord : vtx_tex_coords) {
55                 out.tex_coords.emplace_back(coord.x, coord.y, coord.z + tex_offset);
56         }
57         for (auto idx : vtx_idx) {
58                 out.indices.emplace_back(idx_offset + idx);
59         }
60 }
61
62 void Shape::Vertices(
63         SkyBoxModel::Buffer &out
64 ) const {
65         for (const auto &pos : vtx_pos) {
66                 out.vertices.emplace_back(pos);
67         }
68         for (auto idx : vtx_idx) {
69                 out.indices.emplace_back(idx);
70         }
71 }
72
73 void Shape::Outline(OutlineModel::Buffer &out) const {
74         out.vertices.insert(out.vertices.end(), out_pos.begin(), out_pos.end());
75         out.indices.insert(out.indices.end(), out_idx.begin(), out_idx.end());
76 }
77
78 void Shape::SetShape(
79         const EntityModel::Positions &pos,
80         const EntityModel::Normals &nrm,
81         const EntityModel::Indices &idx
82 ) {
83         vtx_pos = pos;
84         vtx_nrm = nrm;
85         vtx_idx = idx;
86 }
87
88 void Shape::SetTexture(
89         const BlockModel::TexCoords &tex_coords
90 ) {
91         vtx_tex_coords = tex_coords;
92 }
93
94 void Shape::SetOutline(
95         const OutlineModel::Positions &pos,
96         const OutlineModel::Indices &idx
97 ) {
98         out_pos = pos;
99         out_idx = idx;
100 }
101
102
103 NullShape::NullShape()
104 : Shape() {
105
106 }
107
108 bool NullShape::Intersects(
109         const Ray &,
110         const glm::mat4 &,
111         float &, glm::vec3 &
112 ) const noexcept {
113         return false;
114 }
115
116 bool NullShape::Intersects(
117         const glm::mat4 &,
118         const AABB &,
119         const glm::mat4 &,
120         float &,
121         glm::vec3 &
122 ) const noexcept {
123         return false;
124 }
125
126
127 CuboidShape::CuboidShape(const AABB &b)
128 : Shape()
129 , bb(b) {
130         bb.Adjust();
131         SetShape({
132                 { bb.min.x, bb.min.y, bb.max.z }, // front
133                 { bb.max.x, bb.min.y, bb.max.z },
134                 { bb.min.x, bb.max.y, bb.max.z },
135                 { bb.max.x, bb.max.y, bb.max.z },
136                 { bb.min.x, bb.min.y, bb.min.z }, // back
137                 { bb.min.x, bb.max.y, bb.min.z },
138                 { bb.max.x, bb.min.y, bb.min.z },
139                 { bb.max.x, bb.max.y, bb.min.z },
140                 { bb.min.x, bb.max.y, bb.min.z }, // top
141                 { bb.min.x, bb.max.y, bb.max.z },
142                 { bb.max.x, bb.max.y, bb.min.z },
143                 { bb.max.x, bb.max.y, bb.max.z },
144                 { bb.min.x, bb.min.y, bb.min.z }, // bottom
145                 { bb.max.x, bb.min.y, bb.min.z },
146                 { bb.min.x, bb.min.y, bb.max.z },
147                 { bb.max.x, bb.min.y, bb.max.z },
148                 { bb.min.x, bb.min.y, bb.min.z }, // left
149                 { bb.min.x, bb.min.y, bb.max.z },
150                 { bb.min.x, bb.max.y, bb.min.z },
151                 { bb.min.x, bb.max.y, bb.max.z },
152                 { bb.max.x, bb.min.y, bb.min.z }, // right
153                 { bb.max.x, bb.max.y, bb.min.z },
154                 { bb.max.x, bb.min.y, bb.max.z },
155                 { bb.max.x, bb.max.y, bb.max.z },
156         }, {
157                 {  0.0f,  0.0f,  1.0f }, // front
158                 {  0.0f,  0.0f,  1.0f },
159                 {  0.0f,  0.0f,  1.0f },
160                 {  0.0f,  0.0f,  1.0f },
161                 {  0.0f,  0.0f, -1.0f }, // back
162                 {  0.0f,  0.0f, -1.0f },
163                 {  0.0f,  0.0f, -1.0f },
164                 {  0.0f,  0.0f, -1.0f },
165                 {  0.0f,  1.0f,  0.0f }, // top
166                 {  0.0f,  1.0f,  0.0f },
167                 {  0.0f,  1.0f,  0.0f },
168                 {  0.0f,  1.0f,  0.0f },
169                 {  0.0f, -1.0f,  0.0f }, // bottom
170                 {  0.0f, -1.0f,  0.0f },
171                 {  0.0f, -1.0f,  0.0f },
172                 {  0.0f, -1.0f,  0.0f },
173                 { -1.0f,  0.0f,  0.0f }, // left
174                 { -1.0f,  0.0f,  0.0f },
175                 { -1.0f,  0.0f,  0.0f },
176                 { -1.0f,  0.0f,  0.0f },
177                 {  1.0f,  0.0f,  0.0f }, // right
178                 {  1.0f,  0.0f,  0.0f },
179                 {  1.0f,  0.0f,  0.0f },
180                 {  1.0f,  0.0f,  0.0f },
181         }, {
182                   0,  1,  2,  2,  1,  3, // front
183                   4,  5,  6,  6,  5,  7, // back
184                   8,  9, 10, 10,  9, 11, // top
185                  12, 13, 14, 14, 13, 15, // bottom
186                  16, 17, 18, 18, 17, 19, // left
187                  20, 21, 22, 22, 21, 23, // right
188         });
189         SetTexture({
190                 { 0.0f, 1.0f, 0.0f }, // front
191                 { 1.0f, 1.0f, 0.0f },
192                 { 0.0f, 0.0f, 0.0f },
193                 { 1.0f, 0.0f, 0.0f },
194                 { 1.0f, 1.0f, 0.0f }, // back
195                 { 1.0f, 0.0f, 0.0f },
196                 { 0.0f, 1.0f, 0.0f },
197                 { 0.0f, 0.0f, 0.0f },
198                 { 0.0f, 0.0f, 0.0f }, // top
199                 { 0.0f, 1.0f, 0.0f },
200                 { 1.0f, 0.0f, 0.0f },
201                 { 1.0f, 1.0f, 0.0f },
202                 { 1.0f, 0.0f, 0.0f }, // bottom
203                 { 0.0f, 0.0f, 0.0f },
204                 { 1.0f, 1.0f, 0.0f },
205                 { 0.0f, 1.0f, 0.0f },
206                 { 0.0f, 1.0f, 0.0f }, // left
207                 { 1.0f, 1.0f, 0.0f },
208                 { 0.0f, 0.0f, 0.0f },
209                 { 1.0f, 0.0f, 0.0f },
210                 { 1.0f, 1.0f, 0.0f }, // right
211                 { 1.0f, 0.0f, 0.0f },
212                 { 0.0f, 1.0f, 0.0f },
213                 { 0.0f, 0.0f, 0.0f },
214         });
215         SetOutline({
216                 { bb.min.x, bb.min.y, bb.min.z }, // back
217                 { bb.max.x, bb.min.y, bb.min.z },
218                 { bb.min.x, bb.max.y, bb.min.z },
219                 { bb.max.x, bb.max.y, bb.min.z },
220                 { bb.min.x, bb.min.y, bb.max.z }, // front
221                 { bb.max.x, bb.min.y, bb.max.z },
222                 { bb.min.x, bb.max.y, bb.max.z },
223                 { bb.max.x, bb.max.y, bb.max.z },
224         }, {
225                 0, 1, 1, 3, 3, 2, 2, 0, // back
226                 4, 5, 5, 7, 7, 6, 6, 4, // front
227                 0, 4, 1, 5, 2, 6, 3, 7, // sides
228         });
229 }
230
231 bool CuboidShape::Intersects(
232         const Ray &ray,
233         const glm::mat4 &M,
234         float &dist, glm::vec3 &normal
235 ) const noexcept {
236         return Intersection(ray, bb, M, &dist, &normal);
237 }
238
239 bool CuboidShape::Intersects(
240         const glm::mat4 &M,
241         const AABB &box,
242         const glm::mat4 &box_M,
243         float &depth,
244         glm::vec3 &normal
245 ) const noexcept {
246         return Intersection(bb, M, box, box_M, depth, normal);
247 }
248
249
250 StairShape::StairShape(const AABB &bb, const glm::vec2 &clip)
251 : Shape()
252 , top({ { bb.min.x, clip.y, bb.min.z }, { bb.max.x, bb.max.y, clip.x } })
253 , bot({ bb.min, { bb.max.x, clip.y, bb.max.z } }) {
254         SetShape({
255                 { top.min.x, top.min.y, top.max.z }, // front, upper
256                 { top.max.x, top.min.y, top.max.z },
257                 { top.min.x, top.max.y, top.max.z },
258                 { top.max.x, top.max.y, top.max.z },
259                 { bot.min.x, bot.min.y, bot.max.z }, // front, lower
260                 { bot.max.x, bot.min.y, bot.max.z },
261                 { bot.min.x, bot.max.y, bot.max.z },
262                 { bot.max.x, bot.max.y, bot.max.z },
263                 { bot.min.x, bot.min.y, bot.min.z }, // back
264                 { bot.min.x, top.max.y, bot.min.z },
265                 { top.max.x, bot.min.y, bot.min.z },
266                 { top.max.x, top.max.y, bot.min.z },
267                 { top.min.x, top.max.y, top.min.z }, // top, upper
268                 { top.min.x, top.max.y, top.max.z },
269                 { top.max.x, top.max.y, top.min.z },
270                 { top.max.x, top.max.y, top.max.z },
271                 { bot.min.x, bot.max.y, top.max.z }, // top, lower
272                 { bot.min.x, bot.max.y, bot.max.z },
273                 { bot.max.x, bot.max.y, top.max.z },
274                 { bot.max.x, bot.max.y, bot.max.z },
275                 { bot.min.x, bot.min.y, bot.min.z }, // bottom
276                 { bot.max.x, bot.min.y, bot.min.z },
277                 { bot.min.x, bot.min.y, bot.max.z },
278                 { bot.max.x, bot.min.y, bot.max.z },
279                 { top.min.x, top.min.y, top.min.z }, // left, upper
280                 { top.min.x, top.min.y, top.max.z },
281                 { top.min.x, top.max.y, top.min.z },
282                 { top.min.x, top.max.y, top.max.z },
283                 { bot.min.x, bot.min.y, bot.min.z }, // left, lower
284                 { bot.min.x, bot.min.y, bot.max.z },
285                 { bot.min.x, bot.max.y, bot.min.z },
286                 { bot.min.x, bot.max.y, bot.max.z },
287                 { top.max.x, top.min.y, top.min.z }, // right, upper
288                 { top.max.x, top.max.y, top.min.z },
289                 { top.max.x, top.min.y, top.max.z },
290                 { top.max.x, top.max.y, top.max.z },
291                 { bot.max.x, bot.min.y, bot.min.z }, // right, lower
292                 { bot.max.x, bot.max.y, bot.min.z },
293                 { bot.max.x, bot.min.y, bot.max.z },
294                 { bot.max.x, bot.max.y, bot.max.z },
295         }, {
296                 {  0.0f,  0.0f,  1.0f }, // front x2
297                 {  0.0f,  0.0f,  1.0f },
298                 {  0.0f,  0.0f,  1.0f },
299                 {  0.0f,  0.0f,  1.0f },
300                 {  0.0f,  0.0f,  1.0f },
301                 {  0.0f,  0.0f,  1.0f },
302                 {  0.0f,  0.0f,  1.0f },
303                 {  0.0f,  0.0f,  1.0f },
304                 {  0.0f,  0.0f, -1.0f }, // back
305                 {  0.0f,  0.0f, -1.0f },
306                 {  0.0f,  0.0f, -1.0f },
307                 {  0.0f,  0.0f, -1.0f },
308                 {  0.0f,  1.0f,  0.0f }, // top x2
309                 {  0.0f,  1.0f,  0.0f },
310                 {  0.0f,  1.0f,  0.0f },
311                 {  0.0f,  1.0f,  0.0f },
312                 {  0.0f,  1.0f,  0.0f },
313                 {  0.0f,  1.0f,  0.0f },
314                 {  0.0f,  1.0f,  0.0f },
315                 {  0.0f,  1.0f,  0.0f },
316                 {  0.0f, -1.0f,  0.0f }, // bottom
317                 {  0.0f, -1.0f,  0.0f },
318                 {  0.0f, -1.0f,  0.0f },
319                 {  0.0f, -1.0f,  0.0f },
320                 { -1.0f,  0.0f,  0.0f }, // left x2
321                 { -1.0f,  0.0f,  0.0f },
322                 { -1.0f,  0.0f,  0.0f },
323                 { -1.0f,  0.0f,  0.0f },
324                 { -1.0f,  0.0f,  0.0f },
325                 { -1.0f,  0.0f,  0.0f },
326                 { -1.0f,  0.0f,  0.0f },
327                 { -1.0f,  0.0f,  0.0f },
328                 {  1.0f,  0.0f,  0.0f }, // right x2
329                 {  1.0f,  0.0f,  0.0f },
330                 {  1.0f,  0.0f,  0.0f },
331                 {  1.0f,  0.0f,  0.0f },
332                 {  1.0f,  0.0f,  0.0f },
333                 {  1.0f,  0.0f,  0.0f },
334                 {  1.0f,  0.0f,  0.0f },
335                 {  1.0f,  0.0f,  0.0f },
336         }, {
337                  0,  1,  2,  2,  1,  3, // front, upper
338                  4,  5,  6,  6,  5,  7, // front, lower
339                  8,  9, 10, 10,  9, 11, // back
340                 12, 13, 14, 14, 13, 15, // top, upper
341                 16, 17, 18, 18, 17, 19, // top, lower
342                 20, 21, 22, 22, 21, 23, // bottom
343                 24, 25, 26, 26, 25, 27, // left, upper
344                 28, 29, 30, 30, 29, 31, // left, lower
345                 32, 33, 34, 34, 33, 35, // right, upper
346                 36, 37, 38, 38, 37, 39, // right, lower
347         });
348         SetTexture({
349                 { 0.0f, 0.5f, 0.0f }, // front, upper
350                 { 1.0f, 0.5f, 0.0f },
351                 { 0.0f, 0.0f, 0.0f },
352                 { 1.0f, 0.0f, 0.0f },
353                 { 0.0f, 1.0f, 0.0f }, // front, lower
354                 { 1.0f, 1.0f, 0.0f },
355                 { 0.0f, 0.5f, 0.0f },
356                 { 1.0f, 0.5f, 0.0f },
357                 { 1.0f, 1.0f, 0.0f }, // back
358                 { 1.0f, 0.0f, 0.0f },
359                 { 0.0f, 1.0f, 0.0f },
360                 { 0.0f, 0.0f, 0.0f },
361                 { 0.0f, 0.0f, 0.0f }, // top, upper
362                 { 0.0f, 0.5f, 0.0f },
363                 { 1.0f, 0.0f, 0.0f },
364                 { 1.0f, 0.5f, 0.0f },
365                 { 0.0f, 0.5f, 0.0f }, // top, lower
366                 { 0.0f, 1.0f, 0.0f },
367                 { 1.0f, 0.5f, 0.0f },
368                 { 1.0f, 1.0f, 0.0f },
369                 { 1.0f, 0.0f, 0.0f }, // bottom
370                 { 0.0f, 0.0f, 0.0f },
371                 { 1.0f, 1.0f, 0.0f },
372                 { 0.0f, 1.0f, 0.0f },
373                 { 0.0f, 0.5f, 0.0f }, // left, upper
374                 { 0.5f, 0.5f, 0.0f },
375                 { 0.0f, 0.0f, 0.0f },
376                 { 0.5f, 0.0f, 0.0f },
377                 { 0.0f, 1.0f, 0.0f }, // left, lower
378                 { 1.0f, 1.0f, 0.0f },
379                 { 0.0f, 0.5f, 0.0f },
380                 { 1.0f, 0.5f, 0.0f },
381                 { 1.0f, 0.5f, 0.0f }, // right, upper
382                 { 1.0f, 0.0f, 0.0f },
383                 { 0.5f, 0.5f, 0.0f },
384                 { 0.5f, 0.0f, 0.0f },
385                 { 1.0f, 1.0f, 0.0f }, // right, lower
386                 { 1.0f, 0.5f, 0.0f },
387                 { 0.0f, 1.0f, 0.0f },
388                 { 0.0f, 0.5f, 0.0f },
389         });
390         SetOutline({
391                 { bot.min.x, bot.min.y, bot.min.z }, // bottom
392                 { bot.max.x, bot.min.y, bot.min.z },
393                 { bot.min.x, bot.min.y, bot.max.z },
394                 { bot.max.x, bot.min.y, bot.max.z },
395                 { bot.min.x, bot.max.y, top.max.z }, // middle
396                 { bot.max.x, bot.max.y, top.max.z },
397                 { bot.min.x, bot.max.y, bot.max.z },
398                 { bot.max.x, bot.max.y, bot.max.z },
399                 { top.min.x, top.max.y, top.min.z }, // top
400                 { top.max.x, top.max.y, top.min.z },
401                 { top.min.x, top.max.y, top.max.z },
402                 { top.max.x, top.max.y, top.max.z },
403         }, {
404                  0,  1,  1,  3,  3,  2,  2,  0, // bottom
405                  4,  5,  5,  7,  7,  6,  6,  4, // middle
406                  8,  9,  9, 11, 11, 10, 10 , 8, // top
407                  0,  8,  4, 10,  2,  6, // verticals, btf
408                  1,  9,  5, 11,  3,  7,
409         });
410 }
411
412 bool StairShape::Intersects(
413         const Ray &ray,
414         const glm::mat4 &M,
415         float &dist,
416         glm::vec3 &norm
417 ) const noexcept {
418         float top_dist, bot_dist;
419         glm::vec3 top_norm, bot_norm;
420         bool top_hit = Intersection(ray, top, M, &top_dist, &top_norm);
421         bool bot_hit = Intersection(ray, bot, M, &bot_dist, &bot_norm);
422
423         if (top_hit) {
424                 if (bot_hit) {
425                         if (top_dist < bot_dist) {
426                                 dist = top_dist;
427                                 norm = top_norm;
428                                 return true;
429                         } else {
430                                 dist = bot_dist;
431                                 norm = bot_norm;
432                                 return true;
433                         }
434                 } else {
435                         dist = top_dist;
436                         norm = top_norm;
437                         return true;
438                 }
439         } else if (bot_hit) {
440                 dist = bot_dist;
441                 norm = bot_norm;
442                 return true;
443         } else {
444                 return false;
445         }
446 }
447
448 bool StairShape::Intersects(
449         const glm::mat4 &M,
450         const AABB &box,
451         const glm::mat4 &box_M,
452         float &dist,
453         glm::vec3 &normal
454 ) const noexcept {
455         bool top_hit, bot_hit;
456         float top_dist, bot_dist;
457         glm::vec3 top_normal, bot_normal;
458
459         top_hit = Intersection(bot, M, box, box_M, top_dist, top_normal);
460         bot_hit = Intersection(top, M, box, box_M, bot_dist, bot_normal);
461
462         if (top_hit) {
463                 if (bot_hit && bot_dist < top_dist) {
464                         dist = bot_dist;
465                         normal = bot_normal;
466                         return true;
467                 } else {
468                         dist = top_dist;
469                         normal = top_normal;
470                         return true;
471                 }
472                 return true;
473         } else if (bot_hit) {
474                 dist = bot_dist;
475                 normal = bot_normal;
476                 return true;
477         } else {
478                 return false;
479         }
480 }
481
482 }