float KDTree::caculateCost(SplitNode *split,aabb &frontBox, aabb &backBox) { float frontArea = 2 * (frontBox.w()*frontBox.d() + frontBox.w()*frontBox.h() + frontBox.d()*frontBox.h()); float backArea = 2 * (backBox.w()*backBox.d() + backBox.w()*backBox.h() +backBox.d()*backBox.h()); return frontArea * split->nlcount+ backArea * split->nrcount; }
void ireon::kd_tree::KdTree<T>::subdivide( KdTreeNode<T>* node, const aabb& box, int depth, int a_Prims ) { // recycle used split list nodes //add sPool_ at end sList_ if (sList_) { SplitList* list = sList_; while (list->next) list = list->next; list->next = sPool_; sPool_ = sList_, sList_ = 0; } // determine split axis Vector3 s = box.getSize(); if ((s.x >= s.y) && (s.x >= s.z)) node->setAxis( 0 ); else if ((s.y >= s.x) && (s.y >= s.z)) node->setAxis( 1 ); int axis = node->getAxis(); // make a list of the split position candidates ObjectList<T>* l = node->getList(); real p1, p2; real pos1 = box.getPos().val[axis]; real pos2 = box.getPos().val[axis] + box.getSize().val[axis]; bool* pright = new bool[a_Prims]; float* eleft = new float[a_Prims], *eright = new float[a_Prims]; T** parray = new T*[a_Prims]; real etleft, etright; int aidx = 0; while (l) { T* p = parray[aidx] = l->getPrimitive(); pright[aidx] = true; etleft = eleft[aidx]; etright = eright[aidx]; p->calculateRange( etleft, etright, axis ); eleft[aidx] = (float)etleft; eright[aidx] = (float)etright; aidx++; for ( int i = 0; i < 3; i++ ) { p1 = (float)p->vertice( i )->cell[axis]; if ((p1 >= pos1) && (p1 <= pos2)) insertSplitPos( p1 ); } l = l->getNext(); } // determine n1count / n2count for each split position aabb b1, b2, b3 = box, b4 = box; SplitList* splist = sList_; float b3p1 = b3.getPos().val[axis]; float b4p2 = b4.getPos().val[axis] + b4.getSize().val[axis]; Vector3 foo; while (splist) { foo = b4.getPos(); foo.val[axis] = splist->splitpos; b4.setPos(foo); foo = b4.getSize(); foo.val[axis] = pos2 - splist->splitpos; b4.setSize(foo); foo = b3.getSize(); foo.val[axis] = splist->splitpos - pos1; b3.setSize(foo); float b3p2 = b3.getPos().val[axis] + b3.getSize().val[axis]; float b4p1 = b4.getPos().val[axis]; for ( int i = 0; i < a_Prims; i++ ) if (pright[i]) { T* p = parray[i]; if ((eleft[i] <= b3p2) && (eright[i] >= b3p1)) if (p->intersectBox( b3 )) splist->n1count++; if ((eleft[i] <= b4p2) && (eright[i] >= b4p1)) if (p->intersectBox( b4 )) splist->n2count++; else pright[i] = false; } else splist->n1count++; splist = splist->next; } delete[] pright; // calculate surface area for current node real SAV = 0.5f / (box.w() * box.d() + box.w() * box.h() + box.d() * box.h()); // calculate cost for not splitting real Cleaf = a_Prims * 1.0f; // determine optimal split plane position splist = sList_; real lowcost = 10000; real bestpos = 0; while (splist) { // calculate child node extends foo = b4.getPos(); foo.val[axis] = splist->splitpos; b4.setPos(foo); foo = b4.getSize(); foo.val[axis] = pos2 - splist->splitpos; b4.setSize(foo); foo = b3.getSize(); foo.val[axis] = splist->splitpos - pos1; b3.setSize(foo); // calculate child node cost real SA1 = 2 * (b3.w() * b3.d() + b3.w() * b3.h() + b3.d() * b3.h()); real SA2 = 2 * (b4.w() * b4.d() + b4.w() * b4.h() + b4.d() * b4.h()); real splitcost = 0.3f + 1.0f * (SA1 * SAV * splist->n1count + SA2 * SAV * splist->n2count); // update best cost tracking variables if (splitcost < lowcost) { lowcost = splitcost; bestpos = splist->splitpos; b1 = b3, b2 = b4; } splist = splist->next; } if (lowcost > Cleaf) { delete[] eleft; delete[] eright; delete[] parray; return; } node->setSplitPos( bestpos ); // construct child nodes KdTreeNode<T>* left = s_MManager->NewKdTreeNodePair(); int n1count = 0, n2count = 0, total = 0; // assign primitives to both sides float b1p1 = b1.getPos().val[axis]; float b2p2 = b2.getPos().val[axis] + b2.getSize().val[axis]; float b1p2 = b1.getPos().val[axis] + b1.getSize().val[axis]; float b2p1 = b2.getPos().val[axis]; for ( int i = 0; i < a_Prims; i++ ) { T* p = parray[i]; total++; if ((eleft[i] <= b1p2) && (eright[i] >= b1p1)) if (p->intersectBox( b1 )) { left->add( p ); n1count++; } if ((eleft[i] <= b2p2) && (eright[i] >= b2p1)) if (p->intersectBox( b2 )) { (left + 1)->add( p ); n2count++; } } delete[] eleft; delete[] eright; delete[] parray; s_MManager->FreeObjectList( node->getList() ); node->setLeft( left ); node->setLeaf( false ); if (depth < MAXTREEDEPTH) { if (n1count > 2) subdivide( left, b1, depth + 1, n1count ); if (n2count > 2) subdivide( left + 1, b2, depth + 1, n2count ); } }
float KDTree::caculateSingleVoxelCost(int numofTriangles,aabb &box) { float area = 2 * (box.w()*box.d() + box.w()*box.h() + box.d()*box.h()); return area * numofTriangles; }