BBox LWObject::Face::getBBox() const { BBox ret = BBox::empty(); ret.extend(m_lwObject->vertices[vert1]); ret.extend(m_lwObject->vertices[vert2]); ret.extend(m_lwObject->vertices[vert3]); return ret; }
//An iterative split in the middle build for BVHs void BVH::build(const std::vector<Primitive*> &_objects) { std::vector<BBox> objectBBoxes(_objects.size()); BuildStateStruct curState; curState.centroidBBox = BBox::empty(); std::vector<CentroidWithID> centroids(objectBBoxes.size()); for(size_t i = 0; i < objectBBoxes.size(); i++) { objectBBoxes[i] = _objects[i]->getBBox(); centroids[i].centroid = objectBBoxes[i].min.lerp(objectBBoxes[i].max, 0.5f); centroids[i].origIndex = i; curState.centroidBBox.extend(centroids[i].centroid); } curState.segmentStart = 0; curState.segmentEnd = objectBBoxes.size(); curState.nodeIndex = 0; m_nodes.resize(1); std::stack<BuildStateStruct> buildStack; const float _EPS = 0.0000001f; for(;;) { size_t objCnt = curState.segmentEnd - curState.segmentStart; Vector boxDiag = curState.centroidBBox.diagonal(); int splitDim = boxDiag.x > boxDiag.y ? (boxDiag.x > boxDiag.z ? 0 : 2) : (boxDiag.y > boxDiag.z ? 1 : 2); if(fabs(boxDiag[splitDim]) < _EPS || objCnt < 3) { //Create a leaf const size_t NODE_TYPE_MASK = ((size_t)1 << Node::LEAF_FLAG_BIT); m_nodes[curState.nodeIndex].bbox = BBox::empty(); m_nodes[curState.nodeIndex].dataIndex = m_leafData.size() | NODE_TYPE_MASK; for(size_t i = curState.segmentStart; i < curState.segmentEnd; i++) { m_nodes[curState.nodeIndex].bbox.extend(objectBBoxes[centroids[i].origIndex]); m_leafData.push_back(_objects[centroids[i].origIndex]); } m_leafData.push_back(NULL); if(buildStack.empty()) break; curState = buildStack.top(); buildStack.pop(); continue; } float splitVal = (curState.centroidBBox.min[splitDim] + curState.centroidBBox.max[splitDim]) / 2.f; size_t leftPtr = curState.segmentStart, rightPtr = curState.segmentEnd - 1; BBox nodeBBox = BBox::empty(); BuildStateStruct rightState; curState.centroidBBox = BBox::empty(); rightState.centroidBBox = BBox::empty(); while(leftPtr < rightPtr) { while(leftPtr < curState.segmentEnd && centroids[leftPtr].centroid[splitDim] <= splitVal) { curState.centroidBBox.extend(centroids[leftPtr].centroid); nodeBBox.extend(objectBBoxes[centroids[leftPtr].origIndex]); leftPtr++; } while(rightPtr >= curState.segmentStart && centroids[rightPtr].centroid[splitDim] > splitVal) { rightState.centroidBBox.extend(centroids[rightPtr].centroid); nodeBBox.extend(objectBBoxes[centroids[rightPtr].origIndex]); rightPtr--; } if(leftPtr >= rightPtr) break; std::swap(centroids[leftPtr], centroids[rightPtr]); } m_nodes[curState.nodeIndex].bbox = nodeBBox; m_nodes[curState.nodeIndex].dataIndex = m_nodes.size(); _ASSERT(leftPtr > curState.segmentStart && leftPtr < curState.segmentEnd); _ASSERT(leftPtr == rightPtr + 1); rightState.segmentStart = leftPtr; rightState.segmentEnd = curState.segmentEnd; curState.segmentEnd = leftPtr; curState.nodeIndex = m_nodes.size(); rightState.nodeIndex = curState.nodeIndex + 1; buildStack.push(rightState); m_nodes.resize(rightState.nodeIndex + 1); } }