Beispiel #1
0
// BVHAccel Method Definitions
BVHAccel::BVHAccel(const std::vector<std::shared_ptr<Primitive>> &p,
                   int maxPrimsInNode, SplitMethod splitMethod)
    : maxPrimsInNode(std::min(255, maxPrimsInNode)),
      primitives(p),
      splitMethod(splitMethod) {
    StatTimer buildTime(&constructionTime);
    if (primitives.size() == 0) return;
    // Build BVH from _primitives_

    // Initialize _primitiveInfo_ array for primitives
    std::vector<BVHPrimitiveInfo> primitiveInfo(primitives.size());
    for (size_t i = 0; i < primitives.size(); ++i)
        primitiveInfo[i] = {i, primitives[i]->WorldBound()};

    // Build BVH tree for primitives using _primitiveInfo_
    MemoryArena arena(1024 * 1024);
    int totalNodes = 0;
    std::vector<std::shared_ptr<Primitive>> orderedPrims;
    orderedPrims.reserve(primitives.size());
    BVHBuildNode *root;
    if (splitMethod == SplitMethod::HLBVH)
        root = HLBVHBuild(arena, primitiveInfo, &totalNodes, orderedPrims);
    else
        root = recursiveBuild(arena, primitiveInfo, 0, primitives.size(),
                              &totalNodes, orderedPrims);
    primitives.swap(orderedPrims);
    Info("BVH created with %d nodes for %d primitives (%.2f MB)", totalNodes,
         (int)primitives.size(),
         float(totalNodes * sizeof(LinearBVHNode)) / (1024.f * 1024.f));

    // Compute representation of depth-first traversal of BVH tree
    treeBytes += totalNodes * sizeof(LinearBVHNode) + sizeof(*this) +
                 primitives.size() * sizeof(primitives[0]);
    nodes = AllocAligned<LinearBVHNode>(totalNodes);
    int offset = 0;
    flattenBVHTree(root, &offset);
    Assert(offset == totalNodes);
}
CBVH_PBRT::CBVH_PBRT( const CGENERICCONTAINER &aObjectContainer,
                      int aMaxPrimsInNode,
                      SPLITMETHOD aSplitMethod ) :
    m_maxPrimsInNode( std::min( 255, aMaxPrimsInNode ) ),
    m_splitMethod( aSplitMethod )
{
    if( aObjectContainer.GetList().empty() )
    {
        m_nodes = NULL;

        return;
    }

    // Initialize the indexes of ray packet for partition traversal
    for( unsigned int i = 0; i < RAYPACKET_RAYS_PER_PACKET; ++i )
    {
        m_I[i] = i;
    }

    // Convert the objects list to vector of objects
    // /////////////////////////////////////////////////////////////////////////
    aObjectContainer.ConvertTo( m_primitives );

    wxASSERT( aObjectContainer.GetList().size() == m_primitives.size() );

    // Initialize _primitiveInfo_ array for primitives
    // /////////////////////////////////////////////////////////////////////////
    std::vector<BVHPrimitiveInfo> primitiveInfo( m_primitives.size() );

    for( size_t i = 0; i < m_primitives.size(); ++i )
    {
        wxASSERT( m_primitives[i]->GetBBox().IsInitialized() );

        primitiveInfo[i] = BVHPrimitiveInfo( i, m_primitives[i]->GetBBox() );
    }

    // Build BVH tree for primitives using _primitiveInfo_
    int totalNodes = 0;

    CONST_VECTOR_OBJECT orderedPrims;
    orderedPrims.clear();
    orderedPrims.reserve( m_primitives.size() );

    BVHBuildNode *root;

    if( m_splitMethod == SPLIT_HLBVH )
        root = HLBVHBuild( primitiveInfo, &totalNodes, orderedPrims);
    else
        root = recursiveBuild( primitiveInfo, 0, m_primitives.size(),
                               &totalNodes, orderedPrims);

    wxASSERT( m_primitives.size() == orderedPrims.size() );

    m_primitives.swap( orderedPrims );

    // Compute representation of depth-first traversal of BVH tree
    m_nodes = static_cast<LinearBVHNode *>( _mm_malloc( sizeof( LinearBVHNode ) *
                                                        totalNodes,
                                                        L1_CACHE_LINE_SIZE ) );
    m_addresses_pointer_to_mm_free.push_back( m_nodes );

    for( int i = 0; i < totalNodes; ++i )
    {
        m_nodes[i].bounds.Reset();
        m_nodes[i].primitivesOffset = 0;
        m_nodes[i].nPrimitives = 0;
        m_nodes[i].axis = 0;
    }

    uint32_t offset = 0;

    flattenBVHTree( root, &offset );

    wxASSERT( offset == (unsigned int)totalNodes );

#ifdef PRINT_STATISTICS_3D_VIEWER
    uint32_t treeBytes = totalNodes * sizeof( LinearBVHNode ) + sizeof( *this ) +
                         m_primitives.size() * sizeof( m_primitives[0] ) +
                         m_addresses_pointer_to_mm_free.size() * sizeof( void * );

    printf( "////////////////////////////////////////////////////////////////////////////////\n" );
    printf( "Creating a CBVH_PBRT from %u objects ", (unsigned int)m_primitives.size() );

    switch( m_splitMethod )
    {
    case SPLIT_MIDDLE:      printf( "using SPLIT_MIDDLE\n" ); break;
    case SPLIT_EQUALCOUNTS: printf( "using SPLIT_EQUALCOUNTS\n" ); break;
    case SPLIT_SAH:         printf( "using SPLIT_SAH\n" ); break;
    case SPLIT_HLBVH:       printf( "using SPLIT_HLBVH\n" ); break;
    }

    printf( "  BVH created with %d nodes (%.2f MB)\n",
            totalNodes, float(treeBytes) / (1024.f * 1024.f) );
    printf( "////////////////////////////////////////////////////////////////////////////////\n\n" );
#endif
}