// Please read and edit this document using WordPad.
// ===============================================================================================================================================================
// EXPERIMENTAL V-HACD DECOMPOSITION (very little tested and prone to errors, be warned...(not talking about the library, but my usage of it inside HACDDemo))
// ==============================================================================================================================================================
//
// Usage: 	[Windows:] Drag an .obj or an .off model onto the file appHACDDemo.exe.
//		[Linux:] a) Open a terminal in the folder of the model(s) you need to decompose
//			 b) Type:	export HACDDemo=/.../Bullet/Demos/HACDDemo/Release/appHACDDemo	
//					or similiar (basically the full path of your appHACDDemo executable)
//			 c) Now you can type: $HACDDemo myModel.obj
//			    to decompose a model in this terminal window (with no persistent effect when you close it).
//			 [Of course you can simply use: /.../appHACDDemo myModel.obj every time too]	
//
// IMPORTANT: For V-HACD to kick in (instead of HACD), you must set:
// extraParams.ignoreAllParamsAndUseVHACDInsteadIfAvailable = true; in file: "appHACDDemo.exe.cmdlineParams.txt" (NOT THIS FILE)   	
//
// Depending on how appHACDDemo is compiled:
// -> V-HACD may be present or not (if this is the case the option above is ignored);
// -> many other mesh formats can be imported through the support of the optional Asset Import Library.
//
// ================================================================================================================================
// COMMANDLINE USAGE PARAMS TO DECOMPOSE MESHES WITH V-HACD ("Volumetric Hierarchical approximate convex decomposition" library by Khaled Mamou)
// ================================================================================================================================
// Please read "Khaled Mamou's Blog" at http://kmamou.blogspot.com/  for further info.
//
// The input mesh will be decomposed using these params, and can be optionally saved
// as a ".bcs" (Bullet Collision Shape) file (*).
//
// This is pseudo C++ (not 100% C++ compatible).
// Only one parameter is allowed per line.
// Only one equality character ('=') is allowed per line.
// Only one semicolon is allowed per line.
// Multiline comments are allowed only if '/*' or '*/' own a whole line.
//
//
// This time I've chosen the same default values as the V-HACD library (note that: params.targetNTrianglesDecimatedMesh = 1000;).
// Beware that (not 100% sure of what I'm going to say here, I'm just experimenting):
// -> decomposition results don't seem deterministic to me (because I compiled with openMP? maybe, but it's worth the speed improvement).
// -> sub-shapes shouldn't overlap, but they CAN actually overlap in some cases (because I use params.targetNTrianglesDecimatedMesh>0? maybe, but again I prefer speeding up the process).
// -> there is no way to specify the number of vertices in each sub-shape (probably because V-HACD simply splits the input mesh into chunks: so you get many vertices of your input mesh back
//	inside child shapes, which are actually CONCAVE as far as I can see so far, and they become convex when you turn them into convex hulls). 
//	[However you can params.reduceHullVerticesUsingBtShapeHull = true; to limit the number of vertices in each child shape to a maximum of 42.]
//   
//
//
//
// Happy decomposing.
// Flix
//
// P.S.: In the comments I speak about "clusters", "child shapes" and "convex hulls": they're all the same thing!
//
// ==============================================================
btVHACDCompoundShape::Params params;						// the variable name 'params' can't be modified
//----------------------------
// ORIGINAL PARAMS (V-HACD.lib original comments):
// ---------------------------
params.depth				=		10;		// (10) maximum number of decomposition stages (type: integer, default: 10)
params.maxConcavity			=		0.01;		// (0.01)  maximum allowed concavity (type: float, default 0.01)
params.posSampling			=		10;		// (10) clipping plane position sampling resolution for coarse search (type: int, default 10)
params.angleSampling			=		10;		// (10)  clipping plane orientation sampling resolution for coarse search (type: int, default 10) 
params.posRefine			=		5;		// (5)  clipping plane position sampling resolution for refined search (type: int, default 5) 
params.angleRefine;			=		5;		// (5)  clipping plane orientation sampling resolution for refined search (type: int, default 5)
params.alpha				=		0.01;		// (0.01)  parameter controlling the compromise between concavity and balance between convex-hulls. (type: float, default: 0.01)
params.targetNTrianglesDecimatedMesh	=		1000;		// (1000) this options should speed up the decomposition of big meshes by performing mesh simplification before decomposition (good values are 500, 1000, 2000, 5000, 10000 and o on).

