int main(int argc, char* argv[]) { // --input camel.off --output camel_acd.wrl --log log.txt --resolution 1000000 --depth 20 --concavity 0.0025 --planeDownsampling 4 --convexhullDownsampling 4 --alpha 0.05 --beta 0.05 --gamma 0.00125 --pca 0 --mode 0 --maxNumVerticesPerCH 256 --minVolumePerCH 0.0001 --convexhullApproximation 1 --oclDeviceID 2 { // set parameters Parameters params; ParseParameters(argc, argv, params); MyCallback myCallback; MyLogger myLogger(params.m_fileNameLog); params.m_paramsVHACD.m_logger = &myLogger; params.m_paramsVHACD.m_callback = &myCallback; Usage(params); if (!params.m_run) { return 0; } std::ostringstream msg; #ifdef CL_VERSION_1_1 msg << "+ OpenCL (ON)" << std::endl; OCLHelper oclHelper; if (params.m_paramsVHACD.m_oclAcceleration) { bool res = InitOCL(params.m_oclPlatformID, params.m_oclDeviceID, oclHelper, msg); if (!res) { myLogger.Log(msg.str().c_str()); return -1; } } #else //CL_VERSION_1_1 msg << "+ OpenCL (OFF)" << std::endl; #endif //CL_VERSION_1_1 #ifdef _OPENMP msg << "+ OpenMP (ON)" << std::endl; #else msg << "+ OpenMP (OFF)" << std::endl; #endif msg << "+ Parameters" << std::endl; msg << "\t input " << params.m_fileNameIn << endl; msg << "\t resolution " << params.m_paramsVHACD.m_resolution << endl; msg << "\t max. depth " << params.m_paramsVHACD.m_depth << endl; msg << "\t max. concavity " << params.m_paramsVHACD.m_concavity << endl; msg << "\t plane down-sampling " << params.m_paramsVHACD.m_planeDownsampling << endl; msg << "\t convex-hull down-sampling " << params.m_paramsVHACD.m_convexhullDownsampling << endl; msg << "\t alpha " << params.m_paramsVHACD.m_alpha << endl; msg << "\t beta " << params.m_paramsVHACD.m_beta << endl; msg << "\t maxhulls " << params.m_paramsVHACD.m_maxConvexHulls << endl; msg << "\t pca " << params.m_paramsVHACD.m_pca << endl; msg << "\t mode " << params.m_paramsVHACD.m_mode << endl; msg << "\t max. vertices per convex-hull " << params.m_paramsVHACD.m_maxNumVerticesPerCH << endl; msg << "\t min. volume to add vertices to convex-hulls " << params.m_paramsVHACD.m_minVolumePerCH << endl; msg << "\t convex-hull approximation " << params.m_paramsVHACD.m_convexhullApproximation << endl; msg << "\t OpenCL acceleration " << params.m_paramsVHACD.m_oclAcceleration << endl; msg << "\t OpenCL platform ID " << params.m_oclPlatformID << endl; msg << "\t OpenCL device ID " << params.m_oclDeviceID << endl; msg << "\t output " << params.m_fileNameOut << endl; msg << "\t log " << params.m_fileNameLog << endl; msg << "+ Load mesh" << std::endl; myLogger.Log(msg.str().c_str()); cout << msg.str().c_str(); // load mesh vector<float> points; vector<int> triangles; string fileExtension; GetFileExtension(params.m_fileNameIn, fileExtension); //cout<<"params.m_fileNameIn="<<params.m_fileNameIn<<" and fileExtension="<<fileExtension<<endl; if (fileExtension == ".OFF") { if (!LoadOFF(params.m_fileNameIn, points, triangles, myLogger)) { cout<<"load OFF file error"<<endl; return -1; } } else if (fileExtension == ".OBJ") { if (!LoadOBJ(params.m_fileNameIn, points, triangles, myLogger)) { cout<<"load OBJ file error"<<endl; return -1; } } else { myLogger.Log("Format not supported!\n"); return -1; } // run V-HACD IVHACD* interfaceVHACD = CreateVHACD(); #ifdef CL_VERSION_1_1 if (params.m_paramsVHACD.m_oclAcceleration) { bool res = interfaceVHACD->OCLInit(oclHelper.GetDevice(), &myLogger); if (!res) { params.m_paramsVHACD.m_oclAcceleration = false; } } #endif //CL_VERSION_1_1 bool res = interfaceVHACD->Compute(&points[0], 3, (unsigned int)points.size() / 3, &triangles[0], 3, (unsigned int)triangles.size() / 3, params.m_paramsVHACD); if (res) { std::string ext; if (params.m_fileNameOut.length() > 4) { ext = params.m_fileNameOut.substr(params.m_fileNameOut.length()-4); } std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); if (ext != ".obj") { // save output unsigned int nConvexHulls = interfaceVHACD->GetNConvexHulls(); msg.str(""); msg << "+ Generate output: " << nConvexHulls << " convex-hulls " << endl; myLogger.Log(msg.str().c_str()); ofstream foutCH(params.m_fileNameOut.c_str()); IVHACD::ConvexHull ch; if (foutCH.is_open()) { /******* Phuc : Save nb of convex part decomposition *******/ ofstream outFile; std::string filename; filename=params.m_fileNameOut.substr(0,params.m_fileNameOut.length()-4);//../../results/egea_acd_0.dat ///filename=params.m_fileNameIn.substr(0,params.m_fileNameOut.length()-4); filename=filename+".txt"; outFile.open(filename.c_str()); if (!outFile.is_open()) { cerr<<"! ERROR: can NOT open file : "<<filename<<endl; exit(1); } outFile<<nConvexHulls<<endl; outFile.close(); /******* Phuc : Save nb of convex part decomposition *******/ Material mat; for (unsigned int p = 0; p < nConvexHulls; ++p) { interfaceVHACD->GetConvexHull(p, ch); ComputeRandomColor(mat); SaveVRML2(foutCH, ch.m_points, ch.m_triangles, ch.m_nPoints, ch.m_nTriangles, mat, myLogger); msg.str(""); msg << "\t CH[" << setfill('0') << setw(5) << p << "] " << ch.m_nPoints << " V, " << ch.m_nTriangles << " T" << endl; myLogger.Log(msg.str().c_str()); #ifdef SAVE_PART /****** Phuc : Save convex-part decomposition *********/ filename=params.m_fileNameOut.substr(0,params.m_fileNameOut.length()-4);//../../results/egea_acd_0.dat ///filename=params.m_fileNameIn.substr(0,params.m_fileNameIn.length()-4);//../../data/egea_0.dat filename=filename+"_"+std::to_string(p)+".dat"; //cout<<filename<<endl; ofstream fpart(filename.c_str()); if (fpart.is_open()) { size_t nV = ch.m_nPoints * 3; for (size_t v = 0; v < nV; v += 3) { fpart << ch.m_points[v + 0] << " " << ch.m_points[v + 1] << " " << ch.m_points[v + 2] << std::endl; } fpart.close(); } else std::cout<<"Can't open file\n"<<std::endl; /****** Phuc : Save convex-part decomposition *********/ #endif } foutCH.close(); } } else { unsigned int nConvexHulls = interfaceVHACD->GetNConvexHulls(); msg.str(""); msg << "+ Generate output: " << nConvexHulls << " convex-hulls " << endl; myLogger.Log(msg.str().c_str()); ofstream foutCH(params.m_fileNameOut.c_str()); IVHACD::ConvexHull ch; if (foutCH.is_open()) { /******* Phuc : Save nb of convex part decomposition *******/ ofstream outFile; std::string filename; filename=params.m_fileNameOut.substr(0,params.m_fileNameOut.length()-4);//../../results/egea_acd_0.dat ///filename=params.m_fileNameIn.substr(0,params.m_fileNameIn.length()-4); filename=filename+".txt"; outFile.open(filename.c_str()); if (!outFile.is_open()) { cerr<<"! ERROR: can NOT open file : "<<filename<<endl; exit(1); } outFile<<nConvexHulls<<endl; outFile.close(); /******* Phuc : Save nb of convex part decomposition *******/ Material mat; int vertexOffset = 1;//obj wavefront starts counting at 1... for (unsigned int p = 0; p < nConvexHulls; ++p) { interfaceVHACD->GetConvexHull(p, ch); SaveOBJ(foutCH, ch.m_points, ch.m_triangles, ch.m_nPoints, ch.m_nTriangles, mat, myLogger, p, vertexOffset); vertexOffset+=ch.m_nPoints; msg.str(""); msg << "\t CH[" << setfill('0') << setw(5) << p << "] " << ch.m_nPoints << " V, " << ch.m_nTriangles << " T" << endl; myLogger.Log(msg.str().c_str()); #ifdef SAVE_PART /****** Phuc : Save convex-part decomposition *********/ filename=params.m_fileNameOut.substr(0,params.m_fileNameOut.length()-4);//../../results/egea_acd_0.dat ///filename=params.m_fileNameIn.substr(0,params.m_fileNameIn.length()-4);//../../data/egea_0.dat filename=filename+"_"+std::to_string(p)+".dat"; ofstream fpart(filename.c_str()); if (fpart.is_open()) { size_t nV = ch.m_nPoints * 3; for (size_t v = 0; v < nV; v += 3) { fpart << ch.m_points[v + 0] << " " << ch.m_points[v + 1] << " " << ch.m_points[v + 2] << std::endl; } fpart.close(); } else std::cout<<"Can't open file\n"<<std::endl; /****** Phuc : Save convex-part decomposition *********/ #endif } foutCH.close(); } } } else { myLogger.Log("Decomposition cancelled by user!\n"); } #ifdef CL_VERSION_1_1 if (params.m_paramsVHACD.m_oclAcceleration) { bool res = interfaceVHACD->OCLRelease(&myLogger); if (!res) { assert(-1); } } #endif //CL_VERSION_1_1 interfaceVHACD->Clean(); interfaceVHACD->Release(); } #ifdef _CRTDBG_MAP_ALLOC _CrtDumpMemoryLeaks(); #endif // _CRTDBG_MAP_ALLOC return 0; }
int main(int argc, char* argv[]) { // --input camel.off --output camel_acd.obj --log log.txt --resolution 1000000 --depth 20 --concavity 0.0025 --planeDownsampling 4 --convexhullDownsampling 4 --alpha 0.05 --beta 0.05 --gamma 0.00125 --pca 0 --mode 0 --maxNumVerticesPerCH 256 --minVolumePerCH 0.0001 --convexhullApproximation 1 --oclDeviceID 2 { // set parameters Parameters params; ParseParameters(argc, argv, params); MyCallback myCallback; MyLogger myLogger(params.m_fileNameLog); params.m_paramsVHACD.m_logger = &myLogger; params.m_paramsVHACD.m_callback = &myCallback; Usage(params); if (!params.m_run) { return 0; } std::ostringstream msg; msg << "+ OpenCL (OFF)" << std::endl; msg << "+ Parameters" << std::endl; msg << "\t input " << params.m_fileNameIn << endl; msg << "\t resolution " << params.m_paramsVHACD.m_resolution << endl; msg << "\t max. depth " << params.m_paramsVHACD.m_depth << endl; msg << "\t max. concavity " << params.m_paramsVHACD.m_concavity << endl; msg << "\t plane down-sampling " << params.m_paramsVHACD.m_planeDownsampling << endl; msg << "\t convex-hull down-sampling " << params.m_paramsVHACD.m_convexhullDownsampling << endl; msg << "\t alpha " << params.m_paramsVHACD.m_alpha << endl; msg << "\t beta " << params.m_paramsVHACD.m_beta << endl; msg << "\t gamma " << params.m_paramsVHACD.m_gamma << endl; msg << "\t pca " << params.m_paramsVHACD.m_pca << endl; msg << "\t mode " << params.m_paramsVHACD.m_mode << endl; msg << "\t max. vertices per convex-hull " << params.m_paramsVHACD.m_maxNumVerticesPerCH << endl; msg << "\t min. volume to add vertices to convex-hulls " << params.m_paramsVHACD.m_minVolumePerCH << endl; msg << "\t convex-hull approximation " << params.m_paramsVHACD.m_convexhullApproximation << endl; msg << "\t OpenCL acceleration " << params.m_paramsVHACD.m_oclAcceleration << endl; msg << "\t OpenCL platform ID " << params.m_oclPlatformID << endl; msg << "\t OpenCL device ID " << params.m_oclDeviceID << endl; msg << "\t output " << params.m_fileNameOut << endl; msg << "\t log " << params.m_fileNameLog << endl; msg << "+ Load mesh" << std::endl; myLogger.Log(msg.str().c_str()); cout << msg.str().c_str(); // load mesh vector<float> points; vector<int> triangles; string fileExtension; GetFileExtension(params.m_fileNameIn, fileExtension); if (fileExtension == ".OFF") { if (!LoadOFF(params.m_fileNameIn, points, triangles, myLogger)) { return -1; } } else if (fileExtension == ".OBJ") { if (!LoadOBJ(params.m_fileNameIn, points, triangles, myLogger)) { return -1; } } else { myLogger.Log("Format not supported!\n"); return -1; } // run V-HACD IVHACD* interfaceVHACD = CreateVHACD(); #ifdef CL_VERSION_1_1 if (params.m_paramsVHACD.m_oclAcceleration) { bool res = interfaceVHACD->OCLInit(oclHelper.GetDevice(), &myLogger); if (!res) { params.m_paramsVHACD.m_oclAcceleration = false; } } #endif //CL_VERSION_1_1 bool res = interfaceVHACD->Compute(&points[0], 3, (unsigned int)points.size() / 3, &triangles[0], 3, (unsigned int)triangles.size() / 3, params.m_paramsVHACD); if (res) { // save output unsigned int nConvexHulls = interfaceVHACD->GetNConvexHulls(); msg.str(""); msg << "+ Generate output: " << nConvexHulls << " convex-hulls " << endl; myLogger.Log(msg.str().c_str()); ofstream foutCH(params.m_fileNameOut.c_str()); IVHACD::ConvexHull ch; if (foutCH.is_open()) { Material mat; int vertexOffset = 1;//obj wavefront starts counting at 1... for (unsigned int p = 0; p < nConvexHulls; ++p) { interfaceVHACD->GetConvexHull(p, ch); SaveOBJ(foutCH, ch.m_points, ch.m_triangles, ch.m_nPoints, ch.m_nTriangles, mat, myLogger, p, vertexOffset); vertexOffset+=ch.m_nPoints; msg.str(""); msg << "\t CH[" << setfill('0') << setw(5) << p << "] " << ch.m_nPoints << " V, " << ch.m_nTriangles << " T" << endl; myLogger.Log(msg.str().c_str()); } foutCH.close(); } } else { myLogger.Log("Decomposition cancelled by user!\n"); } #ifdef CL_VERSION_1_1 if (params.m_paramsVHACD.m_oclAcceleration) { bool res = interfaceVHACD->OCLRelease(&myLogger); if (!res) { assert(-1); } } #endif //CL_VERSION_1_1 interfaceVHACD->Clean(); interfaceVHACD->Release(); } #ifdef _CRTDBG_MAP_ALLOC _CrtDumpMemoryLeaks(); #endif // _CRTDBG_MAP_ALLOC return 0; }
btCollisionShape* BulletSim::BuildVHACDHullShapeFromMesh2(btCollisionShape* mesh, HACDParams* parms) { #if defined(USEVHACD) int* triangles; // array of indesex float* points; // array of coordinates // copy the mesh into the structures btStridingMeshInterface* meshInfo = ((btTriangleMeshShape*)mesh)->getMeshInterface(); const unsigned char* vertexBase; // base of the vertice array int numVerts; // the num of vertices PHY_ScalarType vertexType; // the data type representing the vertices int vertexStride; // bytes between each vertex const unsigned char* indexBase; // base of the index array int indexStride; // bytes between the index values int numFaces; // the number of triangles specified by the indexes PHY_ScalarType indicesType; // the data type of the indexes meshInfo->getLockedReadOnlyVertexIndexBase(&vertexBase, numVerts, vertexType, vertexStride, &indexBase, indexStride, numFaces, indicesType); if (vertexType != PHY_FLOAT || indicesType != PHY_INTEGER) { // If an odd data structure, we cannot hullify m_worldData.BSLog("VHACD: triangle mesh not of right types"); // DEBUG DEBUG return NULL; } // Create pointers to the vertices and indices as the PHY types that they are float* tVertex = (float*)vertexBase; int tVertexStride = vertexStride / sizeof(float); int* tIndices = (int*) indexBase; int tIndicesStride = indexStride / sizeof(int); m_worldData.BSLog("VHACD: nVertices=%d, nIndices=%d", numVerts, numFaces*3); // DEBUG DEBUG // Copy the vertices/indices into the HACD data structures points = new float[numVerts * 3]; triangles = new int[numFaces * 3]; int pp = 0; for (int ii=0; ii < (numVerts * tVertexStride); ii += tVertexStride) { points[pp+0] = tVertex[ii+0]; points[pp+1] = tVertex[ii+1]; points[pp+2] = tVertex[ii+2]; pp += 3; } pp = 0; for(int ii=0; ii < (numFaces * tIndicesStride); ii += tIndicesStride ) { triangles[pp+0] = tIndices[ii+0]; triangles[pp+1] = tIndices[ii+1]; triangles[pp+2] = tIndices[ii+2]; pp += 3; } meshInfo->unLockReadOnlyVertexBase(0); m_worldData.BSLog("VHACD: structures copied"); // DEBUG DEBUG IVHACD::Parameters vParams; vParams.m_resolution = (unsigned int)parms->vHACDresolution; vParams.m_depth = (int)parms->vHACDdepth; vParams.m_concavity = (double)parms->vHACDconcavity; vParams.m_planeDownsampling = (int)parms->vHACDplaneDownsampling; vParams.m_convexhullDownsampling = (int)parms->vHACDconvexHullDownsampling; vParams.m_alpha = (double)parms->vHACDalpha; vParams.m_beta = (double)parms->vHACDbeta; vParams.m_delta = (double)parms->vHACDdelta; vParams.m_gamma = (double)parms->vHACDgamma; vParams.m_pca = (int)parms->vHACDpca; vParams.m_mode = (int)parms->vHACDmode; vParams.m_maxNumVerticesPerCH = (unsigned int)parms->vHACDmaxNumVerticesPerCH; vParams.m_minVolumePerCH = (double)parms->vHACDminVolumePerCH; vParams.m_callback = new VHACDProgressLog(&m_worldData); // vParams.m_logger = vParams.m_convexhullApproximation = (parms->vHACDconvexHullApprox == ParamTrue); vParams.m_oclAcceleration = (parms->vHACDoclAcceleration == ParamTrue); IVHACD* interfaceVHACD = CreateVHACD(); bool res = interfaceVHACD->Compute(points, 1, numFaces * 3, triangles, 3, numVerts, vParams); unsigned int nConvexHulls = interfaceVHACD->GetNConvexHulls(); m_worldData.BSLog("VHACD: After compute. nHulls=%d", nConvexHulls); // DEBUG DEBUG // Create the compound shape all the hulls will be added to btCompoundShape* compoundShape = new btCompoundShape(true); compoundShape->setMargin(m_worldData.params->collisionMargin); // Convert each of the built hulls into btConvexHullShape objects and add to the compoundShape IVHACD::ConvexHull ch; for (unsigned int hul = 0; hul < nConvexHulls; hul++) { interfaceVHACD->GetConvexHull(hul, ch); size_t nPoints = ch.m_nPoints; size_t nTriangles = ch.m_nTriangles; m_worldData.BSLog("VHACD: Add hull %d. nPoints=%d, nTriangles=%d", hul, nPoints, nTriangles); // DEBUG DEBUG // Average the location of all the vertices to create a centriod for the hull. btAlignedObjectArray<btVector3> vertices; vertices.reserve(nTriangles); btVector3 centroid; centroid.setValue(0,0,0); /* int pp = 0; for (int ii=0; ii < nPoints; ii++) { btVector3 vertex(ch.m_points[pp + 0], ch.m_points[pp + 1], ch.m_points[pp + 2] ); vertices.push_back(vertex); centroid += vertex; pp += 3; m_worldData.BSLog("VHACD: Hull %d, vertex %d:<%f,%f,%f>", hul, ii, vertex.getX(), vertex.getY(), vertex.getZ()); // DEBUG DEBUG } // centroid *= 1.f/((float)(nPoints)); // Move the vertices to have the common centroid for (int ii=0; ii < nPoints; ii++) { vertices[ii] -= centroid; } */ for (int ii=0; ii < nTriangles; ii++) { int tri = ch.m_triangles[ii] * 3; btVector3 vertex(ch.m_points[tri+0], ch.m_points[tri+1], ch.m_points[tri+2]); vertices.push_back(vertex); } btConvexHullShape* convexShape; // Optionally compress the hull a little bit to account for the collision margin. if (parms->shouldAdjustCollisionMargin == ParamTrue) { float collisionMargin = 0.01f; btAlignedObjectArray<btVector3> planeEquations; btGeometryUtil::getPlaneEquationsFromVertices(vertices, planeEquations); btAlignedObjectArray<btVector3> shiftedPlaneEquations; for (int p=0; p<planeEquations.size(); p++) { btVector3 plane = planeEquations[p]; plane[3] += collisionMargin; shiftedPlaneEquations.push_back(plane); } btAlignedObjectArray<btVector3> shiftedVertices; btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,shiftedVertices); convexShape = new btConvexHullShape(shiftedVertices[0], shiftedVertices.size(), sizeof(btVector3)); } else { convexShape = new btConvexHullShape(vertices[0], vertices.size(), sizeof(btVector3)); } convexShape->setMargin(m_worldData.params->collisionMargin); // Add the hull shape to the compound shape btTransform childTrans; childTrans.setIdentity(); childTrans.setOrigin(centroid); m_worldData.BSLog("HACD: Add child shape %d", hul); // DEBUG DEBUG compoundShape->addChildShape(childTrans, convexShape); } // The params structure doesn't have a destructor to get rid of logging and progress callbacks if (vParams.m_callback) { delete vParams.m_callback; vParams.m_callback = 0; } delete [] points; delete [] triangles; interfaceVHACD->Clean(); interfaceVHACD->Release(); return compoundShape; #else return NULL; #endif }