BVH::BVH(ObjMesh& _mesh) { mesh = _mesh; //build work list workList.reserve(mesh.faces.size()); for(auto i = 0; i < mesh.faces.size(); ++i) workList.push_back(BVHPrimitiveInfo(i, BBox(mesh.vertices[mesh.faces[i].x], mesh.vertices[mesh.faces[i].y], mesh.vertices[mesh.faces[i].z]))); //recursive build std::cout<<"Building BVH..."<<std::endl; orderedPrims.reserve(mesh.faces.size()); root = RecursiveBuild(0, workList.size()); std::cout<<"Totoal nodes: "<<totalNodes<<std::endl; std::cout<<"Max depth: "<<maxDepth<<std::endl; //replace mesh faces order with ordered one mesh.faces.swap(orderedPrims); //build linear bvh lbvh.reserve(totalNodes); for(auto i = 0; i < totalNodes; ++i) lbvh.push_back(LBVHNode()); uint32_t offset = 0; Flatten(root, &offset); std::cout<<"Root max: ("<<lbvh[0].bMax.x<<", "<<lbvh[0].bMax.y<<", "<<lbvh[0].bMax.z<<")"<<std::endl; std::cout<<"Root min: ("<<lbvh[0].bMin.x<<", "<<lbvh[0].bMin.y<<", "<<lbvh[0].bMin.z<<")"<<std::endl; }
// 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()); }
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 }