void JRTHeuristicKDTreeBuilder::BuildTreeImpl(const JRTBoundingBox& rBounds,
                                              const std::vector<const JRTTriangle*>& rTris,
                                              std::vector<JRTKDNode>& rNodesOut,
                                              std::vector<UINT>&      rTrisOut)
{

    rNodesOut.push_back(JRTKDNode());        // create root node

    // extract triangle BBs
    BuildBBs(rTris, m_bbs);

    // extract split planes
    std::vector<Split> splits[3];

    for (int i = 0; i < 3; i++)
    {
        ExtractSplits(i, m_bbs, splits[i], rBounds);
    }

    // build vectors of pointers to these split planes for shuffling around
    SplitVec splitPtrs[3];

    for (int i = 0; i < 3; i++)
    {
        splitPtrs[i].resize(splits[i].size());

        for (int j = 0; j < (int)splits[i].size(); j++)
        {
            splitPtrs[i][j] = &splits[i][j];
        }
    }

    // build vectors of pointers to BBs, also for shuffling around
    std::vector<TriangleBB*> bbPtrs;

    for (int i = 0; i < (int)m_bbs.size(); i++)
    {
        bbPtrs.push_back(&m_bbs[i]);
    }

    BuildTreeRecursive(JRTKDTree::MAX_TREE_DEPTH, rBounds,  splitPtrs, bbPtrs,  &rNodesOut[0], rNodesOut, rTrisOut);



}
Пример #2
0
void JRTKDTreeBuilder::BuildTreeImpl(const JRTBoundingBox& rBounds,
                                     const std::vector<const JRTTriangle*>& rTris,
                                     std::vector<JRTKDNode>& rNodesOut,
                                     std::vector<UINT>& rTriIndicesOut)
{

    rNodesOut.push_back(JRTKDNode());        // create root node

    std::vector<UINT> rIndices;

    for (UINT i = 0; i < rTris.size(); i++)
    {
        rIndices.push_back(i);
    }

    // construct the tree using our naive tree building function
    BuildTreeSimple(&rNodesOut[0], rTris, rIndices, rBounds, JRTKDTree::MAX_TREE_DEPTH, rNodesOut, rTriIndicesOut);

}
Пример #3
0
void BuildTreeSimple(JRTKDNode* current_node,
                     const std::vector<const JRTTriangle*>& triangles_in,
                     const std::vector<UINT>& rIndicesIn,
                     const JRTBoundingBox& scene_bounds,
                     UINT depth_max,
                     std::vector<JRTKDNode>& nodes_out,
                     std::vector<UINT>& rTriIndicesOut)
{
    if (depth_max == 0  || rIndicesIn.size() < 25)
    {
        // make leaf
        current_node->leaf.is_leaf = true;
        current_node->leaf.triangle_start  = (UINT) rTriIndicesOut.size();
        current_node->leaf.triangle_count  = (UINT) rIndicesIn.size();

        for (UINT i = 0; i < rIndicesIn.size(); i++)
        {
            rTriIndicesOut.push_back(rIndicesIn[i]);
        }

        return;
    }


    // choose best split plane and split node bounding box
    float diffs[3];
    Axis maxcomp = X_AXIS;

    // choose split plane based on longest BBox axis
    JRTBoundingBox front_bounds(scene_bounds);
    JRTBoundingBox back_bounds(scene_bounds);

    for (int i = X_AXIS; i < Z_AXIS; i++)
    {
        diffs[i] = scene_bounds.GetMax()[i] - scene_bounds.GetMin()[i];

        if (diffs[i] > diffs[maxcomp])
        {
            maxcomp = (Axis)i;
        }
    }

    float splitval = 0.5f * diffs[maxcomp] + scene_bounds.GetMin()[maxcomp];

    front_bounds.GetMin()[maxcomp] = splitval;
    back_bounds.GetMax()[maxcomp] = splitval;


    // partition polygons
    std::vector<UINT> front_polys;
    std::vector<UINT> back_polys;
    PartitionTriangles(triangles_in, rIndicesIn, (Axis)maxcomp, splitval, front_polys, back_polys);

    // make current node an inner node
    current_node->leaf.is_leaf = false;
    current_node->inner.axis = (UBYTE)maxcomp;
    current_node->inner.position = splitval;
    current_node->inner.front_offset = (UINT)nodes_out.size();

    UINT front_child = (UINT)nodes_out.size();
    UINT back_child = (UINT)nodes_out.size() + 1;


    // always allocate left child next to right child
    nodes_out.push_back(JRTKDNode());
    nodes_out.push_back(JRTKDNode());

    // recursively continue tree construction
    BuildTreeSimple(&nodes_out[front_child],  triangles_in, front_polys, front_bounds, depth_max - 1, nodes_out, rTriIndicesOut);
    BuildTreeSimple(&nodes_out[back_child],   triangles_in, back_polys,  back_bounds, depth_max - 1, nodes_out, rTriIndicesOut);

}
void JRTHeuristicKDTreeBuilder::BuildTreeRecursive(UINT nDepthLimit,
                                                   const JRTBoundingBox& rNodeBounds,
                                                   SplitVec splits[3],
                                                   std::vector<TriangleBB*>& rBBsThisNode,
                                                   JRTKDNode* pNode,
                                                   std::vector<JRTKDNode>& rNodesOut,
                                                   std::vector<UINT>& rTrisOut)
{
    UINT nTriCount = (UINT)rBBsThisNode.size();

    JRT_ASSERT(splits[0].size() == splits[1].size() && splits[1].size() == splits[2].size());

    // initialize best cost to cost of not splitting
    float fBestCost = INTERSECT_COST * nTriCount;

    // find the optimal split
    bool bSplit = false;
    float fSplitValue;
    UINT eSplitAxis = X_AXIS;


    float fNodeBBInvArea = 1.0f / Max(0.0000001f, rNodeBounds.GetSurfaceArea());
    float fNodeVolume = rNodeBounds.GetVolume();

    for (UINT axis = X_AXIS; axis <= Z_AXIS; axis++)
    {
        LocateBestSplit(fNodeBBInvArea, rNodeBounds, splits, axis, nTriCount, fBestCost, bSplit, eSplitAxis, fSplitValue);
    }


    if (!bSplit || nDepthLimit == 0)
    {
        // we either don't want to split, or can't split, so make a leaf
        pNode->leaf.is_leaf = true;
        pNode->leaf.triangle_count = 0;
        pNode->leaf.triangle_start = (UINT)rTrisOut.size();

        for (UINT i = 0; i < rBBsThisNode.size(); i++)
        {
            // do robust tri-box clipping at the leaves
            const Vec3f* pV1 = &rBBsThisNode[i]->pTri->GetV1();
            const Vec3f* pV2 = &rBBsThisNode[i]->pTri->GetV2();
            const Vec3f* pV3 = &rBBsThisNode[i]->pTri->GetV3();

            if (rNodeBounds.TriangleIntersect(pV1, pV2, pV3))
            {
                rTrisOut.push_back(rBBsThisNode[i]->nIndex);
                pNode->leaf.triangle_count++;
            }
        }
    }
    else
    {
        // make a non-leaf

        pNode->inner.axis = eSplitAxis;
        pNode->inner.is_leaf = false;
        pNode->inner.position = fSplitValue;

        JRT_ASSERT(fSplitValue > rNodeBounds.GetMin()[eSplitAxis] &&
                   fSplitValue < rNodeBounds.GetMax()[eSplitAxis]);

        ClassifyBBs(splits[0], m_bbs, eSplitAxis, fSplitValue);

        // partition the splits
        SplitVec frontSplits[3];
        SplitVec backSplits[3];

        for (int j = X_AXIS; j <= Z_AXIS; j++)
        {
            PartitionSplits(fSplitValue, eSplitAxis, splits[j], m_bbs, backSplits[j], frontSplits[j]);

            // clear old split vec to save memory
            splits[j].clear();
        }

        // partition BBs
        std::vector<TriangleBB*> backBBs;
        std::vector<TriangleBB*> frontBBs;
        PartitionBBs(eSplitAxis, fSplitValue, rBBsThisNode, backBBs, frontBBs);

        rBBsThisNode.clear(); // save memory

        // create new nodes
        // by convention, always create front child right before back child
        pNode->inner.front_offset = (UINT)rNodesOut.size();
        UINT nFront = (UINT)rNodesOut.size();
        UINT nBack = nFront + 1;
        rNodesOut.push_back(JRTKDNode());
        rNodesOut.push_back(JRTKDNode());

        // split the node bounding box
        JRTBoundingBox front_bounds, back_bounds;
        rNodeBounds.Split(eSplitAxis, fSplitValue, front_bounds, back_bounds);

        // recursively build the subtrees
        BuildTreeRecursive(nDepthLimit - 1, front_bounds, frontSplits, frontBBs,  &rNodesOut[ nFront ], rNodesOut, rTrisOut);
        BuildTreeRecursive(nDepthLimit - 1, back_bounds,  backSplits,  backBBs, &rNodesOut[ nBack ], rNodesOut, rTrisOut);
    }
}