// Tip. don't touch these:	
params.displayDebugInfo			=		true;		// (false) With printf. It make sense to leave it to true in cmdline mode. (This option seems currently broken ATM...) 
//------------------------------------------------------
// W.I.P.: ADDITIONAL PARAMS ADDED BY ME (TO BE TESTED):
//------------------------------------------------------
params.keepSubmeshesSeparated				=	false;	// (false). True is slower (not true in many cases! Try yourself), and must be used when submesh index is needed. Currently only .obj file loading supports multiple submeshes.
											// A btAlignedObjectArray< int > submeshIndexOfChildShapes to map the child shape index vs the submesh index is displayed in the console window.
											// It's worth trying it even if you don't need submesh indices. The decomposition is called one time for every submesh. Good if you want good precision at the cost of more convex hull (params.nClusters * numSubmeshes is the minimum you can get)
											// 	  Ordering refers to the whole set of submeshes (so that it's independent on decomposeOnlySelectedSubmeshes).														
params.decomposeACleanCopyOfTheMesh			=	true;		// (true). Removes duplicated vertices and degenerate triangle. Not too slow, and can speed up decomposition (slightly) and reduce the number of (useless) resulting hulls..
params.decomposeACenteredCopyOfTheMesh		=	false;	// (false). The mesh center is always calculated keeping into account all the subparts of the whole btStridingMeshInterface.
params.decomposeATranslatedCopyOfTheMesh		=btVector3(0,0,0);// (btVector3(0,0,0)). In unscaled units. The center of mass will be shifted in the opposite way.
params.decomposeAScaledCopyOfTheMesh		=btVector3(1,1,1);// (btVector3(1,1,1)). The order of transformations is: center -> translate -> scale; thus the scaling here multiplies the translation effect.
params.decomposeOnlySelectedSubmeshes		=	{};		// ({}) If size()==0, decompose all submeshes. (e.g. = {0,1,2};) . Currently only .obj file loading supports multiple submeshes.
params.decomposeADecimatedCopyOfTheMesh		=	false;	// (false). (DEPRECATED: Use params.targetNTrianglesDecimatedMesh instead.) True can be used to reduce the number of child shapes when increasing "concavity" and "connectionDistance" does not help (but some detail gets lost). Slow? Maybe, but can speed up the decomposition process.
params.decimationDistanceInAabbHalfExtentsUnits	=	0.1;		// (0.1). In (0,1]. Bigger results in bigger decimation (= possibly less child shapes)
params.decimationDistanceUniformInXYZ		=	true;		// (true).	When true: 		DDx = DDy = DDz = decimationDistanceInHalfAabbExtentsUnits * min(AabbHalfExtents)xyz;
											//		When false:  	DDx = decimationDistanceInHalfAabbExtentsUnits * AabbHalfExtents.x;	
											//					DDy = decimationDistanceInHalfAabbExtentsUnits * AabbHalfExtents.y;	
											//					DDz = decimationDistanceInHalfAabbExtentsUnits * AabbHalfExtents.z;	
params.reduceHullVerticesUsingBtShapeHull		=	false;	// (false)  when set, uses btShapeHull (implemented by John McCutchan) to simplify the original btConvexHullShapes, so that the number of hull vertices in each child shape is less than 42. It should result in a lower number of vertices per hull (when this does not happen, the original btConvexHullShape is used).
params.shrinkObjectInwardsToCompensateCollisionMargin=false;	// (false)	// Based on the code in appConvexDecompositionDemo. Slow. And seems to produce artifacts in some meshes...
params.useStanMelaxVolumeIntegrationForClusterOrigins=false;	// (false).	If true the child shape transform origins are not placed in the child shape aabb centers, but in their (uniform volume based)
								//		center of mass. However please note that usually child shapes overlap: so this overhead does not make sense in most cases.
	

