void BVH::build() { Pane::info("BVH # Started building from mesh"); std::vector<BVHPrimitive> data; data.reserve(mesh->faces.size()); // TODO: reserve for primitives // Create data structures for BVH for(unsigned i = 0; i < mesh->faces.size(); i++) data.emplace_back(i, computeAABB(mesh, i)); Pane::info("BVH # Finished creating bounding volumes"); unsigned totalNodes = 0; // Build recursively BVHNode *root = buildRecursive(data, 0, mesh->faces.size(), primitives, totalNodes); Pane::info("BVH # Finished volume hierarchy build"); // Allocate linear nodes nodes.resize(totalNodes); unsigned offset = 0; flatten(root, offset); Pane::info("BVH # Finished flattening volume hierarchy"); }
void testHelperFunctions( const std::string & meshFile, const uint_t numTotalBlocks ) { auto mesh = make_shared<MeshType>(); mesh::readAndBroadcast( meshFile, *mesh); auto triDist = make_shared< mesh::TriangleDistance<MeshType> >( mesh ); auto distanceOctree = make_shared< DistanceOctree< MeshType > >( triDist ); const real_t meshVolume = real_c( computeVolume( *mesh ) ); const real_t blockVolume = meshVolume / real_c( numTotalBlocks ); static const real_t cellsPersBlock = real_t(1000); const real_t cellVolume = blockVolume / cellsPersBlock; const real_t dx = std::pow( cellVolume, real_t(1) / real_t(3) ); WALBERLA_LOG_INFO_ON_ROOT( "Creating SBF with createStructuredBlockStorageInsideMesh with block size" ); auto sbf0 = mesh::createStructuredBlockStorageInsideMesh( distanceOctree, dx, numTotalBlocks ); WALBERLA_LOG_INFO_ON_ROOT( "Creating SBF with createStructuredBlockStorageInsideMesh with block size" ); Vector3<uint_t> blockSize( sbf0->getNumberOfXCells(), sbf0->getNumberOfYCells(), sbf0->getNumberOfZCells() ); auto sbf1 = mesh::createStructuredBlockStorageInsideMesh( distanceOctree, dx, blockSize ); auto exteriorAabb = computeAABB( *mesh ).getScaled( real_t(2) ); WALBERLA_LOG_INFO_ON_ROOT( "Creating SBF with createStructuredBlockStorageInsideMesh with block size" ); auto sbf2 = mesh::createStructuredBlockStorageOutsideMesh( exteriorAabb, distanceOctree, dx, numTotalBlocks ); WALBERLA_LOG_INFO_ON_ROOT( "Creating SBF with createStructuredBlockStorageInsideMesh with block size" ); blockSize = Vector3<uint_t>( sbf2->getNumberOfXCells(), sbf2->getNumberOfYCells(), sbf2->getNumberOfZCells() ); auto sbf3 = mesh::createStructuredBlockStorageOutsideMesh( exteriorAabb, distanceOctree, dx, blockSize ); }
void run( const std::string & meshFile, const uint_t numTotalBlocks ) { auto mesh = make_shared<MeshType>(); mesh::readAndBroadcast( meshFile, *mesh); auto aabb = computeAABB( *mesh ); auto domainAABB = aabb.getScaled( typename MeshType::Scalar(1.26) ); // AABB containing the test points auto triDist = make_shared< mesh::TriangleDistance<MeshType> >( mesh ); auto distanceOctree = make_shared< DistanceOctree<MeshType> >( triDist ); Vector3<uint_t> numBlocks = math::getFactors3D( numTotalBlocks, domainAABB.sizes() ); test< ExcludeMeshExterior< DistanceOctree< MeshType > > >( distanceOctree, *mesh, domainAABB, numBlocks ); test< ExcludeMeshInterior< DistanceOctree< MeshType > > >( distanceOctree, *mesh, domainAABB, numBlocks ); }
void testAABBDistance( const Vector3<real_t> & translationVector = Vector3<real_t>() ) { auto mesh = make_shared<MeshType>(); mesh::readAndBroadcast( "cube.obj", *mesh); translate( *mesh, translationVector ); auto aabb = computeAABB( *mesh ); // works since the mesh is a cube auto testVolume = aabb.getScaled( real_t(2) ); // AABB containing the test points TriangleDistance<MeshType> triDist( mesh ); std::mt19937 rng; for( int i = 0; i < 10000; ++i ) { auto p = testVolume.randomPoint( rng ); WALBERLA_CHECK_FLOAT_EQUAL( triDist.sqSignedDistance( toOpenMesh(p) ), aabb.sqSignedDistance( p ) ); } }
bool createHull(unsigned int vcount, const float *points,NxuGeometry &g,const NxMat34 *localPose,NxReal shrink,unsigned int maxv) { bool ret = false; g.reset(); HullLibrary hl; HullDesc desc(QF_TRIANGLES, vcount, points, sizeof(float) *3); desc.mMaxVertices = maxv; HullResult result; HullError err = hl.CreateConvexHull(desc, result); if (err == QE_OK) { ret = true; g.mVertices = new float[result.mNumOutputVertices *3]; float bmin[3]; float bmax[3]; computeAABB( result.mNumOutputVertices, result.mOutputVertices, sizeof(float)*3, bmin, bmax ); NxVec3 center; center.x = (bmax[0]-bmin[0])*0.5f + bmin[0]; center.y = (bmax[1]-bmin[1])*0.5f + bmin[1]; center.z = (bmax[2]-bmin[2])*0.5f + bmin[2]; const float *source = result.mOutputVertices; float *dest = g.mVertices; for (NxU32 i=0; i<result.mNumOutputVertices; i++) { NxVec3 v(source[0],source[1],source[2]); v-=center; v*=shrink; v+=center; if ( localPose ) { NxVec3 t; localPose->multiply(v,t); v = t; } dest[0] = v.x; dest[1] = v.y; dest[2] = v.z; source+=3; dest+=3; } g.mIndices = new unsigned int[result.mNumIndices]; memcpy(g.mIndices, result.mIndices, sizeof(unsigned int) *result.mNumIndices); g.mVcount = result.mNumOutputVertices; g.mTcount = result.mNumFaces; hl.ReleaseResult(result); } return ret; }
void test( const std::string & meshFile ) { auto mesh = make_shared< MeshType >(); mesh::readAndBroadcast( meshFile, *mesh); auto aabb = computeAABB( *mesh ); using Scalar = typename MeshType::Scalar; Vector3<Scalar> translation( numeric_cast<Scalar>( aabb.xSize() ) * Scalar(2) * Scalar( MPIManager::instance()->rank() ), Scalar(0), Scalar(0) ); translate( *mesh, translation ); mesh->request_face_normals(); mesh->request_vertex_normals(); mesh->update_normals(); mesh->request_face_status(); bool b = true; for( auto it = mesh->faces_begin(); it != mesh->faces_end(); ++it ) { mesh->status( *it ).set_tagged( b ); b = !b; } mesh->request_vertex_status(); b = true; for( auto it = mesh->vertices_begin(); it != mesh->vertices_end(); ++it ) { mesh->status( *it ).set_tagged( b ); b = !b; } std::vector< typename MeshType::Color > colors; colors.push_back( typename MeshType::Color( 255,0,0 ) ); colors.push_back( typename MeshType::Color( 0,255,0 ) ); colors.push_back( typename MeshType::Color( 0,0,255 ) ); auto colorIt = colors.begin(); mesh->request_vertex_colors(); for( auto it = mesh->vertices_begin(); it != mesh->vertices_end(); ++it ) { mesh->set_color( *it, *colorIt ); ++colorIt; if( colorIt == colors.end() ) colorIt = colors.begin(); } mesh->request_face_colors(); for( auto it = mesh->faces_begin(); it != mesh->faces_end(); ++it ) { mesh->set_color( *it, *colorIt ); ++colorIt; if( colorIt == colors.end() ) colorIt = colors.begin(); } DistributedVTKMeshWriter< MeshType > meshWriter( mesh, "distributed_mesh_vtk_test_unfiltered", 1 ); meshWriter.addDataSource( make_shared< NormalsVertexDataSource< MeshType > >() ); meshWriter.addDataSource( make_shared< NormalsFaceDataSource < MeshType > >() ); meshWriter.addDataSource( make_shared< AreaFaceDataSource < MeshType > >() ); meshWriter.addDataSource( make_shared< StatusBitFaceDataSource < MeshType > >( OpenMesh::Attributes::TAGGED, "tagged" ) ); meshWriter.addDataSource( make_shared< StatusBitVertexDataSource< MeshType > >( OpenMesh::Attributes::TAGGED, "tagged" ) ); meshWriter.addDataSource( make_shared< ColorFaceDataSource < MeshType > >() ); meshWriter.addDataSource( make_shared< ColorVertexDataSource< MeshType > >() ); meshWriter.addDataSource( make_shared< IndexFaceDataSource < MeshType > >() ); meshWriter.addDataSource( make_shared< IndexVertexDataSource< MeshType > >() ); meshWriter.addDataSource( make_shared< RankFaceDataSource < MeshType > >() ); meshWriter.addDataSource( make_shared< RankVertexDataSource< MeshType > >() ); meshWriter(); DistributedVTKMeshWriter< MeshType > meshWriterAABBfiltered( mesh, "distributed_mesh_vtk_test_aabb_filter", 1 ); meshWriterAABBfiltered.addDataSource( make_shared< NormalsVertexDataSource< MeshType > >() ); meshWriterAABBfiltered.addDataSource( make_shared< NormalsFaceDataSource < MeshType > >() ); meshWriterAABBfiltered.addDataSource( make_shared< AreaFaceDataSource < MeshType > >() ); meshWriterAABBfiltered.addDataSource( make_shared< StatusBitFaceDataSource < MeshType > >( OpenMesh::Attributes::TAGGED, "tagged" ) ); meshWriterAABBfiltered.addDataSource( make_shared< StatusBitVertexDataSource< MeshType > >( OpenMesh::Attributes::TAGGED, "tagged" ) ); meshWriterAABBfiltered.addDataSource( make_shared< ColorFaceDataSource < MeshType > >() ); meshWriterAABBfiltered.addDataSource( make_shared< ColorVertexDataSource< MeshType > >() ); meshWriterAABBfiltered.addDataSource( make_shared< IndexFaceDataSource < MeshType > >() ); meshWriterAABBfiltered.addDataSource( make_shared< IndexVertexDataSource< MeshType > >() ); meshWriterAABBfiltered.addDataSource( make_shared< RankFaceDataSource < MeshType > >() ); meshWriterAABBfiltered.addDataSource( make_shared< RankVertexDataSource< MeshType > >() ); meshWriterAABBfiltered.setFaceFilter( mesh::AABBFaceFilter< MeshType >(aabb) ); meshWriterAABBfiltered(); DistributedVTKMeshWriter< MeshType > meshWriterStatusfiltered( mesh, "distributed_mesh_vtk_test_status_filter", 1 ); meshWriterStatusfiltered.addDataSource( make_shared< NormalsVertexDataSource< MeshType > >() ); meshWriterStatusfiltered.addDataSource( make_shared< NormalsFaceDataSource < MeshType > >() ); meshWriterStatusfiltered.addDataSource( make_shared< AreaFaceDataSource < MeshType > >() ); meshWriterStatusfiltered.addDataSource( make_shared< StatusBitFaceDataSource < MeshType > >( OpenMesh::Attributes::TAGGED, "tagged" ) ); meshWriterStatusfiltered.addDataSource( make_shared< StatusBitVertexDataSource< MeshType > >( OpenMesh::Attributes::TAGGED, "tagged" ) ); meshWriterStatusfiltered.addDataSource( make_shared< ColorFaceDataSource < MeshType > >() ); meshWriterStatusfiltered.addDataSource( make_shared< ColorVertexDataSource< MeshType > >() ); meshWriterStatusfiltered.addDataSource( make_shared< IndexFaceDataSource < MeshType > >() ); meshWriterStatusfiltered.addDataSource( make_shared< IndexVertexDataSource< MeshType > >() ); meshWriterStatusfiltered.addDataSource( make_shared< RankFaceDataSource < MeshType > >() ); meshWriterStatusfiltered.addDataSource( make_shared< RankVertexDataSource< MeshType > >() ); meshWriterStatusfiltered.setFaceFilter( mesh::StatusFaceFilter< MeshType >( OpenMesh::Attributes::TAGGED ) ); meshWriterStatusfiltered(); }
bool load_obj(const char *path) { const char *s_sep = " \t\n\r"; FILE *f = fopen(path, "rt"); if (!f) return false; bool result = true; char buf[256]; while (result && !feof(f)) { strcpy(buf, ""); fgets(buf, 256, f); char *token = strtok( buf, s_sep); if (token) { switch (token[0]) { case 'v': { if ((token[1] == 0) || (token[1] == 'n') || (token[1] == 't')) { char type = token[1]; token = strtok( NULL, s_sep); int i = 0; int r = 3; if(type == 't') r = 2; float v[3]; while (token && (i < r)) { v[i] = static_cast<float>(atof(token)); token = strtok( NULL, s_sep); ++i; } if ((i != r) || token) { result = false; break; } switch(type) { case 0: { g_vertices.push_back(vec3(v[0],v[1],v[2])); break; } case 'n': { g_normals.push_back(vec3(v[0],v[1],v[2])); break; } default: break; } } break; } case 'f': { face f; for (int i = 0; i < 3; ++i) { token = strtok( NULL, s_sep); if (!token) { result = false; break; } char *p = strchr(token, '/'); char *q = strrchr(token, '/'); if (!p || !q) { result = false; break; } *p = 0; ++q; f.v[i] = atoi(token) - 1; f.n[i] = atoi(q) - 1; if ((f.v[i] < 0) || (f.n[i] < 0)) { result = false; break; } } if (result) { g_faces.push_back(f); } break; } } } } fclose(f); // // Compute scene AABB // g_sceneAABB = computeAABB(g_vertices); return result; }
void test( const std::string & meshFile, const uint_t numProcesses, const uint_t numTotalBlocks ) { auto mesh = make_shared<MeshType>(); mesh::readAndBroadcast( meshFile, *mesh); auto aabb = computeAABB( *mesh ); auto domainAABB = aabb.getScaled( typename MeshType::Scalar(3) ); auto triDist = make_shared< mesh::TriangleDistance<MeshType> >( mesh ); auto distanceOctree = make_shared< DistanceOctree< MeshType > >( triDist ); const real_t meshVolume = real_c( computeVolume( *mesh ) ); const real_t blockVolume = meshVolume / real_c( numTotalBlocks ); static const real_t cellsPersBlock = real_t(1000); const real_t cellVolume = blockVolume / cellsPersBlock; const Vector3<real_t> cellSize( std::pow( cellVolume, real_t(1) / real_t(3) ) ); ComplexGeometryStructuredBlockforestCreator bfc( domainAABB, cellSize, makeExcludeMeshInterior( distanceOctree, cellSize.min() ) ); auto wl = mesh::makeMeshWorkloadMemory( distanceOctree, cellSize ); wl.setInsideCellWorkload(0); wl.setOutsideCellWorkload(1); wl.setForceZeroMemoryOnZeroWorkload(true); bfc.setWorkloadMemorySUIDAssignmentFunction( wl ); bfc.setRefinementSelectionFunction( makeRefinementSelection( distanceOctree, 5, cellSize[0], cellSize[0] * real_t(5) ) ); WALBERLA_LOG_INFO_ON_ROOT( "Creating SBF with StaticLevelwiseCurveBalanceWeighted Partitioner" ); bfc.setTargetProcessAssignmentFunction( blockforest::StaticLevelwiseCurveBalanceWeighted() ); auto sbf_default = bfc.createSetupBlockForest( Vector3<uint_t>(64,64,64), numProcesses ); //sbf_default->writeVTKOutput("sbf_default"); WALBERLA_LOG_INFO_ON_ROOT( sbf_default->toString() ); return; #ifdef WALBERLA_BUILD_WITH_PARMETIS WALBERLA_LOG_INFO_ON_ROOT( "Creating SBF with ParMetis (PART_KWAY, no commweights)" ); bfc.setTargetProcessAssignmentFunction( blockforest::StaticLevelwiseParMetis( blockforest::StaticLevelwiseParMetis::PARMETIS_PART_KWAY ) ); auto sbf = bfc.createSetupBlockForest( numTotalBlocks, numProcesses ); //sbf->writeVTKOutput("sbf"); WALBERLA_LOG_INFO_ON_ROOT( sbf->toString() ); WALBERLA_LOG_INFO_ON_ROOT( "Creating SBF with ParMetis (PART_KWAY, commweights)" ); bfc.setTargetProcessAssignmentFunction( blockforest::StaticLevelwiseParMetis( commInXDirection, blockforest::StaticLevelwiseParMetis::PARMETIS_PART_KWAY ) ); auto sbf_edge = bfc.createSetupBlockForest( numTotalBlocks, numProcesses ); //sbf_edge->writeVTKOutput("sbf_edge"); WALBERLA_LOG_INFO_ON_ROOT( sbf_edge->toString() ); WALBERLA_LOG_INFO_ON_ROOT( "Creating SBF with ParMetis (PART_GEOM_KWAY, no commweights)" ); bfc.setTargetProcessAssignmentFunction( blockforest::StaticLevelwiseParMetis( blockforest::StaticLevelwiseParMetis::PARMETIS_PART_GEOM_KWAY ) ); auto sbf_geom = bfc.createSetupBlockForest( numTotalBlocks, numProcesses ); //sbf_geom->writeVTKOutput("sbf_geom"); WALBERLA_LOG_INFO_ON_ROOT( sbf_geom->toString() ); WALBERLA_LOG_INFO_ON_ROOT( "Creating SBF with ParMetis (PART_GEOM_KWAY, commweights)" ); bfc.setTargetProcessAssignmentFunction( blockforest::StaticLevelwiseParMetis( commInXDirection, blockforest::StaticLevelwiseParMetis::PARMETIS_PART_GEOM_KWAY ) ); auto sbf_geom_edge = bfc.createSetupBlockForest( numTotalBlocks, numProcesses ); //sbf_geom_edge->writeVTKOutput("sbf_geom_edge"); WALBERLA_LOG_INFO_ON_ROOT( sbf_geom_edge->toString() ); #endif }