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;
}
Exemple #2
0
//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);
    }
}