Tramway SDK
aabb.h
Go to the documentation of this file.
1// TRAMWAY DRIFT AND DUNGEON EXPLORATION SIMULATOR 2022
2// All rights reserved.
3
4#ifndef TRAM_SDK_TEMPLATES_AABB_H
5#define TRAM_SDK_TEMPLATES_AABB_H
6
7#include <framework/math.h>
8#include <framework/logging.h>
9#include <framework/core.h>
10
11#include <iostream>
12
13#include <vector>
14
15namespace tram {
16
17class AABBTree {
18public:
22 }
23
24 vec3 GetAABBMin() { return root->min; }
25 vec3 GetAABBMax() { return root->max; }
26
27 struct Node;
28
29 Node* InsertLeaf (uint32_t value, vec3 min, vec3 max) {
30 Node* new_node = new Node;
31
32 new_node->value = value;
33
34 new_node->min = min;
35 new_node->max = max;
36
37 if (root->left == nullptr) {
38 root->left = new_node;
39 new_node->parent = root;
40
41 if (root->right) {
43 } else {
44 root->min = new_node->min;
45 root->max = new_node->max;
46 }
47
48 return new_node;
49 }
50
51 if (root->right == nullptr) {
52 root->right = new_node;
53 new_node->parent = root;
54
55 if (root->left) {
57 } else {
58 root->min = new_node->min;
59 root->max = new_node->max;
60 }
61
62 return new_node;
63 }
64
65 Node* sibling = FindSibling(min, max, root);
66 Node* sibling_parent = sibling->parent;
67 Node* new_parent = new Node;
68
69 if (sibling_parent->left == sibling) {
70 sibling_parent->left = new_parent;
71 } else if (sibling_parent->right == sibling) {
72 sibling_parent->right = new_parent;
73 } else {
74 assert(false);
75 }
76
77 new_parent->parent = sibling_parent;
78
79 new_parent->left = new_node;
80 new_parent->right = sibling;
81
82 sibling->parent = new_parent;
83 new_node->parent = new_parent;
84
85 UpdateParentAABB(new_parent);
86
88
89 return new_node;
90 }
91
92 void RemoveLeaf(Node* node) {
93 assert(node);
94
95 Node* parent = node->parent;
96 Node* sibling = parent->left == node ? parent->right : parent->left;
97
98 if (parent->left != node && parent->right != node) {
99 assert(false);
100 }
101
102 if (parent == root) {
103 if (parent->left == node) {
104 parent->left = nullptr;
105
106 if (sibling) {
107 parent->min = sibling->min;
108 parent->max = sibling->max;
109 }
110 } else {
111 parent->right = nullptr;
112
113 if (sibling) {
114 parent->min = sibling->min;
115 parent->max = sibling->max;
116 }
117 }
118
119 delete node;
120
122
123 return;
124 }
125
126 Node* grandparent = parent->parent;
127
128 if (grandparent->left == parent) {
129 grandparent->left = sibling;
130 } else {
131 grandparent->right = sibling;
132 }
133
134 sibling->parent = grandparent;
135
136 UpdateParentAABB(grandparent);
137
138 delete node;
139 delete parent;
140
142 }
143
144 void RemoveHierarchy(Node* node) {
145 if (node->IsLeaf()) {
146 delete node;
147 } else {
148 RemoveHierarchy(node->left);
149 RemoveHierarchy(node->right);
150 delete node;
151 }
152 }
153
154 void FindIntersection (vec3 ray_pos, vec3 ray_dir, Node* node, std::vector<uint32_t>& result) {
155 bool is_node_intersect = AABBIntersect(ray_pos, ray_dir, node->min, node->max);
156
157 if (is_node_intersect) {
158 if (node->IsLeaf() && node != root) {
159 result.push_back(node->value);
160 } else {
161 if (node->left) FindIntersection (ray_pos, ray_dir, node->left, result);
162 if (node->right) FindIntersection (ray_pos, ray_dir, node->right, result);
163 }
164 }
165 }
166
167//private:
168
169 void UpdateParentAABB (Node* node) {
170 assert(!node->IsLeaf());
171
172 Node* left_child = node->left;
173 Node* right_child = node->right;
174
175 if (!left_child || !right_child) {
176 assert(node == root);
177
178 if (!left_child && right_child) {
179 node->min = right_child->min;
180 node->max = right_child->max;
181 } else if (left_child && !right_child) {
182 node->min = left_child->min;
183 node->max = left_child->max;
184 } else {
185 node->min = {0.0f, 0.0f, 0.0f};
186 node->max = {0.0f, 0.0f, 0.0f};
187 }
188
189 return;
190 }
191
192
193 node->min = MergeAABBMin(left_child->min, right_child->min);
194 node->max = MergeAABBMax(left_child->max, right_child->max);
195
196 if (node->parent != nullptr) {
198 }
199
200 assert(node->parent != node);
201 }
202
203 // searches the children of search_node to find a sibling for target_node
204 Node* FindSibling (vec3 min, vec3 max, Node* node) {
205 assert(node);
206
207 if (node->IsLeaf()) {
208 return node;
209 }
210
211 if (node->left == nullptr) {
212 assert(false);
213 }
214 assert(node->left);
215 assert(node->right);
216
217 vec3 left_merge_min = MergeAABBMin(min, node->left->min);
218 vec3 left_merge_max = MergeAABBMax(max, node->left->max);
219
220 vec3 right_merge_min = MergeAABBMin(min, node->right->min);
221 vec3 right_merge_max = MergeAABBMax(max, node->right->max);
222
223 float left_merge_volume = AABBVolume(left_merge_min, left_merge_max);
224 float right_merge_volume = AABBVolume(right_merge_min, right_merge_max);
225
226 //float left_merge_volume = AABBSurface(left_merge_min, left_merge_max);
227 //float right_merge_volume = AABBSurface(right_merge_min, right_merge_max);
228
229 if (left_merge_volume < right_merge_volume) {
230 return FindSibling(min, max, node->left);
231 } else {
232 return FindSibling(min, max, node->right);
233 }
234 }
235
236
237 void ValidateTree (Node* node) {
238 return;
239 if (root->parent != nullptr) {
240 //if (((Node*)0)->IsLeaf()) assert(false);
241 }
242
243 return;
244 ValidateTree (node, 0);
245 }
246 void ValidateTree (Node* node, size_t num) {
247 assert(node);
248 assert((long long)node > 100);
249
250 if (num > 400) {
251 //if (((Node*)0)->IsLeaf()) assert(false);
252 }
253
254 if (node->IsLeaf() && node != root) {
255 //assert(node->value < 40000);
256 } else {
257 if (node != root || (node == root && node->left))ValidateTree(node->left, num+1);
258 if (node != root || (node == root && node->right))ValidateTree(node->right, num+1);
259 }
260 }
261
262 static vec3 MergeAABBMin (vec3 a, vec3 b) {
263 return vec3 {
264 a.x < b.x ? a.x : b.x,
265 a.y < b.y ? a.y : b.y,
266 a.z < b.z ? a.z : b.z
267 };// - vec3 {0.1f, 0.1f, 0.1f};
268 }
269
270 static vec3 MergeAABBMax (vec3 a, vec3 b) {
271 return vec3 {
272 a.x > b.x ? a.x : b.x,
273 a.y > b.y ? a.y : b.y,
274 a.z > b.z ? a.z : b.z
275 };// + vec3 {0.1f, 0.1f, 0.1f};
276 }
277
278 static float AABBVolume (vec3 min, vec3 max) {
279 return (max.x - min.x) * (max.y - min.y) * (max.z - min.z);
280 }
281
282 static float AABBSurface (vec3 min, vec3 max) {
283 float x = max.x - min.x;
284 float y = max.y - min.y;
285 float z = max.z - min.z;
286
287 assert(max.x >= min.x);
288 assert(max.y >= min.y);
289 assert(max.z >= min.z);
290
291 return 2 * ((x * y) + (x * z) + (y * z));
292 }
293
294 static bool AABBIntersect (vec3 ray_pos, vec3 ray_dir, vec3 min, vec3 max) {
295 vec3 t1 = (min - ray_pos) / ray_dir; // what happens if ray_dir == 0.0f?
296 vec3 t2 = (max - ray_pos) / ray_dir; // TODO: check
297
298 vec3 t1min = glm::min(t1, t2);
299 vec3 t2max = glm::max(t1, t2);
300
301 float tnear = glm::max(glm::max(t1min.x, t1min.y), t1min.z);
302 float tfar = glm::min(glm::min(t2max.x, t2max.y), t2max.z);
303
304 return tfar >= tnear;
305 }
306
307 struct Node {
308 bool IsLeaf () const { return right == 0; }
309
310 void Print () const { std::cout << " l: " << left << " r: " << right << " p: " << parent << std::endl; }
311
312 union {
313 Node* left = nullptr;
314 uint32_t value;
315 };
316
317 Node* right = nullptr;
318 Node* parent = nullptr;
319
322 };
323
324 Node* root = new Node {nullptr, nullptr, nullptr, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}};
325};
326
327}
328
329#endif // TRAM_SDK_TEMPLATES_AABB_H
Definition: aabb.h:17
Node * InsertLeaf(uint32_t value, vec3 min, vec3 max)
Definition: aabb.h:29
static bool AABBIntersect(vec3 ray_pos, vec3 ray_dir, vec3 min, vec3 max)
Definition: aabb.h:294
~AABBTree()
Definition: aabb.h:20
void UpdateParentAABB(Node *node)
Definition: aabb.h:169
void ValidateTree(Node *node)
Definition: aabb.h:237
AABBTree()
Definition: aabb.h:19
vec3 GetAABBMax()
Definition: aabb.h:25
Node * root
Definition: aabb.h:324
static float AABBVolume(vec3 min, vec3 max)
Definition: aabb.h:278
static vec3 MergeAABBMax(vec3 a, vec3 b)
Definition: aabb.h:270
void RemoveLeaf(Node *node)
Definition: aabb.h:92
void RemoveHierarchy(Node *node)
Definition: aabb.h:144
static vec3 MergeAABBMin(vec3 a, vec3 b)
Definition: aabb.h:262
Node * FindSibling(vec3 min, vec3 max, Node *node)
Definition: aabb.h:204
vec3 GetAABBMin()
Definition: aabb.h:24
void ValidateTree(Node *node, size_t num)
Definition: aabb.h:246
void FindIntersection(vec3 ray_pos, vec3 ray_dir, Node *node, std::vector< uint32_t > &result)
Definition: aabb.h:154
static float AABBSurface(vec3 min, vec3 max)
Definition: aabb.h:282
Definition: api.h:9
glm::vec3 vec3
Definition: math.h:12
Definition: aabb.h:307
Node * left
Definition: aabb.h:313
Node * right
Definition: aabb.h:317
bool IsLeaf() const
Definition: aabb.h:308
Node * parent
Definition: aabb.h:318
vec3 max
Definition: aabb.h:321
vec3 min
Definition: aabb.h:320
uint32_t value
Definition: aabb.h:314
void Print() const
Definition: aabb.h:310
Definition: graph.h:17