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