btCompoundShape* convex_decomposition_hacd::ConvexDecomp(int numVertices, float* vertices, int numIndices,const unsigned int* indices)
{
	//-----------------------------------------------
	// HACD
	//-----------------------------------------------

	std::vector< HACD::Vec3<HACD::Real> > points;
	std::vector< HACD::Vec3<long> > triangles;

	for(int i=0; i<numVertices; i++ ) 
	{
		int index = i*3;
		HACD::Vec3<HACD::Real> vertex(vertices[index], vertices[index+1],vertices[index+2]);
		points.push_back(vertex);
	}

	for(int i=0;i<numIndices/3;i++)
	{
		int index = i*3;
		HACD::Vec3<long> triangle(indices[index], indices[index+1], indices[index+2]);
		triangles.push_back(triangle);
	}

	HACD::HACD myHACD;
	myHACD.SetPoints(&points[0]);
	myHACD.SetNPoints(points.size());
	myHACD.SetTriangles(&triangles[0]);
	myHACD.SetNTriangles(triangles.size());
	myHACD.SetCompacityWeight(0.1);
	myHACD.SetVolumeWeight(0.0);

	// HACD parameters
	// Recommended parameters: 2 100 0 0 0 0
	size_t nClusters = 2;
	double concavity = 10;
	bool invert = false;
	bool addExtraDistPoints = true;//false;
	bool addNeighboursDistPoints = true;//false;
	bool addFacesPoints = false;       

	myHACD.SetNClusters(nClusters);                     // minimum number of clusters
	myHACD.SetNVerticesPerCH(256);                      // max of 100 vertices per convex-hull
	myHACD.SetConcavity(concavity);                     // maximum concavity
	myHACD.SetAddExtraDistPoints(addExtraDistPoints);   
	myHACD.SetAddNeighboursDistPoints(addNeighboursDistPoints);   
	myHACD.SetAddFacesPoints(addFacesPoints); 

	myHACD.SetAddExtraDistPoints(true);   
	myHACD.SetAddFacesPoints(true); 


	
        MStatus stat = MS::kSuccess;
        MString title = "Esc to stop";
        MString sleeping = "Esc to stop";
        
        int amount = 0;
        int maxProgress = 1000;
        
        // First reserve the progress window.  If a progress window is already
        // active (eg. through the mel "progressWindow" command), this command
        // fails.
        //
        if (!MProgressWindow::reserve())
        {
                MGlobal::displayError("Progress window already in use.");
                stat = MS::kFailure;
        }

        //
        // Set up and print progress window state
        //


        CHECK_MSTATUS(MProgressWindow::setProgressRange(amount, maxProgress));
        CHECK_MSTATUS(MProgressWindow::setTitle(title));
        CHECK_MSTATUS(MProgressWindow::setInterruptable(true));
        CHECK_MSTATUS(MProgressWindow::setProgress(amount));

        MString progressWindowState = MString("Progress Window Info:") +
                MString("\nMin: ") + MProgressWindow::progressMin() +
                MString("\nMax: ") + MProgressWindow::progressMax() + 
                MString("\nTitle: ") + MProgressWindow::title() + 
                MString("\nInterruptible: ") + MProgressWindow::isInterruptable();

        MGlobal::displayInfo(progressWindowState);
        
        CHECK_MSTATUS(MProgressWindow::startProgress());
        
		int i=1;
		MString statusStr = sleeping;
        statusStr += i;

		 CHECK_MSTATUS(MProgressWindow::setProgressStatus(statusStr));
          CHECK_MSTATUS(MProgressWindow::advanceProgress(1));
		   MGlobal::displayInfo(MString("Current progress: ") + MProgressWindow::progress());
		    
		   MGlobal::executeCommand("pause -sec 1", false,false);
		   
        // Count 10 seconds
        //
/*        for (int i = amount; i < maxProgress; i++)
        {
                if (i != 0 && MProgressWindow::isCancelled()) {
                        MGlobal::displayInfo("Progress interrupted!");
                        break;
                }

                MString statusStr = sleeping;
                statusStr += i;
                CHECK_MSTATUS(MProgressWindow::setProgressStatus(statusStr));
                CHECK_MSTATUS(MProgressWindow::advanceProgress(1));

                MGlobal::displayInfo(MString("Current progress: ") + MProgressWindow::progress());

                MGlobal::executeCommand("pause -sec 1", false, false);
        }
		*/

        
        // End the progress, unreserving the progress window so it can be used
        // elsewhere.
        //
     
	myHACD.SetCallBack(mayaCallback);

	bool result = myHACD.Compute();
	if (!result)
	{
		nClusters = 0;
	} else
	{
		nClusters = myHACD.GetNClusters();
	}
	   
	CHECK_MSTATUS(MProgressWindow::endProgress());

	
	

//	myHACD.Save("output.wrl", false);

	btCompoundShape* compound = new btCompoundShape();
//   mMergedTriangleMesh = new btTriangleMesh();

   //now create some bodies
	if (1)
	{
		btTransform trans;
		trans.setIdentity();

		for (int c=0;c<nClusters;c++)
		{
			//generate convex result
			size_t nPoints = myHACD.GetNPointsCH(c);
			size_t nTriangles = myHACD.GetNTrianglesCH(c);

			float* vertices = new float[nPoints*3];
			unsigned int* triangles = new unsigned int[nTriangles*3];
			
			HACD::Vec3<HACD::Real> * pointsCH = new HACD::Vec3<HACD::Real>[nPoints];
			HACD::Vec3<long> * trianglesCH = new HACD::Vec3<long>[nTriangles];
			myHACD.GetCH(c, pointsCH, trianglesCH);

			// points
			for(size_t v = 0; v < nPoints; v++)
			{
				vertices[3*v] = pointsCH[v].X();
				vertices[3*v+1] = pointsCH[v].Y();
				vertices[3*v+2] = pointsCH[v].Z();
			}
			// triangles
			for(size_t f = 0; f < nTriangles; f++)
			{
				triangles[3*f] = trianglesCH[f].X();
				triangles[3*f+1] = trianglesCH[f].Y();
				triangles[3*f+2] = trianglesCH[f].Z();
			}

			delete [] pointsCH;
			delete [] trianglesCH;

			ConvexDecompResult(nPoints, vertices, nTriangles, triangles);
		}

		for (int i=0;i<m_convexShapes.size();i++)
		{
			btVector3 centroid = m_convexCentroids[i];
			trans.setOrigin(centroid);
			btConvexHullShape* convexShape = m_convexShapes[i];
			compound->addChildShape(trans,convexShape);
		}
	}

/*   mMergedTriangleVertices = new float[mNumMergedTriangleVertices*3];
   mMergedTriangleIndices = new int[mNumMergedTriangleIndices];
   for(int i=0; i<m_trimeshes.size(); i++)
   {
      mMergedTriangleVertices[i] = 
   }*/


   return compound;
}
vector<pair<btVector3, btConvexHullShape*> > ofxBulletConvexDecomposer::decompose(const ofMesh &meshToDecompose, btVector3 scale )
{
	assert( meshToDecompose.getMode() == OF_TRIANGLES_MODE );
	vector<pair<btVector3, btConvexHullShape*> > convexShapes;
	int tcount = meshToDecompose.getNumIndices()/3;
	if ( tcount == 0 )
		// nothing to do
		return convexShapes;
	
	// adapted from bullet-2.81-rev2613/Demos/ConvexDecompositionDemo/ConvexDecompositionDemo.cpp
	
	/*
	 unsigned int depth = 5;
	 float cpercent     = 5;
	 float ppercent     = 15;
	 unsigned int maxv  = 16;
	 float skinWidth    = 0.0;
	 
	 // ConvexDecomposition::WavefrontObj wo;
	 ConvexDecomposition::DecompDesc desc;
	 desc.mVcount       = meshToDecompose.getNumVertices();
	 desc.mVertices     = (float*)(meshToDecompose.getVerticesPointer());
	 desc.mTcount       = meshToDecompose.getNumIndices()/3;
	 desc.mIndices      = meshToDecompose.getIndexPointer();
	 desc.mDepth        = depth;
	 desc.mCpercent     = cpercent;
	 desc.mPpercent     = ppercent;
	 desc.mMaxVertices  = maxv;
	 desc.mSkinWidth    = skinWidth;
	 
	 desc.mCallback = this;
	 */
	
	//-----------------------------------------------
	// HACD
	//-----------------------------------------------
	
	std::vector< HACD::Vec3<HACD::Real> > points;
	std::vector< HACD::Vec3<long> > triangles;
	
	for(int i=0; i<meshToDecompose.getNumVertices(); i++ )
	{
		ofVec3f meshVert = meshToDecompose.getVertex(i);
		HACD::Vec3<HACD::Real> vertex( meshVert.x, meshVert.y, meshVert.z );
		points.push_back(vertex);
	}
	
	for(int i=0;i<meshToDecompose.getNumIndices(); i+=3 )
	{
		HACD::Vec3<long> triangle(meshToDecompose.getIndex(i), meshToDecompose.getIndex(i+1), meshToDecompose.getIndex(i+2) );
		triangles.push_back(triangle);
	}
	assert(triangles.size()==tcount);
	
	
	HACD::HACD myHACD;
	myHACD.SetPoints(&points[0]);
	myHACD.SetNPoints(points.size());
	myHACD.SetTriangles(&triangles[0]);
	myHACD.SetNTriangles(triangles.size());
	myHACD.SetCompacityWeight(0.1);
	myHACD.SetVolumeWeight(0.0);
	
	// HACD parameters
	// Recommended parameters: 2 100 0 0 0 0
	size_t nClusters = 2;
	double concavity = 100;
	bool invert = false;
	bool addExtraDistPoints = false;
	bool addNeighboursDistPoints = false;
	bool addFacesPoints = false;
	
	myHACD.SetNClusters(nClusters);                     // minimum number of clusters
	myHACD.SetNVerticesPerCH(100);                      // max of 100 vertices per convex-hull
	myHACD.SetConcavity(concavity);                     // maximum concavity
	myHACD.SetAddExtraDistPoints(addExtraDistPoints);
	myHACD.SetAddNeighboursDistPoints(addNeighboursDistPoints);
	myHACD.SetAddFacesPoints(addFacesPoints);
	
	myHACD.SetCallBack( hacdCallback );
	
	myHACD.Compute();
	nClusters = myHACD.GetNClusters();
	
	
	
	int totalTriangles = 0;
	int totalPoints = 0;
	for (int c=0;c<nClusters;c++)
	{
		//generate convex result
		size_t nPoints = myHACD.GetNPointsCH(c);
		size_t nTriangles = myHACD.GetNTrianglesCH(c);
		ofLogVerbose("ofxBulletConvexDecomposer") << "cluster " << c <<"/" << nClusters << " points " << nPoints << " triangles " << nTriangles;
		
		float* vertices = new float[nPoints*3];
		unsigned int* triangles = new unsigned int[nTriangles*3];
		
		HACD::Vec3<HACD::Real> * pointsCH = new HACD::Vec3<HACD::Real>[nPoints];
		HACD::Vec3<long> * trianglesCH = new HACD::Vec3<long>[nTriangles];
		myHACD.GetCH(c, pointsCH, trianglesCH);
		
		// points
		for(size_t v = 0; v < nPoints; v++)
		{
			vertices[3*v] = pointsCH[v].X();
			vertices[3*v+1] = pointsCH[v].Y();
			vertices[3*v+2] = pointsCH[v].Z();
		}
		// triangles
		for(size_t f = 0; f < nTriangles; f++)
		{
			triangles[3*f] = trianglesCH[f].X();
			triangles[3*f+1] = trianglesCH[f].Y();
			triangles[3*f+2] = trianglesCH[f].Z();
		}
		
	
		ConvexResult r(nPoints, vertices, nTriangles, triangles);
		convexShapes.push_back( createConvexHullShapeFromConvexResult(r, scale) );
		
		delete [] pointsCH;
		delete [] trianglesCH;
		delete [] vertices;
		delete [] triangles;
		
		totalTriangles += nTriangles;
	}

	return convexShapes;
}