]> git.localhorst.tv Git - blank.git/blob - src/model/shape.cpp
box/box intersection test
[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         Model::Positions &vertex,
9         Model::Normals &normal,
10         Model::Indices &index
11 ) const {
12         for (const auto &pos : vtx_pos) {
13                 vertex.emplace_back(pos);
14         }
15         for (const auto &nrm : vtx_nrm) {
16                 normal.emplace_back(nrm);
17         }
18         for (auto idx : vtx_idx) {
19                 index.emplace_back(idx);
20         }
21 }
22
23 void Shape::Vertices(
24         Model::Positions &vertex,
25         Model::Normals &normal,
26         Model::Indices &index,
27         const glm::mat4 &transform,
28         Model::Index idx_offset
29 ) const {
30         for (const auto &pos : vtx_pos) {
31                 vertex.emplace_back(transform * glm::vec4(pos, 1.0f));
32         }
33         for (const auto &nrm : vtx_nrm) {
34                 normal.emplace_back(transform * glm::vec4(nrm, 0.0f));
35         }
36         for (auto idx : vtx_idx) {
37                 index.emplace_back(idx_offset + idx);
38         }
39 }
40
41 void Shape::Vertices(
42         BlockModel::Positions &vertex,
43         BlockModel::Indices &index,
44         const glm::mat4 &transform,
45         BlockModel::Index idx_offset
46 ) const {
47         for (const auto &pos : vtx_pos) {
48                 vertex.emplace_back(transform * glm::vec4(pos, 1.0f));
49         }
50         for (auto idx : vtx_idx) {
51                 index.emplace_back(idx_offset + idx);
52         }
53 }
54
55 void Shape::Outline(
56         OutlineModel::Positions &vertex,
57         OutlineModel::Indices &index,
58         const OutlineModel::Position &elem_offset,
59         OutlineModel::Index idx_offset
60 ) const {
61         for (const auto &pos : out_pos) {
62                 vertex.emplace_back(elem_offset + pos);
63         }
64         for (auto idx : out_idx) {
65                 index.emplace_back(idx_offset + idx);
66         }
67 }
68
69
70 NullShape::NullShape()
71 : Shape() {
72
73 }
74
75 bool NullShape::Intersects(
76         const Ray &,
77         const glm::mat4 &,
78         float &, glm::vec3 &
79 ) const noexcept {
80         return false;
81 }
82
83
84 CuboidShape::CuboidShape(const AABB &b)
85 : Shape()
86 , bb(b) {
87         bb.Adjust();
88         SetShape({
89                 { bb.min.x, bb.min.y, bb.max.z }, // front
90                 { bb.max.x, bb.min.y, bb.max.z },
91                 { bb.min.x, bb.max.y, bb.max.z },
92                 { bb.max.x, bb.max.y, bb.max.z },
93                 { bb.min.x, bb.min.y, bb.min.z }, // back
94                 { bb.min.x, bb.max.y, bb.min.z },
95                 { bb.max.x, bb.min.y, bb.min.z },
96                 { bb.max.x, bb.max.y, bb.min.z },
97                 { bb.min.x, bb.max.y, bb.min.z }, // top
98                 { bb.min.x, bb.max.y, bb.max.z },
99                 { bb.max.x, bb.max.y, bb.min.z },
100                 { bb.max.x, bb.max.y, bb.max.z },
101                 { bb.min.x, bb.min.y, bb.min.z }, // bottom
102                 { bb.max.x, bb.min.y, bb.min.z },
103                 { bb.min.x, bb.min.y, bb.max.z },
104                 { bb.max.x, bb.min.y, bb.max.z },
105                 { bb.min.x, bb.min.y, bb.min.z }, // left
106                 { bb.min.x, bb.min.y, bb.max.z },
107                 { bb.min.x, bb.max.y, bb.min.z },
108                 { bb.min.x, bb.max.y, bb.max.z },
109                 { bb.max.x, bb.min.y, bb.min.z }, // right
110                 { bb.max.x, bb.max.y, bb.min.z },
111                 { bb.max.x, bb.min.y, bb.max.z },
112                 { bb.max.x, bb.max.y, bb.max.z },
113         }, {
114                 {  0.0f,  0.0f,  1.0f }, // front
115                 {  0.0f,  0.0f,  1.0f },
116                 {  0.0f,  0.0f,  1.0f },
117                 {  0.0f,  0.0f,  1.0f },
118                 {  0.0f,  0.0f, -1.0f }, // back
119                 {  0.0f,  0.0f, -1.0f },
120                 {  0.0f,  0.0f, -1.0f },
121                 {  0.0f,  0.0f, -1.0f },
122                 {  0.0f,  1.0f,  0.0f }, // top
123                 {  0.0f,  1.0f,  0.0f },
124                 {  0.0f,  1.0f,  0.0f },
125                 {  0.0f,  1.0f,  0.0f },
126                 {  0.0f, -1.0f,  0.0f }, // bottom
127                 {  0.0f, -1.0f,  0.0f },
128                 {  0.0f, -1.0f,  0.0f },
129                 {  0.0f, -1.0f,  0.0f },
130                 { -1.0f,  0.0f,  0.0f }, // left
131                 { -1.0f,  0.0f,  0.0f },
132                 { -1.0f,  0.0f,  0.0f },
133                 { -1.0f,  0.0f,  0.0f },
134                 {  1.0f,  0.0f,  0.0f }, // right
135                 {  1.0f,  0.0f,  0.0f },
136                 {  1.0f,  0.0f,  0.0f },
137                 {  1.0f,  0.0f,  0.0f },
138         }, {
139                   0,  1,  2,  2,  1,  3, // front
140                   4,  5,  6,  6,  5,  7, // back
141                   8,  9, 10, 10,  9, 11, // top
142                  12, 13, 14, 14, 13, 15, // bottom
143                  16, 17, 18, 18, 17, 19, // left
144                  20, 21, 22, 22, 21, 23, // right
145         });
146         SetOutline({
147                 { bb.min.x, bb.min.y, bb.min.z }, // back
148                 { bb.max.x, bb.min.y, bb.min.z },
149                 { bb.min.x, bb.max.y, bb.min.z },
150                 { bb.max.x, bb.max.y, bb.min.z },
151                 { bb.min.x, bb.min.y, bb.max.z }, // front
152                 { bb.max.x, bb.min.y, bb.max.z },
153                 { bb.min.x, bb.max.y, bb.max.z },
154                 { bb.max.x, bb.max.y, bb.max.z },
155         }, {
156                 0, 1, 1, 3, 3, 2, 2, 0, // back
157                 4, 5, 5, 7, 7, 6, 6, 4, // front
158                 0, 4, 1, 5, 2, 6, 3, 7, // sides
159         });
160 }
161
162 bool CuboidShape::Intersects(
163         const Ray &ray,
164         const glm::mat4 &M,
165         float &dist, glm::vec3 &normal
166 ) const noexcept {
167         return Intersection(ray, bb, M, &dist, &normal);
168 }
169
170
171 StairShape::StairShape(const AABB &bb, const glm::vec2 &clip)
172 : Shape()
173 , top({ { bb.min.x, clip.y, bb.min.z }, { bb.max.x, bb.max.y, clip.x } })
174 , bot({ bb.min, { bb.max.x, clip.y, bb.max.z } }) {
175         SetShape({
176                 { top.min.x, top.min.y, top.max.z }, // front, upper
177                 { top.max.x, top.min.y, top.max.z },
178                 { top.min.x, top.max.y, top.max.z },
179                 { top.max.x, top.max.y, top.max.z },
180                 { bot.min.x, bot.min.y, bot.max.z }, // front, lower
181                 { bot.max.x, bot.min.y, bot.max.z },
182                 { bot.min.x, bot.max.y, bot.max.z },
183                 { bot.max.x, bot.max.y, bot.max.z },
184                 { bot.min.x, bot.min.y, bot.min.z }, // back
185                 { bot.min.x, top.max.y, bot.min.z },
186                 { top.max.x, bot.min.y, bot.min.z },
187                 { top.max.x, top.max.y, bot.min.z },
188                 { top.min.x, top.max.y, top.min.z }, // top, upper
189                 { top.min.x, top.max.y, top.max.z },
190                 { top.max.x, top.max.y, top.min.z },
191                 { top.max.x, top.max.y, top.max.z },
192                 { bot.min.x, bot.max.y, top.max.z }, // top, lower
193                 { bot.min.x, bot.max.y, bot.max.z },
194                 { bot.max.x, bot.max.y, top.max.z },
195                 { bot.max.x, bot.max.y, bot.max.z },
196                 { bot.min.x, bot.min.y, bot.min.z }, // bottom
197                 { bot.max.x, bot.min.y, bot.min.z },
198                 { bot.min.x, bot.min.y, bot.max.z },
199                 { bot.max.x, bot.min.y, bot.max.z },
200                 { top.min.x, top.min.y, top.min.z }, // left, upper
201                 { top.min.x, top.min.y, top.max.z },
202                 { top.min.x, top.max.y, top.min.z },
203                 { top.min.x, top.max.y, top.max.z },
204                 { bot.min.x, bot.min.y, bot.min.z }, // left, lower
205                 { bot.min.x, bot.min.y, bot.max.z },
206                 { bot.min.x, bot.max.y, bot.min.z },
207                 { bot.min.x, bot.max.y, bot.max.z },
208                 { top.max.x, top.min.y, top.min.z }, // right, upper
209                 { top.max.x, top.max.y, top.min.z },
210                 { top.max.x, top.min.y, top.max.z },
211                 { top.max.x, top.max.y, top.max.z },
212                 { bot.max.x, bot.min.y, bot.min.z }, // right, lower
213                 { bot.max.x, bot.max.y, bot.min.z },
214                 { bot.max.x, bot.min.y, bot.max.z },
215                 { bot.max.x, bot.max.y, bot.max.z },
216         }, {
217                 {  0.0f,  0.0f,  1.0f }, // front x2
218                 {  0.0f,  0.0f,  1.0f },
219                 {  0.0f,  0.0f,  1.0f },
220                 {  0.0f,  0.0f,  1.0f },
221                 {  0.0f,  0.0f,  1.0f },
222                 {  0.0f,  0.0f,  1.0f },
223                 {  0.0f,  0.0f,  1.0f },
224                 {  0.0f,  0.0f,  1.0f },
225                 {  0.0f,  0.0f, -1.0f }, // back
226                 {  0.0f,  0.0f, -1.0f },
227                 {  0.0f,  0.0f, -1.0f },
228                 {  0.0f,  0.0f, -1.0f },
229                 {  0.0f,  1.0f,  0.0f }, // top x2
230                 {  0.0f,  1.0f,  0.0f },
231                 {  0.0f,  1.0f,  0.0f },
232                 {  0.0f,  1.0f,  0.0f },
233                 {  0.0f,  1.0f,  0.0f },
234                 {  0.0f,  1.0f,  0.0f },
235                 {  0.0f,  1.0f,  0.0f },
236                 {  0.0f,  1.0f,  0.0f },
237                 {  0.0f, -1.0f,  0.0f }, // bottom
238                 {  0.0f, -1.0f,  0.0f },
239                 {  0.0f, -1.0f,  0.0f },
240                 {  0.0f, -1.0f,  0.0f },
241                 { -1.0f,  0.0f,  0.0f }, // left x2
242                 { -1.0f,  0.0f,  0.0f },
243                 { -1.0f,  0.0f,  0.0f },
244                 { -1.0f,  0.0f,  0.0f },
245                 { -1.0f,  0.0f,  0.0f },
246                 { -1.0f,  0.0f,  0.0f },
247                 { -1.0f,  0.0f,  0.0f },
248                 { -1.0f,  0.0f,  0.0f },
249                 {  1.0f,  0.0f,  0.0f }, // right x2
250                 {  1.0f,  0.0f,  0.0f },
251                 {  1.0f,  0.0f,  0.0f },
252                 {  1.0f,  0.0f,  0.0f },
253                 {  1.0f,  0.0f,  0.0f },
254                 {  1.0f,  0.0f,  0.0f },
255                 {  1.0f,  0.0f,  0.0f },
256                 {  1.0f,  0.0f,  0.0f },
257         }, {
258                  0,  1,  2,  2,  1,  3, // front, upper
259                  4,  5,  6,  6,  5,  7, // front, lower
260                  8,  9, 10, 10,  9, 11, // back
261                 12, 13, 14, 14, 13, 15, // top, upper
262                 16, 17, 18, 18, 17, 19, // top, lower
263                 20, 21, 22, 22, 21, 23, // bottom
264                 24, 25, 26, 26, 25, 27, // left, upper
265                 28, 29, 30, 30, 29, 31, // left, lower
266                 32, 33, 34, 34, 33, 35, // right, upper
267                 36, 37, 38, 38, 37, 39, // right, lower
268         });
269         SetOutline({
270                 { bot.min.x, bot.min.y, bot.min.z }, // bottom
271                 { bot.max.x, bot.min.y, bot.min.z },
272                 { bot.min.x, bot.min.y, bot.max.z },
273                 { bot.max.x, bot.min.y, bot.max.z },
274                 { bot.min.x, bot.max.y, top.max.z }, // middle
275                 { bot.max.x, bot.max.y, top.max.z },
276                 { bot.min.x, bot.max.y, bot.max.z },
277                 { bot.max.x, bot.max.y, bot.max.z },
278                 { top.min.x, top.max.y, top.min.z }, // top
279                 { top.max.x, top.max.y, top.min.z },
280                 { top.min.x, top.max.y, top.max.z },
281                 { top.max.x, top.max.y, top.max.z },
282         }, {
283                  0,  1,  1,  3,  3,  2,  2,  0, // bottom
284                  4,  5,  5,  7,  7,  6,  6,  4, // middle
285                  8,  9,  9, 11, 11, 10, 10 , 8, // top
286                  0,  8,  4, 10,  2,  6, // verticals, btf
287                  1,  9,  5, 11,  3,  7,
288         //       5,  8,  7, 10,
289         //       1,  9,  3, 11,
290         });
291 }
292
293 bool StairShape::Intersects(
294         const Ray &ray,
295         const glm::mat4 &M,
296         float &dist,
297         glm::vec3 &norm
298 ) const noexcept {
299         float top_dist, bot_dist;
300         glm::vec3 top_norm, bot_norm;
301         bool top_hit = Intersection(ray, top, M, &top_dist, &top_norm);
302         bool bot_hit = Intersection(ray, bot, M, &bot_dist, &bot_norm);
303
304         if (top_hit) {
305                 if (bot_hit) {
306                         if (top_dist < bot_dist) {
307                                 dist = top_dist;
308                                 norm = top_norm;
309                                 return true;
310                         } else {
311                                 dist = bot_dist;
312                                 norm = bot_norm;
313                                 return true;
314                         }
315                 } else {
316                         dist = top_dist;
317                         norm = top_norm;
318                         return true;
319                 }
320         } else if (bot_hit) {
321                 dist = bot_dist;
322                 norm = bot_norm;
323                 return true;
324         } else {
325                 return false;
326         }
327 }
328
329 }