42{
44 {
45
46 stats.updateLeaf(depth, right - left + 1);
48 return;
49 }
50
51 int axis = -1, prevAxis, rightOrig;
52 float clipL = G3D::fnan(), clipR = G3D::fnan(), prevClip = G3D::fnan();
53 float split = G3D::fnan(), prevSplit;
54 bool wasLeft = true;
55 while (true)
56 {
57 prevAxis = axis;
58 prevSplit = split;
59
60 G3D::Vector3 d( gridBox.
hi - gridBox.
lo );
61 if (d.x < 0 || d.y < 0 || d.z < 0)
62 {
63 throw std::logic_error("negative node extents");
64 }
65 for (int i = 0; i < 3; i++)
66 {
67 if (nodeBox.
hi[i] < gridBox.
lo[i] || nodeBox.
lo[i] > gridBox.
hi[i])
68 {
69
70 throw std::logic_error("invalid node overlap");
71 }
72 }
73
74 axis = d.primaryAxis();
75 split = 0.5f * (gridBox.
lo[axis] + gridBox.
hi[axis]);
76
77 clipL = -G3D::inf();
78 clipR = G3D::inf();
79 rightOrig = right;
80 float nodeL = G3D::inf();
81 float nodeR = -G3D::inf();
82 for (int i = left; i <= right;)
83 {
84 int obj = dat.indices[i];
85 float minb = dat.primBound[obj].low()[axis];
86 float maxb = dat.primBound[obj].high()[axis];
87 float center = (minb + maxb) * 0.5f;
88 if (center <= split)
89 {
90
91 i++;
92 if (clipL < maxb)
93 {
94 clipL = maxb;
95 }
96 }
97 else
98 {
99
100 int t = dat.indices[i];
101 dat.indices[i] = dat.indices[right];
102 dat.indices[right] = t;
103 right--;
104 if (clipR > minb)
105 {
106 clipR = minb;
107 }
108 }
109 nodeL = std::min(nodeL, minb);
110 nodeR = std::max(nodeR, maxb);
111 }
112
113 if (nodeL > nodeBox.
lo[axis] && nodeR < nodeBox.
hi[axis])
114 {
115 float nodeBoxW = nodeBox.
hi[axis] - nodeBox.
lo[axis];
116 float nodeNewW = nodeR - nodeL;
117
118 if (1.3f * nodeNewW < nodeBoxW)
119 {
120 stats.updateBVH2();
121 int nextIndex = tempTree.size();
122
123 tempTree.push_back(0);
124 tempTree.push_back(0);
125 tempTree.push_back(0);
126
127 stats.updateInner();
128 tempTree[nodeIndex + 0] = (axis << 30) | (1 << 29) | nextIndex;
131
132 nodeBox.
lo[axis] = nodeL;
133 nodeBox.
hi[axis] = nodeR;
134 subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex, depth + 1, stats);
135 return;
136 }
137 }
138
139 if (right == rightOrig)
140 {
141
142 if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split))
143 {
144
145 stats.updateLeaf(depth, right - left + 1);
147 return;
148 }
149 if (clipL <= split)
150 {
151
152 gridBox.
hi[axis] = split;
153 prevClip = clipL;
154 wasLeft = true;
155 continue;
156 }
157 gridBox.
hi[axis] = split;
158 prevClip = G3D::fnan();
159 }
160 else if (left > right)
161 {
162
163 right = rightOrig;
164 if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split))
165 {
166
167 stats.updateLeaf(depth, right - left + 1);
169 return;
170 }
171 if (clipR >= split)
172 {
173
174 gridBox.
lo[axis] = split;
175 prevClip = clipR;
176 wasLeft = false;
177 continue;
178 }
179 gridBox.
lo[axis] = split;
180 prevClip = G3D::fnan();
181 }
182 else
183 {
184
185 if (prevAxis != -1 && !
isnan(prevClip))
186 {
187
188
189 int nextIndex = tempTree.size();
190
191 tempTree.push_back(0);
192 tempTree.push_back(0);
193 tempTree.push_back(0);
194 if (wasLeft)
195 {
196
197
198 stats.updateInner();
199 tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex;
202 }
203 else
204 {
205
206
207 stats.updateInner();
208 tempTree[nodeIndex + 0] = (prevAxis << 30) | (nextIndex - 3);
211 }
212
213 depth++;
214 stats.updateLeaf(depth, 0);
215
216 nodeIndex = nextIndex;
217 }
218 break;
219 }
220 }
221
222 int nextIndex = tempTree.size();
223
224 int nl = right - left + 1;
225 int nr = rightOrig - (right + 1) + 1;
226 if (nl > 0)
227 {
228 tempTree.push_back(0);
229 tempTree.push_back(0);
230 tempTree.push_back(0);
231 }
232 else
233 {
234 nextIndex -= 3;
235 }
236
237 if (nr > 0)
238 {
239 tempTree.push_back(0);
240 tempTree.push_back(0);
241 tempTree.push_back(0);
242 }
243
244 stats.updateInner();
245 tempTree[nodeIndex + 0] = (axis << 30) | nextIndex;
248
249 AABound gridBoxL(gridBox), gridBoxR(gridBox);
250 AABound nodeBoxL(nodeBox), nodeBoxR(nodeBox);
251 gridBoxL.hi[axis] = gridBoxR.lo[axis] = split;
252 nodeBoxL.hi[axis] = clipL;
253 nodeBoxR.lo[axis] = clipR;
254
255 if (nl > 0)
256 {
257 subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats);
258 }
259 else
260 {
261 stats.updateLeaf(depth + 1, 0);
262 }
263 if (nr > 0)
264 {
265 subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats);
266 }
267 else
268 {
269 stats.updateLeaf(depth + 1, 0);
270 }
271}
#define isnan
Definition: BoundingIntervalHierarchy.cpp:23
G3D::Vector3 hi
Definition: BoundingIntervalHierarchy.h:56
G3D::Vector3 lo
Definition: BoundingIntervalHierarchy.h:56
void createNode(std::vector< uint32 > &tempTree, int nodeIndex, uint32 left, uint32 right) const
Definition: BoundingIntervalHierarchy.h:425