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