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