src/SimpleKDTree.cpp

Go to the documentation of this file.
00001 
00002 #include "SimpleKDTree.h"
00003 #include "Node.h"
00004 #include "Primitive.h"
00005 
00006 
00009 SimpleKDTree::~SimpleKDTree()
00010 {
00011 }
00012 
00013 
00019 void SimpleKDTree::buildTree(   const PrimitiveList &   list,
00020                                 const Box &             bbox )
00021 {
00022     KDTree::buildTree(list, bbox);
00023 
00024     // create the tree recursively
00025     buildTree(mRootNode, 0);
00026 
00027     LOG("Building kd-tree done");
00028 }
00029 
00030 
00036 void SimpleKDTree::setBestSplit(Node * node) const
00037 {
00038     if (!node)
00039         return;
00040 
00041     // set split axis
00042     switch (node->splitAxis())
00043     {
00044         case X_AXIS:    node->setSplitAxis(Y_AXIS);
00045                         break;
00046         case Y_AXIS:    node->setSplitAxis(Z_AXIS);
00047                         break;
00048         case Z_AXIS:
00049         case NO_AXIS:   node->setSplitAxis(X_AXIS);
00050     }
00051 
00052     // to find a location for the split plane we use the method of arithmetic average value.
00053     // Hence we compute the average value of the prmitive's location
00054     // and set this as the split plane
00055     // This is a bad heuristic. Optimize it later if you like
00056     float avg = 0.0;
00057     for (unsigned int i=0; i < node->primitives_count(); i++)
00058     {
00059         avg += (node->primitive(i)->bounds().minVertex()[node->splitAxis()]
00060                 + node->primitive(i)->bounds().maxVertex()[node->splitAxis()]) * 0.5;
00061     }
00062 
00063     node->setSplitPlane(avg / node->primitives_count());
00064 }
00065 
00066 
00072 void SimpleKDTree::buildTree(   Node *          node,
00073                                 unsigned int    depth ) const
00074 {
00075     assert(node);
00076     assert(!node->left());
00077     assert(!node->right());
00078 
00079     float f = 0;
00080     if (terminate(node, f, depth))
00081     {
00082         // make leaf node
00083         node->setSplitAxis(NO_AXIS);
00084         return;
00085     }
00086 
00087     // setup node's split axis and plane
00088     setBestSplit(node);
00089 
00090     // create both children
00091     Node * left     = new Node();
00092     Node * right    = new Node();
00093     node->setLeftRight(left, right);
00094     left->setSplitAxis(node->splitAxis());
00095     right->setSplitAxis(node->splitAxis());
00096 
00097     // check based on the split plane where to put the primitives
00098     for (unsigned int i=0; i < node->primitives_count(); i++)
00099     {
00100         const Box & box = node->primitive(i)->bounds();
00101 
00102         if (box.minVertex()[node->splitAxis()] >= node->splitPlane())
00103         {
00104             // if primitive lies completly on the right side
00105             right->add(node->primitive(i));
00106         }
00107         else if (box.maxVertex()[node->splitAxis()] <= node->splitPlane())
00108         {
00109             // if primitive lies completly on the left side
00110             left->add(node->primitive(i));
00111         }
00112         else
00113         {
00114             // for the rest of cases we just put the primitive in both subtrees
00115             left->add(node->primitive(i));
00116             right->add(node->primitive(i));
00117         }
00118     }
00119 
00120     // clear the node's primitive list, since now the childrens do contain them
00121     node->clear_primitives();
00122 
00123     // setup subtrees
00124     buildTree(left, depth + 1);
00125     buildTree(right, depth + 1);
00126 }
00127 
00128 

Generated on Fri Feb 1 00:01:42 2008 for Grayfall by  doxygen 1.5.1