///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
 *	This file contains the mesh-related exported structures.
 *	\file		FLX_AddMesh.h
 *	\author		Pierre Terdiman
 *	\date		April, 4, 2000
 */
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Include Guard
#ifndef __FLX_ADDMESH_H__
#define __FLX_ADDMESH_H__

	// Edge visibility codes.
	#define	EDGE_0					(1<<0)				//!< Bitmask for first edge
	#define	EDGE_1					(1<<1)				//!< Bitmask for second edge
	#define	EDGE_2					(1<<2)				//!< Bitmask for third edge

	// Mesh flags. Don't forget to copy them in IceZCBFormat.h
	#define	MESH_VFACE				(1<<0)				//!< Mesh has vertex-faces.
	#define	MESH_TFACE				(1<<1)				//!< Mesh has texture-faces.
	#define	MESH_CFACE				(1<<2)				//!< Mesh has color-faces.
	#define MESH_UVW				(1<<3)				//!< UVW's are exported
	#define MESH_WDISCARDED			(1<<4)				//!< W is discarded
	#define MESH_VERTEXCOLORS		(1<<5)				//!< Vertex colors are exported
	#define	MESH_ONEBONEPERVERTEX	(1<<6)				//!< Simple skin with one driving bone/vertex
	#define	MESH_CONVEXHULL			(1<<7)				//!< The convex hull has been exported
	#define	MESH_BOUNDINGSPHERE		(1<<8)				//!< The bounding sphere has been exported
	#define	MESH_INERTIATENSOR		(1<<9)				//!< The inertia tensor has been exported
	#define	MESH_QUANTIZEDVERTICES	(1<<10)				//!< Vertices have been quantized
	#define	MESH_WORDFACES			(1<<11)				//!< Vertex references within faces are stored as words instead of dwords
	#define	MESH_COMPRESSED			(1<<12)				//!< Mesh has been saved in a compression-friendly way
	#define	MESH_EDGEVIS			(1<<13)				//!< Edge visibility has been exported

	// Extra mesh flags actually used in the MeshInfo class
	#define	MESH_CONSOLIDATION		(1<<16)				//!< Mesh has been consolidated
	#define	MESH_FACENORMALS		(1<<17)				//!< Export normals to faces
	#define	MESH_VERTEXNORMALS		(1<<18)				//!< Export normals to vertices
	#define	MESH_NORMALINFO			(1<<19)				//!< Export NormalInfo

	//! A structure to hold face information.
	struct MAXFace
	{
		sdword			VRef[3];						//!< Vertex references
		sdword			TRef[3];						//!< Texture-vertex references
		sdword			CRef[3];						//!< Vertex-color references
		sdword			MatID;							//!< Material ID
		udword			Smg;							//!< Smoothing groups
		ubyte			EdgeVis;						//!< Edge visibility code
	};

	//! A simple class holding convex hull data
	class CHull
	{
		public:
		// Constructor / Destructor
											CHull() : mNbFaces(0), mNbVerts(0), mFaces(null), mVerts(null)	{}
											~CHull()	{ DELETEARRAY(mFaces); DELETEARRAY(mVerts); }
		// Figures
						udword				mNbFaces;	//!< Number of faces
						udword				mNbVerts;	//!< Number of vertices.
		// Topology
						udword*				mFaces;		//!< List of faces
		// Geometry
						MAXPoint*			mVerts;		//!< List of vertices
	};

	//! A simple structure holding volume integrals
	struct ITensor
	{
		MAXPoint		COM;							//!< Center of mass
		float			Mass;							//!< Total mass
		float			InertiaTensor[3][3];			//!< Intertia tensor (mass matrix) relative to the origin
		float			COMInertiaTensor[3][3];			//!< Intertia tensor (mass matrix) relative to the COM
	};

	//! A class to hold skeletal information.
	class Skeleton
	{
		public:
		// Constructor / Destructor
											Skeleton(udword nb)
											{
												mNbBones	= nb;
												mID			= new udword[nb*2];
											}
											~Skeleton()
											{
												DELETEARRAY(mID);
											}

						udword				mNbBones;			//!< Number of bones involved
						udword*				mID;				//!< NbBones couples of IDs (CSID, parent CSID).
	};

	//! A class gathering a mesh in MAX native format.
	class MAXNativeMesh
	{
		public:
		// Constructor / Destructor
											MAXNativeMesh();
											~MAXNativeMesh();

		// Figures
						udword				mNbFaces;			//!< Number of faces in MAX native data
						udword				mNbVerts;			//!< Number of vertices.
						udword				mNbTVerts;			//!< Number of texture-vertices (mapping coordinates)
						udword				mNbCVerts;			//!< Number of vertex-colors
		// MESH Flags
						udword				mFlags;				//!< See flags above.
		// Topologies
						MAXFace*			mFaces;				//!< List of faces
		// Geometries
						MAXPoint*			mVerts;				//!< List of vertices (null for skins, use offset vectors)
						MAXPoint*			mTVerts;			//!< List of texture-vertices
						MAXPoint*			mCVerts;			//!< List of vertex-colors
						udword*				mBonesNb;			//!< Number of bones for each vertex, or null if one bone/vertex. (only for skins)
						udword*				mBonesID;			//!< IDs of driving bones. (only for skins)
						MAXPoint*			mOffsetVectors;		//!< Character Studio's offset vectors. (only for skins)
						float*				mWeights;			//!< Bones weights when there's more than one bone/vertex, else null. (only for skins)
						Skeleton*			mSkeleton;			//!< Skeletal information (only for skins)
		// Possible convex hull
						CHull*				mConvexHull;		//!< Convex hull, only if the ConvexHull field is true in the ExportSettings.
		// Possible bounding sphere
						MAXPoint			mBSCenter;			//!< Bounding sphere center, only if the BoundingSphere field is true in the ExportSettings.
						float				mBSRadius;			//!< Bounding sphere radius, only if the BoundingSphere field is true in the ExportSettings.
		// Possible inertia tensor
						ITensor*			mTensor;			//!< Volume integrals, only if the InertiaTensor field is true in the ExportSettings.
		// Misc
						bool				mParity;			//!< Faces are CW or CCW.
	};

	//! The mesh information class.
	class MeshDescriptor : public ObjectDescriptor
	{
		public:
		// Constructor / Destructor
											MeshDescriptor();
		virtual								~MeshDescriptor();

		// Parameters
						bool				mIsCollapsed;		//!< true => mesh comes from a collapsed modifier stack
						bool				mIsSkeleton;		//!< true => mesh is a BIPED part (i.e. a bone)
						bool				mIsInstance;		//!< true => mesh is an instance from another mesh
						bool				mIsTarget;			//!< true => mesh is a target node (camera, spot or directional target)
						bool				mIsConvertible;		//!< false => mesh can't be converted to triangles (and the native format is unsupported)
						bool				mIsSkin;			//!< true => the mesh is a PHYSIQUE skin
						bool				mCastShadows;		//!< true => a shadow volume can be built from the mesh

		// Instance information (valid if mIsInstance==true)
						MeshDescriptor*		mMasterMesh;		//!< Master object

		// Biped/Physique-related information (valid if mIsSkeleton==true || mIsSkin==true)
						udword				mCharID;			//!< Owner character's ID
		// Biped-related information (valid if mIsSkeleton==true)
						udword				mCSID;				//!< CSID code.

		// Mesh data
						MAXNativeMesh		mOriginalMesh;		//!< Original mesh from MAX
//						MESHBUILDERRESULT*	mCleanMesh;			//!< Mesh after consolidation
						MBResult*			mCleanMesh;			//!< Mesh after consolidation

		// Lightmapper data
						udword				mNbColors;			//!< Number of computed colors
						MAXPoint*			mColors;			//!< Computed colors

		// Mesh consolidation
						bool				Consolidate(const ExportSettings* settings, bool forcenormals, bool discardnormals, bool morph);
		private:
//						MeshBuilder*		mBuilder;			//!< A mesh cleaner.
						MeshBuilder2*		mBuilder;			//!< A mesh cleaner.
	};

#endif // __FLX_ADDMESH_H__
