1use gizmo_core::entity::Entity;
24use gizmo_math::{Aabb, Vec3};
25use std::collections::HashMap;
26
27#[cfg(target_arch = "x86_64")]
32use std::arch::x86_64::*;
33
34#[cfg(target_arch = "x86_64")]
37#[inline]
38pub fn aabb_overlaps_simd4(target: &Aabb, others: [&Aabb; 4]) -> u8 {
39 unsafe {
40 let t_min_x = _mm_set1_ps(target.min.x);
41 let t_max_x = _mm_set1_ps(target.max.x);
42 let t_min_y = _mm_set1_ps(target.min.y);
43 let t_max_y = _mm_set1_ps(target.max.y);
44 let t_min_z = _mm_set1_ps(target.min.z);
45 let t_max_z = _mm_set1_ps(target.max.z);
46
47 let o_min_x = _mm_set_ps(
48 others[3].min.x,
49 others[2].min.x,
50 others[1].min.x,
51 others[0].min.x,
52 );
53 let o_max_x = _mm_set_ps(
54 others[3].max.x,
55 others[2].max.x,
56 others[1].max.x,
57 others[0].max.x,
58 );
59 let o_min_y = _mm_set_ps(
60 others[3].min.y,
61 others[2].min.y,
62 others[1].min.y,
63 others[0].min.y,
64 );
65 let o_max_y = _mm_set_ps(
66 others[3].max.y,
67 others[2].max.y,
68 others[1].max.y,
69 others[0].max.y,
70 );
71 let o_min_z = _mm_set_ps(
72 others[3].min.z,
73 others[2].min.z,
74 others[1].min.z,
75 others[0].min.z,
76 );
77 let o_max_z = _mm_set_ps(
78 others[3].max.z,
79 others[2].max.z,
80 others[1].max.z,
81 others[0].max.z,
82 );
83
84 let res = _mm_and_ps(
86 _mm_and_ps(
87 _mm_and_ps(
88 _mm_cmple_ps(t_min_x, o_max_x),
89 _mm_cmple_ps(o_min_x, t_max_x),
90 ),
91 _mm_and_ps(
92 _mm_cmple_ps(t_min_y, o_max_y),
93 _mm_cmple_ps(o_min_y, t_max_y),
94 ),
95 ),
96 _mm_and_ps(
97 _mm_cmple_ps(t_min_z, o_max_z),
98 _mm_cmple_ps(o_min_z, t_max_z),
99 ),
100 );
101
102 _mm_movemask_ps(res) as u8
103 }
104}
105
106#[cfg(not(target_arch = "x86_64"))]
107#[inline]
108pub fn aabb_overlaps_simd4(target: &Aabb, others: [&Aabb; 4]) -> u8 {
109 let mut mask = 0u8;
110 for (i, other) in others.iter().enumerate() {
111 if aabb_overlaps(target, other) {
112 mask |= 1 << i;
113 }
114 }
115 mask
116}
117
118#[inline]
120fn aabb_overlaps(a: &Aabb, b: &Aabb) -> bool {
121 a.min.x <= b.max.x
122 && b.min.x <= a.max.x
123 && a.min.y <= b.max.y
124 && b.min.y <= a.max.y
125 && a.min.z <= b.max.z
126 && b.min.z <= a.max.z
127}
128
129#[inline]
131fn surface_area(a: &Aabb) -> f32 {
132 let d = Vec3::new(a.max.x - a.min.x, a.max.y - a.min.y, a.max.z - a.min.z);
133 2.0 * (d.x * d.y + d.y * d.z + d.z * d.x)
134}
135
136#[inline]
138fn merge_aabb(a: &Aabb, b: &Aabb) -> Aabb {
139 Aabb {
140 min: Vec3::new(
141 a.min.x.min(b.min.x),
142 a.min.y.min(b.min.y),
143 a.min.z.min(b.min.z),
144 )
145 .into(),
146 max: Vec3::new(
147 a.max.x.max(b.max.x),
148 a.max.y.max(b.max.y),
149 a.max.z.max(b.max.z),
150 )
151 .into(),
152 }
153}
154
155#[inline]
157fn fatten(aabb: &Aabb, margin: f32) -> Aabb {
158 Aabb {
159 min: Vec3::new(
160 aabb.min.x - margin,
161 aabb.min.y - margin,
162 aabb.min.z - margin,
163 )
164 .into(),
165 max: Vec3::new(
166 aabb.max.x + margin,
167 aabb.max.y + margin,
168 aabb.max.z + margin,
169 )
170 .into(),
171 }
172}
173
174#[inline]
177fn aabb_contains(outer: &Aabb, inner: &Aabb) -> bool {
178 inner.min.x >= outer.min.x
179 && inner.min.y >= outer.min.y
180 && inner.min.z >= outer.min.z
181 && inner.max.x <= outer.max.x
182 && inner.max.y <= outer.max.y
183 && inner.max.z <= outer.max.z
184}
185
186const NULL: usize = usize::MAX;
191
192#[derive(Clone)]
193struct Node {
194 aabb: Aabb,
195 parent: usize,
196 left: usize,
197 right: usize,
198 entity: Option<Entity>, height: i32, }
201
202impl Node {
203 #[inline]
204 fn is_leaf(&self) -> bool {
205 self.left == NULL
206 }
207}
208
209impl Default for Node {
210 fn default() -> Self {
211 Self {
212 aabb: Aabb {
213 min: Vec3::ZERO.into(),
214 max: Vec3::ZERO.into(),
215 },
216 parent: NULL,
217 left: NULL,
218 right: NULL,
219 entity: None,
220 height: -1,
221 }
222 }
223}
224
225pub struct DynamicAabbTree {
230 nodes: Vec<Node>,
231 root: usize,
232 free_list: usize,
233 entity_map: HashMap<u32, usize>,
234 tight_aabbs: HashMap<u32, Aabb>,
235 fat_margin: f32,
236}
237
238impl Default for DynamicAabbTree {
239 fn default() -> Self {
240 Self::new()
241 }
242}
243
244impl DynamicAabbTree {
245 pub fn new() -> Self {
246 Self {
247 nodes: Vec::with_capacity(256),
248 root: NULL,
249 free_list: NULL,
250 entity_map: HashMap::new(),
251 tight_aabbs: HashMap::new(),
252 fat_margin: 0.1,
253 }
254 }
255
256 pub fn with_fat_margin(mut self, margin: f32) -> Self {
257 self.fat_margin = margin;
258 self
259 }
260
261 pub fn clear(&mut self) {
262 self.nodes.clear();
263 self.root = NULL;
264 self.free_list = NULL;
265 self.entity_map.clear();
266 self.tight_aabbs.clear();
267 }
268
269 pub fn entity_count(&self) -> usize {
270 self.entity_map.len()
271 }
272
273 fn alloc_node(&mut self) -> usize {
276 if self.free_list != NULL {
277 let idx = self.free_list;
278 self.free_list = self.nodes[idx].parent; self.nodes[idx] = Node::default();
280 idx
281 } else {
282 let idx = self.nodes.len();
283 self.nodes.push(Node::default());
284 idx
285 }
286 }
287
288 fn free_node(&mut self, idx: usize) {
289 self.nodes[idx] = Node {
291 height: -1,
292 parent: self.free_list, ..Default::default()
294 };
295 self.free_list = idx;
296 }
297
298 pub fn insert(&mut self, entity: Entity, aabb: Aabb) {
301 if let Some(&node_idx) = self.entity_map.get(&entity.id()) {
304 let fat = self.nodes[node_idx].aabb;
305 if aabb_contains(&fat, &aabb) {
306 self.tight_aabbs.insert(entity.id(), aabb);
307 return;
308 }
309 self.remove(entity);
310 }
311
312 self.tight_aabbs.insert(entity.id(), aabb);
313 let fat_aabb = fatten(&aabb, self.fat_margin);
314
315 let leaf = self.alloc_node();
316 self.nodes[leaf].aabb = fat_aabb;
317 self.nodes[leaf].entity = Some(entity);
318 self.nodes[leaf].height = 0;
319
320 self.insert_leaf(leaf);
321 self.entity_map.insert(entity.id(), leaf);
322 }
323
324 pub fn remove(&mut self, entity: Entity) {
325 if let Some(leaf) = self.entity_map.remove(&entity.id()) {
326 self.tight_aabbs.remove(&entity.id());
327 self.remove_leaf(leaf);
328 self.free_node(leaf);
329 }
330 }
331
332 fn insert_leaf(&mut self, leaf: usize) {
335 if self.root == NULL {
336 self.root = leaf;
337 self.nodes[leaf].parent = NULL;
338 return;
339 }
340
341 let leaf_aabb = self.nodes[leaf].aabb;
342 let sibling = self.find_best_sibling(&leaf_aabb);
343
344 let old_parent = self.nodes[sibling].parent;
345 let new_parent = self.alloc_node();
346
347 self.nodes[new_parent].parent = old_parent;
348 self.nodes[new_parent].aabb = merge_aabb(&leaf_aabb, &self.nodes[sibling].aabb);
349 self.nodes[new_parent].height = self.nodes[sibling].height + 1;
350 self.nodes[new_parent].left = sibling;
351 self.nodes[new_parent].right = leaf;
352
353 if old_parent != NULL {
354 if self.nodes[old_parent].left == sibling {
355 self.nodes[old_parent].left = new_parent;
356 } else {
357 self.nodes[old_parent].right = new_parent;
358 }
359 } else {
360 self.root = new_parent;
361 }
362
363 self.nodes[sibling].parent = new_parent;
364 self.nodes[leaf].parent = new_parent;
365
366 self.refit_ancestors(self.nodes[leaf].parent);
367 }
368
369 fn remove_leaf(&mut self, leaf: usize) {
370 if leaf == self.root {
371 self.root = NULL;
372 return;
373 }
374
375 let parent = self.nodes[leaf].parent;
376 let sibling = if self.nodes[parent].left == leaf {
377 self.nodes[parent].right
378 } else {
379 self.nodes[parent].left
380 };
381
382 let grand = self.nodes[parent].parent;
383
384 if grand != NULL {
385 if self.nodes[grand].left == parent {
386 self.nodes[grand].left = sibling;
387 } else {
388 self.nodes[grand].right = sibling;
389 }
390 self.nodes[sibling].parent = grand;
391 self.free_node(parent);
392 self.refit_ancestors(grand);
393 } else {
394 self.root = sibling;
396 self.nodes[sibling].parent = NULL;
397 self.free_node(parent);
398 }
399 }
400
401 fn refit_ancestors(&mut self, mut index: usize) {
403 while index != NULL {
404 let left = self.nodes[index].left;
405 let right = self.nodes[index].right;
406
407 self.nodes[index].height = 1 + self.nodes[left].height.max(self.nodes[right].height);
408 self.nodes[index].aabb = merge_aabb(&self.nodes[left].aabb, &self.nodes[right].aabb);
409
410 index = self.balance(index);
411 index = self.nodes[index].parent;
412 }
413 }
414
415 fn find_best_sibling(&self, leaf_aabb: &Aabb) -> usize {
422 let mut best_cost = f32::INFINITY;
423 let mut best = self.root;
424
425 let mut stack = Vec::with_capacity(32);
427 stack.push((self.root, 0.0f32));
428
429 while let Some((idx, inherited)) = stack.pop() {
430 if idx == NULL {
431 continue;
432 }
433
434 let node_sa = surface_area(&self.nodes[idx].aabb);
435 let merged_sa = surface_area(&merge_aabb(leaf_aabb, &self.nodes[idx].aabb));
436 let direct = merged_sa;
437 let total_cost = direct + inherited;
438
439 if total_cost < best_cost {
440 best_cost = total_cost;
441 best = idx;
442 }
443
444 if !self.nodes[idx].is_leaf() {
445 let child_inherited = (merged_sa - node_sa) + inherited;
448
449 let lower_bound = surface_area(leaf_aabb) + child_inherited;
451 if lower_bound < best_cost {
452 stack.push((self.nodes[idx].left, child_inherited));
453 stack.push((self.nodes[idx].right, child_inherited));
454 }
455 }
456 }
457
458 best
459 }
460
461 fn balance(&mut self, a: usize) -> usize {
465 if self.nodes[a].is_leaf() || self.nodes[a].height < 2 {
466 return a;
467 }
468
469 let b = self.nodes[a].left;
470 let c = self.nodes[a].right;
471 let balance_factor = self.nodes[c].height - self.nodes[b].height;
472
473 if balance_factor > 1 {
475 return self.rotate_left(a, b, c);
476 }
477
478 if balance_factor < -1 {
480 return self.rotate_right(a, b, c);
481 }
482
483 a
484 }
485
486 fn rotate_left(&mut self, a: usize, b: usize, c: usize) -> usize {
488 let f = self.nodes[c].left;
489 let g = self.nodes[c].right;
490
491 self.nodes[c].left = a;
493 self.nodes[c].parent = self.nodes[a].parent;
494 self.nodes[a].parent = c;
495
496 let cp = self.nodes[c].parent;
498 if cp != NULL {
499 if self.nodes[cp].left == a {
500 self.nodes[cp].left = c;
501 } else {
502 self.nodes[cp].right = c;
503 }
504 } else {
505 self.root = c;
506 }
507
508 if self.nodes[f].height > self.nodes[g].height {
510 self.nodes[c].right = f;
512 self.nodes[a].right = g;
513 self.nodes[g].parent = a;
515 self.nodes[f].parent = c; self.nodes[a].aabb = merge_aabb(&self.nodes[b].aabb, &self.nodes[g].aabb);
518 self.nodes[c].aabb = merge_aabb(&self.nodes[a].aabb, &self.nodes[f].aabb);
519 self.nodes[a].height = 1 + self.nodes[b].height.max(self.nodes[g].height);
520 self.nodes[c].height = 1 + self.nodes[a].height.max(self.nodes[f].height);
521 } else {
522 self.nodes[c].right = g;
524 self.nodes[a].right = f;
525 self.nodes[f].parent = a;
527 self.nodes[g].parent = c;
528
529 self.nodes[a].aabb = merge_aabb(&self.nodes[b].aabb, &self.nodes[f].aabb);
530 self.nodes[c].aabb = merge_aabb(&self.nodes[a].aabb, &self.nodes[g].aabb);
531 self.nodes[a].height = 1 + self.nodes[b].height.max(self.nodes[f].height);
532 self.nodes[c].height = 1 + self.nodes[a].height.max(self.nodes[g].height);
533 }
534
535 c
536 }
537
538 fn rotate_right(&mut self, a: usize, b: usize, c: usize) -> usize {
540 let d = self.nodes[b].left;
541 let e = self.nodes[b].right;
542
543 self.nodes[b].left = a;
545 self.nodes[b].parent = self.nodes[a].parent;
546 self.nodes[a].parent = b;
547
548 let bp = self.nodes[b].parent;
549 if bp != NULL {
550 if self.nodes[bp].left == a {
551 self.nodes[bp].left = b;
552 } else {
553 self.nodes[bp].right = b;
554 }
555 } else {
556 self.root = b;
557 }
558
559 if self.nodes[d].height > self.nodes[e].height {
560 self.nodes[b].right = d;
562 self.nodes[a].left = e;
563 self.nodes[e].parent = a;
565 self.nodes[d].parent = b;
566
567 self.nodes[a].aabb = merge_aabb(&self.nodes[c].aabb, &self.nodes[e].aabb);
568 self.nodes[b].aabb = merge_aabb(&self.nodes[a].aabb, &self.nodes[d].aabb);
569 self.nodes[a].height = 1 + self.nodes[c].height.max(self.nodes[e].height);
570 self.nodes[b].height = 1 + self.nodes[a].height.max(self.nodes[d].height);
571 } else {
572 self.nodes[b].right = e;
574 self.nodes[a].left = d;
575 self.nodes[d].parent = a;
577 self.nodes[e].parent = b;
578
579 self.nodes[a].aabb = merge_aabb(&self.nodes[c].aabb, &self.nodes[d].aabb);
580 self.nodes[b].aabb = merge_aabb(&self.nodes[a].aabb, &self.nodes[e].aabb);
581 self.nodes[a].height = 1 + self.nodes[c].height.max(self.nodes[d].height);
582 self.nodes[b].height = 1 + self.nodes[a].height.max(self.nodes[e].height);
583 }
584
585 b
586 }
587
588 pub fn query_pairs(&self) -> Vec<(Entity, Entity)> {
594 let mut pairs = Vec::new();
595 if self.root == NULL || self.nodes[self.root].is_leaf() {
596 return pairs;
597 }
598
599 let root_left = self.nodes[self.root].left;
602 let root_right = self.nodes[self.root].right;
603 let mut stack = Vec::with_capacity(128);
604 stack.push((root_left, root_right));
605
606 while let Some((a, b)) = stack.pop() {
611 if a == NULL || b == NULL {
612 continue;
613 }
614
615 if !aabb_overlaps(&self.nodes[a].aabb, &self.nodes[b].aabb) {
617 continue;
618 }
619
620 let a_leaf = self.nodes[a].is_leaf();
621 let b_leaf = self.nodes[b].is_leaf();
622
623 match (a_leaf, b_leaf) {
624 (true, true) => {
625 if let (Some(ea), Some(eb)) = (self.nodes[a].entity, self.nodes[b].entity) {
627 let pair = if ea.id() < eb.id() {
628 (ea, eb)
629 } else {
630 (eb, ea)
631 };
632 pairs.push(pair);
633 }
634 }
635 (true, false) => {
636 stack.push((a, self.nodes[b].left));
638 stack.push((a, self.nodes[b].right));
639 }
640 (false, true) => {
641 stack.push((self.nodes[a].left, b));
643 stack.push((self.nodes[a].right, b));
644 }
645 (false, false) => {
646 if surface_area(&self.nodes[a].aabb) >= surface_area(&self.nodes[b].aabb) {
648 stack.push((self.nodes[a].left, b));
649 stack.push((self.nodes[a].right, b));
650 } else {
651 stack.push((a, self.nodes[b].left));
652 stack.push((a, self.nodes[b].right));
653 }
654 }
655 }
656 }
657
658 self.collect_internal_pairs(&mut pairs);
661
662 pairs
663 }
664
665 fn collect_internal_pairs(&self, pairs: &mut Vec<(Entity, Entity)>) {
668 if self.root == NULL {
669 return;
670 }
671 let mut stack = vec![self.root];
672 while let Some(idx) = stack.pop() {
673 if self.nodes[idx].is_leaf() {
674 continue;
675 }
676 let l = self.nodes[idx].left;
677 let r = self.nodes[idx].right;
678 self.descent_pair(l, r, pairs);
680 stack.push(l);
681 stack.push(r);
682 }
683 }
684
685 fn descent_pair(&self, a: usize, b: usize, pairs: &mut Vec<(Entity, Entity)>) {
686 if a == NULL || b == NULL {
687 return;
688 }
689 if !aabb_overlaps(&self.nodes[a].aabb, &self.nodes[b].aabb) {
690 return;
691 }
692
693 let a_leaf = self.nodes[a].is_leaf();
694 let b_leaf = self.nodes[b].is_leaf();
695
696 match (a_leaf, b_leaf) {
697 (true, true) => {
698 if let (Some(ea), Some(eb)) = (self.nodes[a].entity, self.nodes[b].entity) {
699 let pair = if ea.id() < eb.id() {
700 (ea, eb)
701 } else {
702 (eb, ea)
703 };
704 if !pairs.contains(&pair) {
705 pairs.push(pair);
706 }
707 }
708 }
709 (true, false) => {
710 self.descent_pair(a, self.nodes[b].left, pairs);
711 self.descent_pair(a, self.nodes[b].right, pairs);
712 }
713 (false, true) => {
714 self.descent_pair(self.nodes[a].left, b, pairs);
715 self.descent_pair(self.nodes[a].right, b, pairs);
716 }
717 (false, false) => {
718 if surface_area(&self.nodes[a].aabb) >= surface_area(&self.nodes[b].aabb) {
719 self.descent_pair(self.nodes[a].left, b, pairs);
720 self.descent_pair(self.nodes[a].right, b, pairs);
721 } else {
722 self.descent_pair(a, self.nodes[b].left, pairs);
723 self.descent_pair(a, self.nodes[b].right, pairs);
724 }
725 }
726 }
727 }
728
729 pub fn query_aabb(&self, aabb: &Aabb) -> Vec<Entity> {
731 let mut result = Vec::new();
732 if self.root == NULL {
733 return result;
734 }
735
736 let mut stack = vec![self.root];
737 while let Some(idx) = stack.pop() {
738 if !aabb_overlaps(&self.nodes[idx].aabb, aabb) {
739 continue;
740 }
741 if self.nodes[idx].is_leaf() {
742 if let Some(e) = self.nodes[idx].entity {
743 result.push(e);
744 }
745 } else {
746 stack.push(self.nodes[idx].left);
747 stack.push(self.nodes[idx].right);
748 }
749 }
750
751 result
752 }
753
754 pub fn query_ray(&self, origin: Vec3, dir: Vec3, max_t: f32) -> Vec<(Entity, f32)> {
756 let mut result = Vec::new();
757 if self.root == NULL {
758 return result;
759 }
760
761 let inv_dir = Vec3::new(
762 if dir.x.abs() > 1e-8 {
763 1.0 / dir.x
764 } else {
765 f32::INFINITY
766 },
767 if dir.y.abs() > 1e-8 {
768 1.0 / dir.y
769 } else {
770 f32::INFINITY
771 },
772 if dir.z.abs() > 1e-8 {
773 1.0 / dir.z
774 } else {
775 f32::INFINITY
776 },
777 );
778
779 let mut stack = vec![self.root];
780 while let Some(idx) = stack.pop() {
781 if let Some(t) = ray_aabb_inv(origin, inv_dir, &self.nodes[idx].aabb, max_t) {
782 if self.nodes[idx].is_leaf() {
783 if let Some(e) = self.nodes[idx].entity {
784 result.push((e, t));
785 }
786 } else {
787 stack.push(self.nodes[idx].left);
788 stack.push(self.nodes[idx].right);
789 }
790 }
791 }
792
793 result.sort_unstable_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
794 result
795 }
796
797 #[cfg(debug_assertions)]
801 pub fn validate(&self) {
802 if self.root != NULL {
803 self.validate_node(self.root, NULL);
804 }
805 }
806
807 #[cfg(debug_assertions)]
808 fn validate_node(&self, idx: usize, expected_parent: usize) {
809 let node = &self.nodes[idx];
810 assert_eq!(node.parent, expected_parent, "Node {} parent yanlış", idx);
811 assert!(node.height >= 0, "Aktif node height negatif: {}", idx);
812
813 if node.is_leaf() {
814 assert!(node.entity.is_some(), "Yaprak node entity yok: {}", idx);
815 assert_eq!(node.height, 0);
816 } else {
817 let l = node.left;
818 let r = node.right;
819 assert!(l != NULL && r != NULL, "Internal node çocuksuz: {}", idx);
820
821 let expected_height = 1 + self.nodes[l].height.max(self.nodes[r].height);
822 assert_eq!(node.height, expected_height, "Node {} height yanlış", idx);
823
824 self.validate_node(l, idx);
825 self.validate_node(r, idx);
826 }
827 }
828}
829
830#[inline]
837fn ray_aabb_inv(origin: Vec3, inv_dir: Vec3, aabb: &Aabb, max_t: f32) -> Option<f32> {
838 let tx1 = (aabb.min.x - origin.x) * inv_dir.x;
839 let tx2 = (aabb.max.x - origin.x) * inv_dir.x;
840 let ty1 = (aabb.min.y - origin.y) * inv_dir.y;
841 let ty2 = (aabb.max.y - origin.y) * inv_dir.y;
842 let tz1 = (aabb.min.z - origin.z) * inv_dir.z;
843 let tz2 = (aabb.max.z - origin.z) * inv_dir.z;
844
845 let tmin = tx1.min(tx2).max(ty1.min(ty2)).max(tz1.min(tz2));
847 let tmax = tx1.max(tx2).min(ty1.max(ty2)).min(tz1.max(tz2));
848
849 if tmax < 0.0 || tmin > tmax || tmin > max_t {
850 None
851 } else {
852 Some(tmin.max(0.0)) }
854}
855
856pub struct SpatialHash {
863 tree: DynamicAabbTree,
864}
865
866impl Default for SpatialHash {
867 fn default() -> Self {
868 Self::new(10.0)
869 }
870}
871
872impl SpatialHash {
873 pub fn new(_cell_size: f32) -> Self {
874 Self {
875 tree: DynamicAabbTree::new(),
876 }
877 }
878
879 pub fn clear(&mut self) {
881 self.tree.clear();
882 }
883
884 pub fn insert(&mut self, entity: Entity, aabb: Aabb) {
885 self.tree.insert(entity, aabb);
886 }
887
888 pub fn update(&mut self, entity: Entity, aabb: Aabb) {
889 self.tree.insert(entity, aabb);
890 }
891
892 pub fn remove(&mut self, entity: Entity) {
893 self.tree.remove(entity);
894 }
895
896 pub fn query_pairs(&self) -> Vec<(Entity, Entity)> {
897 self.tree.query_pairs()
898 }
899
900 pub fn query_aabb(&self, aabb: Aabb) -> Vec<Entity> {
901 self.tree.query_aabb(&aabb)
902 }
903
904 pub fn query_point(&self, point: Vec3, radius: f32) -> Vec<Entity> {
905 let aabb = Aabb {
906 min: Vec3::new(point.x - radius, point.y - radius, point.z - radius).into(),
907 max: Vec3::new(point.x + radius, point.y + radius, point.z + radius).into(),
908 };
909 self.tree.query_aabb(&aabb)
910 }
911
912 pub fn query_ray(&self, origin: Vec3, dir: Vec3, max_t: f32) -> Vec<(Entity, f32)> {
913 self.tree.query_ray(origin, dir, max_t)
914 }
915}
916
917#[cfg(test)]
922mod tests {
923 use super::*;
924
925 fn make_entity(id: u32) -> Entity {
926 Entity::new(id, 0)
927 }
928
929 fn make_aabb(cx: f32, cy: f32, cz: f32, r: f32) -> Aabb {
930 Aabb::from_center_half_extents(Vec3::new(cx, cy, cz), Vec3::splat(r))
931 }
932
933 #[test]
934 fn test_insert_query_pairs_basic() {
935 let mut tree = DynamicAabbTree::new();
936 let e1 = make_entity(1);
937 let e2 = make_entity(2);
938 let e3 = make_entity(3);
939
940 tree.insert(e1, make_aabb(0.0, 0.0, 0.0, 1.0));
941 tree.insert(e2, make_aabb(1.0, 0.0, 0.0, 1.0)); tree.insert(e3, make_aabb(100.0, 0.0, 0.0, 1.0)); let pairs = tree.query_pairs();
945
946 let has_12 = pairs
947 .iter()
948 .any(|&(a, b)| (a == e1 && b == e2) || (a == e2 && b == e1));
949 let has_13 = pairs
950 .iter()
951 .any(|&(a, b)| (a == e1 && b == e3) || (a == e3 && b == e1));
952
953 assert!(has_12, "e1-e2 çifti bulunamadı: {:?}", pairs);
954 assert!(!has_13, "e1-e3 yanlış çifti var: {:?}", pairs);
955 }
956
957 #[test]
958 fn test_no_self_pair() {
959 let mut tree = DynamicAabbTree::new();
960 tree.insert(make_entity(1), make_aabb(0.0, 0.0, 0.0, 1.0));
961 assert!(tree.query_pairs().is_empty(), "Self-pair üretilmemeli");
962 }
963
964 #[test]
965 fn test_no_duplicate_pairs() {
966 let mut tree = DynamicAabbTree::new();
967 for i in 0..8 {
968 tree.insert(make_entity(i), make_aabb(i as f32 * 0.5, 0.0, 0.0, 1.0));
969 }
970 let pairs = tree.query_pairs();
971 let mut seen = std::collections::HashSet::new();
972 for &(a, b) in &pairs {
973 let key = (a.id().min(b.id()), a.id().max(b.id()));
974 assert!(seen.insert(key), "Duplicate çift: ({}, {})", a.id(), b.id());
975 }
976 }
977
978 #[test]
979 fn test_remove() {
980 let mut tree = DynamicAabbTree::new();
981 let e1 = make_entity(1);
982 let e2 = make_entity(2);
983 tree.insert(e1, make_aabb(0.0, 0.0, 0.0, 1.0));
984 tree.insert(e2, make_aabb(0.5, 0.0, 0.0, 1.0));
985 tree.remove(e1);
986 assert!(
987 tree.query_pairs().is_empty(),
988 "Silinen entity hâlâ çift üretiyor"
989 );
990 assert_eq!(tree.entity_count(), 1);
991 }
992
993 #[test]
994 fn test_fat_aabb_no_rebuild() {
995 let mut tree = DynamicAabbTree::new();
996 let e = make_entity(1);
997 tree.insert(e, make_aabb(0.0, 0.0, 0.0, 1.0));
998 let initial_node = tree.entity_map[&e.id()];
999 tree.insert(e, make_aabb(0.05, 0.0, 0.0, 1.0));
1001 let after_node = tree.entity_map[&e.id()];
1002 assert_eq!(initial_node, after_node, "Küçük harekette node değişmemeli");
1003 }
1004
1005 #[test]
1006 fn test_query_aabb() {
1007 let mut tree = DynamicAabbTree::new();
1008 let e1 = make_entity(1);
1009 let e2 = make_entity(2);
1010 tree.insert(e1, make_aabb(0.0, 0.0, 0.0, 1.0));
1011 tree.insert(e2, make_aabb(10.0, 0.0, 0.0, 1.0));
1012
1013 let query = make_aabb(0.5, 0.0, 0.0, 0.5);
1014 let result = tree.query_aabb(&query);
1015 assert!(result.contains(&e1), "e1 sorgu sonucunda olmalı");
1016 assert!(!result.contains(&e2), "e2 sorgu sonucunda olmamalı");
1017 }
1018
1019 #[test]
1020 fn test_query_ray() {
1021 let mut tree = DynamicAabbTree::new();
1022 let e1 = make_entity(1);
1023 let e2 = make_entity(2);
1024 tree.insert(e1, make_aabb(5.0, 0.0, 0.0, 1.0));
1025 tree.insert(e2, make_aabb(0.0, 10.0, 0.0, 1.0)); let hits = tree.query_ray(Vec3::ZERO, Vec3::new(1.0, 0.0, 0.0), 100.0);
1028 assert!(hits.iter().any(|(e, _)| *e == e1), "Ray e1'e isabet etmeli");
1029 assert!(
1030 !hits.iter().any(|(e, _)| *e == e2),
1031 "Ray e2'ye isabet etmemeli"
1032 );
1033
1034 for i in 1..hits.len() {
1036 assert!(
1037 hits[i].1 >= hits[i - 1].1,
1038 "Ray sonuçları t'ye göre sıralı olmalı"
1039 );
1040 }
1041 }
1042
1043 #[test]
1044 fn test_ray_origin_inside_aabb() {
1045 let mut tree = DynamicAabbTree::new();
1047 let e = make_entity(1);
1048 tree.insert(e, make_aabb(0.0, 0.0, 0.0, 5.0));
1049 let hits = tree.query_ray(Vec3::ZERO, Vec3::new(1.0, 0.0, 0.0), 100.0);
1050 assert!(!hits.is_empty(), "Origin AABB içindeyken ray isabet etmeli");
1051 }
1052
1053 #[test]
1054 fn test_spatial_hash_compat() {
1055 let mut sh = SpatialHash::new(10.0);
1056 let e1 = make_entity(1);
1057 let e2 = make_entity(2);
1058 sh.insert(e1, make_aabb(0.0, 0.0, 0.0, 1.0));
1059 sh.insert(e2, make_aabb(1.0, 0.0, 0.0, 1.0));
1060 sh.clear(); assert_eq!(sh.query_pairs().len(), 0);
1062 }
1063
1064 #[test]
1065 fn test_many_entities_no_crash() {
1066 let mut tree = DynamicAabbTree::new();
1067 for i in 0..100 {
1068 tree.insert(make_entity(i), make_aabb((i as f32) * 0.3, 0.0, 0.0, 0.5));
1069 }
1070 let pairs = tree.query_pairs();
1071 assert!(!pairs.is_empty(), "Yakın nesneler çift üretmeli");
1073 }
1074
1075 #[cfg(debug_assertions)]
1076 #[test]
1077 fn test_validate_after_operations() {
1078 let mut tree = DynamicAabbTree::new();
1079 for i in 0..20 {
1080 tree.insert(make_entity(i), make_aabb(i as f32, 0.0, 0.0, 0.6));
1081 }
1082 tree.validate();
1083 tree.remove(make_entity(5));
1084 tree.remove(make_entity(10));
1085 tree.validate();
1086 }
1087}