std::vector buildBVH4()

in libraries/hvvr/shared/bvh.cpp [427:467]


std::vector<Box4> buildBVH4(std::vector<Box2>& node2s) {
    std::vector<Box4> nodePlus4s((node2s.size() + 2) / 3);

    // Collapse the 2-BVH to a 4-BVH.  Note: out is updated by the helper function.
    Box4* out = nodePlus4s.data() + nodePlus4s.size();
    BoxPlus cache[3];
    uint32_t cacheSize = helpBuildBVH4(out, node2s.data(), cache, 0);

    // Check to see if we need to process the root separately.
    if (cacheSize == 1) {
        if (nodePlus4s.data() != out)
            fail("Internal consistency LogFatalure with respect to BVH4 normalization.");
        return nodePlus4s;
    }

    // Allocate a new box from the output list.
    BoxPlus* outBoxes = (--out)->boxes;
    if (nodePlus4s.data() != out)
        fail("Internal consistency LogFatalure with respect to BVH4 normalization.");

    // Add some empty boxes to fill up the output;
    BoxPlus empty = {};
    for (uint32_t extra = 4 - cacheSize; extra; --extra)
        *outBoxes++ = empty;

    // Add these boxes to the root.
    for (uint32_t i = 0; i < cacheSize; i++) {
        // Update the cache offsets.
        if (cache[i].offset)
            cache[i].offset -= (uint32_t)(out - (Box4*)nullptr);
        *outBoxes++ = cache[i];
    }

    // Sort each box such that the leaves are first and nodes of the same type are sorted by surface area.
    std::sort(out->boxes, out->boxes + 4, [](const BoxPlus& a, const BoxPlus& b) {
        return (a.offset == 0 && b.offset != 0) ||
               ((a.offset == 0 || b.offset != 0) && a.box.surfaceArea() > b.box.surfaceArea());
    });

    return nodePlus4s;
}