// pick best split plane among all possible splits float Bvh::pickBestSplit( unsigned& axis , float& split_pos , Bvh_Node* node , unsigned _start , unsigned _end ) { BBox inner; for( unsigned i = _start ; i < _end ; i++ ) inner.Union( m_bvhpri[i].m_centroid ); unsigned tri_num = _end - _start; axis = inner.MaxAxisId(); float min_sah = FLT_MAX; // distribute the triangles into bins unsigned bin[BVH_SPLIT_COUNT]; BBox bbox[BVH_SPLIT_COUNT]; BBox rbox[BVH_SPLIT_COUNT-1]; memset( bin , 0 , sizeof( unsigned ) * BVH_SPLIT_COUNT ); float split_start = inner.m_Min[axis]; float split_delta = inner.Delta(axis) * BVH_INV_SPLIT_COUNT; float inv_split_delta = 1.0f / split_delta; for( unsigned i = _start ; i < _end ; i++ ){ int index = (int)((m_bvhpri[i].m_centroid[axis] - split_start) * inv_split_delta); index = min( index , (int)(BVH_SPLIT_COUNT - 1) ); bin[index]++; bbox[index].Union( m_bvhpri[i].GetBBox() ); } rbox[BVH_SPLIT_COUNT-2].Union( bbox[BVH_SPLIT_COUNT-1] ); for( int i = BVH_SPLIT_COUNT-3; i >= 0 ; i-- ) rbox[i] = Union( rbox[i+1] , bbox[i+1] ); unsigned left = bin[0]; BBox lbox = bbox[0]; float pos = split_delta + split_start ; for( unsigned i = 0 ; i < BVH_SPLIT_COUNT - 1 ; i++ ){ float sah_value = sah( left , tri_num - left , lbox , rbox[i] , node->bbox ); if( sah_value < min_sah ){ min_sah = sah_value; split_pos = pos; } left += bin[i+1]; lbox.Union( bbox[i+1] ); pos += split_delta; } return min_sah; }
bool Collision::collide(const BBox &targetBound, const Matrix4D &treeMat, const KdAccelNode* treeNode, const KdTreeAccel* tree, BBox* &collisionBound, vector<Point3D*> &primpts) { if (!collideP(treeNode->bbox, treeMat, targetBound)) { return false; } // If collideP check if node is leaf if (!treeNode->isLeaf()) { auto belowNode = treeNode->belowNode; auto aboveNode = treeNode->aboveNode; bool res = collide(targetBound, treeMat, belowNode, tree, collisionBound, primpts); //if (!res) { res |= collide(targetBound, treeMat, aboveNode, tree, collisionBound, primpts); } return res; } else// If node is leaf { /*collisionBound = new BBox(treeNode->bbox); return true;*/ BBox* imBox = new BBox; treeNode->primIndex; vector<Point3D*> curPrimPts; for (auto idx : treeNode->primIndex) { auto prim = dynamic_cast<Triangle*>(tree->primitives[idx]); for (auto pt : prim->p) { auto wPt = new Point3D((treeMat * Vector4D(*pt, 1.0)).toVector3D()); imBox->Union(*wPt); curPrimPts.push_back(wPt); //primpts.push_back(wPt); } } if (collideP(*imBox, targetBound)) { collisionBound = imBox; //primpts.push_back(curPrimPts); primpts.insert(primpts.end(), curPrimPts.begin(), curPrimPts.end()); return true; } for (auto pt : curPrimPts) { delete pt; } curPrimPts.clear(); delete imBox; return false; } }