## Saturday, 6 December 2014

### Using the V-HACD library in your project

I have lately worked on re-factoring the V-HACD code to make it easier to integrate. An example of code using V-HACD would look like this.

 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36``` ```#include #include "VHACD.h" int main(int argc, char * argv[]) { int * triangles; // array of indexes float * points; // array of coordinates ... // load the mesh ... IVHACD::Parameters params; // V-HACD parameters IVHACD * interfaceVHACD = CreateVHACD(); // create interface // compute approximate convex decomposition bool res = interfaceVHACD->Compute(points, 3, nPoints, triangles, 3, nTriangles, params); // read results unsigned int nConvexHulls = interfaceVHACD->GetNConvexHulls(); // Get the number of convex-hulls IVHACD::ConvexHull ch; for (unsigned int p = 0; p < nConvexHulls; ++p) { interfaceVHACD->GetConvexHull(p, ch); // get the p-th convex-hull information for (unsigned int v = 0, idx = 0; v < ch.m_nPoints; ++v, idx+=3) { printf("x=%f, y=%f, z=%f", ch.m_points[idx], ch.m_points[idx+1], ch.m_points[idx+2]) } for (unsigned int t = 0, idx = 0; t < ch.m_nTriangles; ++t, idx +=3) { printf("i=%f, j=%f, k=%f", ch.m_triangles[idx], ch.m_triangles[idx+1], ch.m_triangles[idx+2]) } } // release memory interfaceVHACD->Clean(); interfaceVHACD->Release(); return 0; } ```

All the magic happens at line 14 where the IVHACD::Compute() function is called. In order to cancel the decomposition process, the function IVHACD::Cancel() could be called from any other thread.

V-HACD offers the user the possibility to track progress and get access to logging information. The only thing the user needs to do is to provide his implementation of the two abstract classes IUserCallback and IUserLogger.

Below, an example of implementation of IUserCallback.

 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16``` ```class MyCallback : public IVHACD::IUserCallback { public: MyCallback(void) {} ~MyCallback() {}; void Update(const double overallProgress, const double stageProgress, const double operationProgress, const char * const stage, const char * const operation) { cout << setfill(' ') << setw(3) << (int)(overallProgress +0.5) << "% " << "[ " << stage << " " << setfill(' ') << setw(3) << (int)(stageProgress +0.5) << "% ] " << operation << " " << setfill(' ') << setw(3) << (int)(operationProgress+0.5) << "%" << endl; }; }; ```

The Update() callback is called regularly during the decomposition process to report:
• The overall progress,
• The progress of the current stage, and
• The progress of the current operation.
Notice that the progress is always reported as a percentage. The decomposition process is composed of a set of stages, which are composed of operations.

An example of implementation of IUserLogger may look as follows.

 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18``` ```class MyLogger : public IVHACD::IUserLogger { public: MyLogger(void){} MyLogger(const string & fileName){ OpenFile(fileName); } ~MyLogger() {}; void Log(const char * const msg) { if (m_file.is_open()) { m_file << msg; m_file.flush(); } }; void OpenFile(const string & fileName) { m_file.open(fileName.c_str()); } private: ofstream m_file; }; ```

MyCallback and MyLogger are hooked to the IVHACD object by updating encode parameters as follows.

 ``` 1 2 3 4 5 6 7 8 9 10``` ```IVHACD::Parameters params; // V-HACD parameters IVHACD * interfaceVHACD = CreateVHACD(); // create interface MyCallback myCallback; MyLogger myLogger(fileNameLog); params.m_logger = &myLogger; params.m_callback = &myCallback; // compute approximate convex decomposition bool res = interfaceVHACD->Compute(points, 3, nPoints, triangles, 3, nTriangles, params); ```