int CBVH_PBRT::flattenBVHTree( BVHBuildNode *node, uint32_t *offset ) { LinearBVHNode *linearNode = &m_nodes[*offset]; linearNode->bounds = node->bounds; int myOffset = (*offset)++; if( node->nPrimitives > 0 ) { wxASSERT( (!node->children[0]) && (!node->children[1]) ); wxASSERT( node->nPrimitives < 65536 ); linearNode->primitivesOffset = node->firstPrimOffset; linearNode->nPrimitives = node->nPrimitives; } else { // Creater interior flattened BVH node linearNode->axis = node->splitAxis; linearNode->nPrimitives = 0; flattenBVHTree( node->children[0], offset ); linearNode->secondChildOffset = flattenBVHTree( node->children[1], offset ); } return myOffset; }
uint32_t BVHAccel::flattenBVHTree(BVHBuildNode *node, uint32_t *offset) { LinearBVHNode *linearNode = &nodes[*offset]; linearNode->bounds = node->bounds; uint32_t myOffset = (*offset)++; if (node->nPrimitives > 0) { Assert(!node->children[0] && !node->children[1]); linearNode->primitivesOffset = node->firstPrimOffset; linearNode->nPrimitives = node->nPrimitives; } else { // Creater interior flattened BVH node linearNode->axis = node->splitAxis; linearNode->nPrimitives = 0; flattenBVHTree(node->children[0], offset); linearNode->secondChildOffset = flattenBVHTree(node->children[1], offset); } return myOffset; }
// BVHAccel Method Definitions BVHAccel::BVHAccel(const vector<Reference<Primitive> > &p, uint32_t mp, const string &sm) { maxPrimsInNode = min(255u, mp); for (uint32_t i = 0; i < p.size(); ++i) p[i]->FullyRefine(primitives); if (sm == "sah") splitMethod = SPLIT_SAH; else if (sm == "middle") splitMethod = SPLIT_MIDDLE; else if (sm == "equal") splitMethod = SPLIT_EQUAL_COUNTS; else { Warning("BVH split method \"%s\" unknown. Using \"sah\".", sm.c_str()); splitMethod = SPLIT_SAH; } if (primitives.size() == 0) { nodes = NULL; return; } // Build BVH from _primitives_ PBRT_BVH_STARTED_CONSTRUCTION(this, primitives.size()); // Initialize _buildData_ array for primitives vector<BVHPrimitiveInfo> buildData; buildData.reserve(primitives.size()); for (uint32_t i = 0; i < primitives.size(); ++i) { BBox bbox = primitives[i]->WorldBound(); buildData.push_back(BVHPrimitiveInfo(i, bbox)); } // Recursively build BVH tree for primitives MemoryArena buildArena; uint32_t totalNodes = 0; vector<Reference<Primitive> > orderedPrims; orderedPrims.reserve(primitives.size()); BVHBuildNode *root = recursiveBuild(buildArena, buildData, 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 nodes = AllocAligned<LinearBVHNode>(totalNodes); for (uint32_t i = 0; i < totalNodes; ++i) new (&nodes[i]) LinearBVHNode; uint32_t offset = 0; flattenBVHTree(root, &offset); Assert(offset == totalNodes); PBRT_BVH_FINISHED_CONSTRUCTION(this); //printf("done creating bvh with %d nodes for %d primitives\n", totalNodes, (int)primitives.size()); }
// 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 }