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