// Child btConvexHullShapes properties:
params.convexHullsCollisionMargin			=	0.01f;	// (0.01f) The collision margin assigned to all the child shapes
params.convexHullsEnablePolyhedralContactClipping=	false;	// (false) This just calls initializePolyhedralFeatures() on each child shape (see Bullet appInternalEdgeDemo). (I don't think it gets serialized, so please ignore it)
//--------------------------------------------
// W.I.P: EXTRA PARAMS FOR CMDLINE USAGE ONLY:
//--------------------------------------------
ExtraParams extraParams;							// the variable name 'extraParams' can't be modified

extraParams.useAutoGeneratedSaveNameToSaveShape	=	false;	// (false). True + params.optionalBCSSaveFilePath.size()>0 => Bullet Collision Shape is saved as "inputMeshFileFullPathWithExtension.bcs" (*)
extraParams.invertYZ					=	false;	// (false). When loading the mesh file, newY = Z and newZ = -Y.
extraParams.ignoreAllParamsAndCreateBvhTriangleMeshShape=false;	// (false). Ignores all the values set by "params" and Just creates the mesh as btBvhTriangleMeshShape (**)
extraParams.ignoreAllParamsAndCreateGImpaceMeshShape=	false;	// (false). Ignores all the values set by "params" and Just creates the mesh as btGImpaceMeshShape (**)
extraParams.decomposeBCSInputFileIfShapeIsCompatible=	false;	// (false). When a .bcs file (or a .bullet file with only one shape inside it) is passed as input and the shape inside the file is one of the following:
											//		btBvhTriangleMeshShape, btGImpactMeshShape, btScaledBvhTriangleMeshShape, (experimental) btCompoundShape with 1st child one of the previous 3,
											//		decompose the input btCollisionShape instead of simply displaying it as it is (which is the default behavior).
extraParams.useFlatNormalsWhenAssigningAMeshToTheDecomposedShape= false;	//(true). Does not affect decomposition, only the displayed mesh ('r' key). Generally 'true' is better for comparing the assigned mesh to the decomposed shape;
									//	  However in the final stage of development, most meshes don't need flat normals (and 'false' looks better).

/*
NOTES:
(*)	Files with extension ".bcs" can be viewed by dragging them onto the file appHACDDemo.exe.
	In C++ applications they can be loaded with the following code:
	// ---------------------------------------------------------------------------------------------------------------------------
	#include <BulletWorldImporter/btBulletWorldImporter.h>	// In "Bullet/Extra/Serialize". Needs link to: BulletWorldImporter.lib
	btCollisionShape* btUtils::Load(const char* filename,bool verbose)	{
		btBulletWorldImporter loader(0);//don't store info into the world
		loader.setVerboseMode(verbose);
		if (!loader.loadFile(filename)) return NULL;
		btCollisionShape* shape = NULL;
		if (loader.getNumCollisionShapes()>0) shape = loader.getCollisionShapeByIndex(0);
		
		//TODO: Cleaner way:
		// 1) Deep clone Collision Shape	
		// 2) loader.deleteAllData(); // deletes all (collision shapes included)
		// 3) return Deep cloned Collision Shape
	
		// Here we don't delete all data from the loader. (leaks?)
		return shape;
	}
	//----------------------------------------------------------------------------------------------------------------------------

(**) Actually a few of the values in params are not ignored:
	params.decomposeAScaledCopyOfTheMesh
	params.decomposeATranslatedCopyOfTheMesh
	params.decomposeACenteredCopyOfTheMesh
	params.convexHullsCollisionMargin (applied to the whole shape)
	params.optionalBCSSaveFilePath
	and of course all extraParams	
	but duplicated vertices and degenerate triangles are not handled.
*/

