-
Notifications
You must be signed in to change notification settings - Fork 0
/
TraversalTree.h
119 lines (89 loc) · 4.5 KB
/
TraversalTree.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//
// Created by ivb on 30.03.17.
//
#ifndef RAY_TRACING_KDTREE_H
#define RAY_TRACING_KDTREE_H
#include "Shape.h"
class TraversalTree {
public:
TraversalTree();
// построить дерево по списку объектов
void build_from_shapes(const std::vector<Shape*> &_shapes);
// наити ближайшее пересечение луча с объектом
bool traverse(Point3D p, Point3D v, Point3D *nearest_intersection, Shape **object);
private:
// узел дерева
struct Node;
// событие начала или конца границы примитива
// используется при поиске наилучшего разбиения узла
struct Event;
// ось, перпендикулярно поторой проводится разбиение
enum SPLIT_TYPE {BY_X = 0, BY_Y, BY_Z};
// корень дерева
Node *root;
// поиск первого пересечения луча с объектом сцены
bool traverse_routine(Node *node, Point3D p, Point3D v,
Point3D *nearest_intersection, Shape **object);
// перебор объектов в узле в поисках первого пересечения
bool traverse_scan(Node *node, Point3D p, Point3D v,
Point3D *nearest_intersection, Shape **object);;
// строит поддерево с корнем в node
void build_node(Node *node, SPLIT_TYPE stp);
// производит разбиение узла на два дочерних
// возвращает true, если разбиение было произведено
// устанавливает значения left->A, left->B, right->A, right->B
bool split_node(Node *node, SPLIT_TYPE stp);
// записывает в поле node->shapes все объекты, ограничивающий
// параллелепипед которых пересекается с таковым узла
template<typename Iterator>
void fill_node_shapes(Node *node, Iterator beg, Iterator end, ld best);
// построить массив событий
void build_event_array(Node *node, std::vector<Event> *events, SPLIT_TYPE stp);
// наити наилучшее разбиение соответствующее некоторому событию
// вернуть итератор этого события в массиве событий
// возвращает false, если разбиение не нужно производить
bool best_split(const std::vector<Event> &events, ld xmin, ld xmax, ld *min);
// заполнить поля, соответствующие ограничивающим объемам в потомках узла
// в соответствии с лучшим разбиением
void fill_boxes(Node *node, ld x, SPLIT_TYPE stp);
// создать объект события для объекта соответствующего типа
std::pair<Event, Event> make_events(Shape *obj, SPLIT_TYPE stp);
// граници ограничивающей области
void get_limits(Node *node, ld *xmin, ld *xmax, SPLIT_TYPE stp);
// задает границы узла в соответствии со списком его примитивов
void set_limiting_box(Node *node);
// упорядочивает узлы по расстоянию до точки p
void sort_nodes(Point3D p, Node* &first, Node* &second);
};
struct TraversalTree::Node {
Node() :
left(nullptr),
right(nullptr),
leaf(true)
{
A = {0, 0, 0};
B = {0, 0, 0};
}
// левый дочерний узел
Node *left;
// правый дочерний узел
Node *right;
// противоположные по диагонали вершины
Point3D A;
Point3D B;
// true если узел является листом
bool leaf;
// объекты узла
// не пуст если и только если leaf == true
std::vector<Shape*> shapes;
};
struct TraversalTree::Event {
// координата события
ld x;
// примитив, событие для которого отслеживается
Shape *obj;
// тип события
// первое событие в массиве событий всегда начало примитива
bool type;
};
#endif //RAY_TRACING_KDTREE_H