00001
00002 #include <algorithm>
00003 #include <map>
00004
00005 #include "SAHKDTree.h"
00006 #include "Node.h"
00007 #include "Event.h"
00008 #include "SplitPlane.h"
00009 #include "Primitive.h"
00010
00011
00014 SAHKDTree::~SAHKDTree()
00015 {
00016 }
00017
00018
00024 void SAHKDTree::buildTree( const PrimitiveList & list,
00025 const Box & bbox )
00026 {
00027 KDTree::buildTree(list, bbox);
00028
00029
00030 EventList events;
00031 PrimitiveList::const_iterator it = list.begin();
00032 for (; it != list.end(); ++it)
00033 {
00034 generateEvents(events, *it, bbox);
00035 }
00036 std::sort(events.begin(), events.end());
00037
00038
00039 buildTree(mRootNode, bbox, events, 0);
00040
00041 LOG("Building kd-tree done");
00042 }
00043
00044
00052 void SAHKDTree::buildTree( Node * node,
00053 const Box & bbox,
00054 EventList & events,
00055 unsigned int depth ) const
00056 {
00057 assert(node);
00058 assert(!node->left());
00059 assert(!node->right());
00060
00061
00062 float minCost = INFINITY;
00063 SplitPlane bestPlane = findBestPlane(minCost, node, bbox, events);
00064
00065
00066
00067
00068
00069
00070 if (terminate(node, minCost, depth))
00071 {
00072
00073 node->setSplitAxis(NO_AXIS);
00074 return;
00075 }
00076 assert(events.size() > 0);
00077
00078
00079 node->setSplitPlane(bestPlane.position());
00080 node->setSplitAxis(bestPlane.direction());
00081
00082
00083 Node * left = new Node();
00084 Node * right = new Node();
00085 node->setLeftRight(left, right);
00086
00087
00088 EventList eLeft;
00089 EventList eRight;
00090
00091
00092 std::pair<Box, Box> boxes = classifyAndSplice(eLeft, eRight, node, bbox, events, bestPlane);
00093
00094
00095 node->clear_primitives();
00096 events.clear();
00097
00098
00099 buildTree(left, boxes.first, eLeft, depth + 1);
00100 buildTree(right, boxes.second, eRight, depth + 1);
00101 }
00102
00103
00114 bool SAHKDTree::terminate( const Node * current,
00115 float minCost,
00116 unsigned int depth ) const
00117 {
00118 return KDTree::terminate(current, minCost, depth) || minCost > mKIntersect * current->primitives_count();
00119 }
00120
00121
00133 float SAHKDTree::SAH( Side & side,
00134 const Box & bbox,
00135 const SplitPlane & plane,
00136 unsigned int number_left,
00137 unsigned int number_right,
00138 unsigned int number_middle ) const
00139 {
00140 float probability_left = bbox.area(plane);
00141 float probability_right = 1.0f - probability_left;
00142 float left_cost = cost(probability_left, probability_right, number_left + number_middle, number_right);
00143 float right_cost = cost(probability_left, probability_right, number_left, number_right + number_middle);
00144
00145 if (left_cost < right_cost)
00146 {
00147 side = S_LEFT;
00148 return left_cost;
00149 }
00150 else
00151 {
00152 side = S_RIGHT;
00153 return right_cost;
00154 }
00155 }
00156
00157
00158
00169 SplitPlane SAHKDTree::findBestPlane( float & minCost,
00170 const Node * node,
00171 const Box & bbox,
00172 const EventList & events ) const
00173 {
00174
00175 unsigned int NL[3];
00176 unsigned int NP[3];
00177 unsigned int NR[3];
00178
00179
00180 for (int k=0; k<3; k++)
00181 {
00182 NL[k] = NP[k] = 0;
00183 NR[k] = node->primitives_count();
00184 }
00185
00186 SplitPlane plane;
00187 minCost = INFINITY;
00188
00189
00190 EventList::const_iterator it = events.begin();
00191 while (it != events.end())
00192 {
00193 unsigned int p_end = 0;
00194 unsigned int p_planar = 0;
00195 unsigned int p_start = 0;
00196
00197 SplitPlane p = it->plane();
00198
00199
00200 while (it != events.end()
00201 && p.direction() == it->plane().direction()
00202 && p.position() <= it->plane().position()
00203 && it->type() == ET_END)
00204 {
00205 ++p_end;
00206 ++it;
00207 }
00208 while (it != events.end()
00209 && p.direction() == it->plane().direction()
00210 && p.position() <= it->plane().position()
00211 && it->type() == ET_PLANAR)
00212 {
00213 ++p_planar;
00214 ++it;
00215 }
00216 while (it != events.end()
00217 && p.direction() == it->plane().direction()
00218 && p.position() <= it->plane().position()
00219 && it->type() == ET_START)
00220 {
00221 ++p_start;
00222 ++it;
00223 }
00224
00225
00226 NP[p.direction()] = p_planar;
00227 NR[p.direction()] -= p_planar + p_end;
00228
00229
00230 Side side;
00231 float cost = SAH(side, bbox, p, NL[p.direction()], NR[p.direction()], NP[p.direction()]);
00232
00233
00234 if (cost < minCost
00235 && bbox.minVertex()[p.direction()] + EPSILON < p.position()
00236 && p.position() < bbox.maxVertex()[p.direction()] - EPSILON)
00237 {
00238 plane = p;
00239 minCost = cost;
00240 plane.setSide(side);
00241 }
00242
00243
00244 NL[p.direction()] += p_planar + p_start;
00245 NP[p.direction()] = 0;
00246 }
00247
00248 return plane;
00249 }
00250
00251
00258 void SAHKDTree::generateEvents( EventList & events,
00259 Primitive * primitive,
00260 const Box & bbox ) const
00261 {
00262 Box b = primitive->bounds().clip(bbox);
00263 for (int k=0; k<3; k++)
00264 {
00265
00266 if (b.minVertex()[k] >= b.maxVertex()[k] - EPSILON)
00267 {
00268 events.push_back(Event(primitive, SplitPlane(b.minVertex()[k], Axis(k)), ET_PLANAR));
00269 }
00270 else
00271 {
00272 events.push_back(Event(primitive, SplitPlane(b.minVertex()[k], Axis(k)), ET_START));
00273 events.push_back(Event(primitive, SplitPlane(b.maxVertex()[k], Axis(k)), ET_END));
00274 }
00275 }
00276 }
00277
00278
00291 std::pair<Box, Box> SAHKDTree::classifyAndSplice( EventList & eLeft,
00292 EventList & eRight,
00293 Node * node,
00294 const Box & bbox,
00295 const EventList & events,
00296 const SplitPlane & plane ) const
00297 {
00298
00299 std::map<Primitive *, Side> prims;
00300 for (unsigned int i=0; i<node->primitives_count(); i++)
00301 {
00302 prims[node->primitive(i)] = S_BOTH;
00303 }
00304 assert(node->primitives_count() == prims.size());
00305
00306
00307
00308
00309
00310
00311 EventList::const_iterator it = events.begin();
00312 for (; it != events.end(); ++it)
00313 {
00314 if (it->type() == ET_END
00315 && it->plane().direction() == plane.direction()
00316 && it->plane().position() <= plane.position())
00317 {
00318
00319 prims[it->primitive()] = S_LEFT;
00320 }
00321 else if (it->type() == ET_START
00322 && it->plane().direction() == plane.direction()
00323 && it->plane().position() >= plane.position())
00324 {
00325
00326 prims[it->primitive()] = S_RIGHT;
00327 }
00328 else if (it->type() == ET_PLANAR
00329 && it->plane().direction() == plane.direction())
00330 {
00331 if (it->plane().position() < plane.position()
00332 || (it->plane().position() <= plane.position()
00333 && plane.side() == S_LEFT))
00334 {
00335
00336 prims[it->primitive()] = S_LEFT;
00337 }
00338 if (it->plane().position() > plane.position()
00339 || (it->plane().position() >= plane.position()
00340 && plane.side() == S_RIGHT))
00341 {
00342
00343 prims[it->primitive()] = S_RIGHT;
00344 }
00345 }
00346
00347 }
00348
00349
00350 for (it = events.begin(); it != events.end(); ++it)
00351 {
00352 if (prims[it->primitive()] == S_LEFT)
00353 {
00354 eLeft.push_back(*it);
00355 }
00356 else if (prims[it->primitive()] == S_RIGHT)
00357 {
00358 eRight.push_back(*it);
00359 }
00360 }
00361
00362
00363 unsigned int leftSize = eLeft.size();
00364 unsigned int rightSize = eRight.size();
00365
00366
00367 std::pair<Box, Box> boxes = bbox.split(plane);
00368
00369
00370 std::map<Primitive *, Side>::iterator mapit = prims.begin();
00371 for (; mapit != prims.end(); ++mapit)
00372 {
00373 if (mapit->second == S_LEFT)
00374 {
00375 node->left()->add(mapit->first);
00376 }
00377 else if (mapit->second == S_RIGHT)
00378 {
00379 node->right()->add(mapit->first);
00380 }
00381 else
00382 {
00383 generateEvents(eLeft, mapit->first, boxes.first);
00384 generateEvents(eRight, mapit->first, boxes.second);
00385
00386 node->left()->add(mapit->first);
00387 node->right()->add(mapit->first);
00388 }
00389 }
00390
00391
00392
00393
00394
00395 EventList::iterator leftBoth = eLeft.begin() + leftSize;
00396 EventList::iterator rightBoth = eRight.begin() + rightSize;
00397
00398
00399 assert(eLeft.begin() <= leftBoth && leftBoth <= eLeft.end());
00400 assert(eRight.begin() <= rightBoth && rightBoth <= eRight.end());
00401
00402
00403 std::sort(leftBoth, eLeft.end());
00404 std::sort(rightBoth, eRight.end());
00405 std::inplace_merge(eLeft.begin(), leftBoth, eLeft.end());
00406 std::inplace_merge(eRight.begin(), rightBoth, eRight.end());
00407
00408 return boxes;
00409 }
00410
00411