1 | #include "BvhConstructor.h"
|
---|
2 | #include "Triangle3.h"
|
---|
3 | #include "SceneEntity.h"
|
---|
4 | #include "Geometry.h"
|
---|
5 | #include "gzstream.h"
|
---|
6 |
|
---|
7 | #include <queue>
|
---|
8 | #include <stack>
|
---|
9 | #include <fstream>
|
---|
10 |
|
---|
11 | #ifdef _CRT_SET
|
---|
12 | #define _CRTDBG_MAP_ALLOC
|
---|
13 | #include <stdlib.h>
|
---|
14 | #include <crtdbg.h>
|
---|
15 |
|
---|
16 | // redefine new operator
|
---|
17 | #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
|
---|
18 | #define new DEBUG_NEW
|
---|
19 | #endif
|
---|
20 |
|
---|
21 |
|
---|
22 | using namespace std;
|
---|
23 |
|
---|
24 |
|
---|
25 | namespace CHCDemoEngine
|
---|
26 | {
|
---|
27 |
|
---|
28 | BvhConstructor::BvhConstructor(SceneEntity **entities,
|
---|
29 | int first,
|
---|
30 | int last):
|
---|
31 | mEntities(entities),
|
---|
32 | mFirst(first),
|
---|
33 | mLast(last),
|
---|
34 | mMaxDepth(10),
|
---|
35 | mMaxObjects(1),
|
---|
36 | mNumNodes(0)
|
---|
37 | {
|
---|
38 | }
|
---|
39 |
|
---|
40 |
|
---|
41 | int BvhConstructor::SortTriangles(BvhLeaf *leaf,
|
---|
42 | int axis,
|
---|
43 | float position
|
---|
44 | )
|
---|
45 | {
|
---|
46 | int i = leaf->mFirst;
|
---|
47 | int j = leaf->mLast;
|
---|
48 |
|
---|
49 | while (1)
|
---|
50 | {
|
---|
51 | //while (mEntities[i]->GetWorldCenter()[axis] < position) ++ i;
|
---|
52 | //while (position < mEntities[j]->GetWorldCenter()[axis]) -- j;
|
---|
53 |
|
---|
54 | while ((i < leaf->mLast) && (mEntities[i]->GetWorldCenter()[axis] < position)) ++ i;
|
---|
55 | while ((j > leaf->mFirst) && (position < mEntities[j]->GetWorldCenter()[axis])) -- j;
|
---|
56 |
|
---|
57 | // sorting finished
|
---|
58 | if (i >= j) break;
|
---|
59 |
|
---|
60 | // swap entities
|
---|
61 | swap(mEntities[i], mEntities[j]);
|
---|
62 |
|
---|
63 | ++ i;
|
---|
64 | -- j;
|
---|
65 | }
|
---|
66 |
|
---|
67 | return j;
|
---|
68 | }
|
---|
69 |
|
---|
70 |
|
---|
71 | int BvhConstructor::SortTrianglesSpatialMedian(BvhLeaf *leaf,
|
---|
72 | int axis)
|
---|
73 | {
|
---|
74 | // spatial median
|
---|
75 | float m = leaf->GetBox().Center()[axis];
|
---|
76 | return SortTriangles(leaf, axis, m);
|
---|
77 | }
|
---|
78 |
|
---|
79 |
|
---|
80 | BvhNode *BvhConstructor::SubdivideLeaf(BvhLeaf *leaf,
|
---|
81 | int parentAxis
|
---|
82 | )
|
---|
83 | {
|
---|
84 | if (TerminationCriteriaMet(leaf))
|
---|
85 | {
|
---|
86 | if (leaf->CountPrimitives() <= 0)
|
---|
87 | cout << "leaf constructed:" << leaf->mBox << " " << leaf->mFirst << " " << leaf->mLast << endl;
|
---|
88 | return leaf;
|
---|
89 | }
|
---|
90 |
|
---|
91 | //const int axis = (parentAxis + 1) % 3;
|
---|
92 | const int axis = leaf->mBox.MajorAxis();
|
---|
93 | const int scale = 20;
|
---|
94 |
|
---|
95 | // position of the split in the partailly sorted array of triangles
|
---|
96 | // corresponding to this leaf
|
---|
97 | int split = -1;
|
---|
98 | float pos = -1.0f;
|
---|
99 |
|
---|
100 | // Spatial median subdivision
|
---|
101 | split = SortTrianglesSpatialMedian(leaf, axis);
|
---|
102 | pos = leaf->mBox.Center()[axis];
|
---|
103 |
|
---|
104 | if (split == leaf->mLast)
|
---|
105 | {
|
---|
106 | // no split could be achieved => just halve number of objects
|
---|
107 | split = (leaf->mLast + leaf->mFirst) / 2;
|
---|
108 | cerr << "no reduction " << leaf->CountPrimitives() << " " << leaf->mFirst << " " << leaf->mLast << endl;
|
---|
109 | }
|
---|
110 |
|
---|
111 | // create two more nodes
|
---|
112 | mNumNodes += 2;
|
---|
113 | BvhInterior *parent = new BvhInterior(leaf->GetParent());
|
---|
114 | parent->mFirst = leaf->mFirst;
|
---|
115 | parent->mLast = leaf->mLast;
|
---|
116 |
|
---|
117 | parent->mAxis = axis;
|
---|
118 | parent->mBox = leaf->mBox;
|
---|
119 | parent->mDepth = leaf->mDepth;
|
---|
120 |
|
---|
121 | BvhLeaf *front = new BvhLeaf(parent);
|
---|
122 |
|
---|
123 | parent->mBack = leaf;
|
---|
124 | parent->mFront = front;
|
---|
125 |
|
---|
126 | // now assign the triangles to the subnodes
|
---|
127 | front->mFirst = split + 1;
|
---|
128 | front->mLast = leaf->mLast;
|
---|
129 | front->mDepth = leaf->mDepth + 1;
|
---|
130 |
|
---|
131 | leaf->mLast = split;
|
---|
132 | leaf->mDepth = front->mDepth;
|
---|
133 | leaf->mParent = parent;
|
---|
134 |
|
---|
135 | front->mBox = SceneEntity::ComputeBoundingBox(mEntities + front->mFirst, front->CountPrimitives());
|
---|
136 | leaf->mBox = SceneEntity::ComputeBoundingBox(mEntities + leaf->mFirst, leaf->CountPrimitives());
|
---|
137 |
|
---|
138 | // recursively continue subdivision
|
---|
139 | parent->mBack = SubdivideLeaf(static_cast<BvhLeaf *>(parent->mBack), axis);
|
---|
140 | parent->mFront = SubdivideLeaf(static_cast<BvhLeaf *>(parent->mFront), axis);
|
---|
141 |
|
---|
142 | return parent;
|
---|
143 | }
|
---|
144 |
|
---|
145 |
|
---|
146 | bool BvhConstructor::TerminationCriteriaMet(BvhLeaf *leaf) const
|
---|
147 | {
|
---|
148 | const bool criteriaMet =
|
---|
149 | (leaf->mDepth > mMaxDepth) ||
|
---|
150 | (leaf->CountPrimitives() <= mMaxObjects);
|
---|
151 |
|
---|
152 | return criteriaMet;
|
---|
153 | }
|
---|
154 |
|
---|
155 |
|
---|
156 | BvhNode *BvhConstructor::Construct(int &numNodes)
|
---|
157 | {
|
---|
158 | BvhNode *root;
|
---|
159 |
|
---|
160 | mNumNodes = 1;
|
---|
161 |
|
---|
162 | BvhLeaf *l = new BvhLeaf(NULL);
|
---|
163 |
|
---|
164 | l->mBox = SceneEntity::ComputeBoundingBox(mEntities + mFirst, mFirst - mLast + 1);
|
---|
165 |
|
---|
166 | l->mFirst = mFirst;
|
---|
167 | l->mLast = mLast;
|
---|
168 | l->mArea = l->mBox.SurfaceArea();
|
---|
169 |
|
---|
170 | cout << "constructing bvh" << endl;
|
---|
171 |
|
---|
172 | root = SubdivideLeaf(l, 0);
|
---|
173 |
|
---|
174 | numNodes = mNumNodes;
|
---|
175 |
|
---|
176 | return root;
|
---|
177 | }
|
---|
178 |
|
---|
179 |
|
---|
180 | } |
---|