/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
------------------------------------------------------------------------------*/


#ifndef	__NBULLETPHYSICWORLD__
#define	__NBULLETPHYSICWORLD__


		#include "nstring/nstring.h"

/*
	@short	Enable multi-threading support in Bullet Dynamics.
	Not working at the moment (need to let the API stabilize a bit first).
*/
#define	__ENABLE_BULLET_MULTITHREAD__	0
/*
	@short	Number of thread used by Bullet.
*/
#define	__BULLET_THREAD_COUNT__			3


		#include "memory/nauto_ptr.h"
		#include "memory/nshared_ptr.h"
		#include "physic/physic_world.h"
        #include "btBulletDynamicsCommon.h"
		#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"

#if	__ENABLE_BULLET_MULTITHREAD__
		#include "BulletMultiThreaded/SpuGatheringCollisionDispatcher.h"
		#include "BulletMultiThreaded/PlatformDefinitions.h"
	#if	__PLATFORM_WINDOWS__
		#include "BulletMultiThreaded/Win32ThreadSupport.h"
		#include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
	#elif __PLATFORM_LINUX__
		#include "BulletMultiThreaded/PosixThreadSupport.h"
		#include "BulletMultiThreaded/SpuNarrowPhaseCollisionTask/SpuGatheringCollisionTask.h"
	#endif
#endif

namespace GS {
	namespace S3D {
		class Scene;
		class BulletDebugDraw;

/// Bullet convex hull.
struct	BulletConvex : public SharedObject
{
		String		name;
		Vector4		center;
		AutoPtr <btConvexHullShape> convex;
};

/// Bullet mesh.
struct	BulletMesh : public SharedObject
{
		String		name;
		String		suffix;
		Vector4		center;

		Array <String> bt_mat;
		Array <ushort> bt_id_mat;
		Array <btScalar> bt_vtx;
		Array <int> bt_idx;

		AutoPtr <btTriangleIndexVertexArray> mesh_interface;
		AutoPtr <btBvhTriangleMeshShape> mesh;
};

/*!
	@short	Bullet physic world.
	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
class	BulletWorld : public PhysicWorld
{
protected:

		SharedList <BulletMesh *> mesh_cache;
		SharedList <BulletConvex *> convex_cache;

		AutoPtr <btDiscreteDynamicsWorld> world;
		AutoPtr <btBroadphaseInterface> broadphase;
		AutoPtr <btCollisionDispatcher> dispatcher;
		AutoPtr <btDefaultCollisionConfiguration> collision_config;
		AutoPtr <btSequentialImpulseConstraintSolver> solver;
		AutoPtr <btOverlappingPairCallback> pair_callback;
#if		__ENABLE_BULLET_MULTITHREAD__
		AutoPtr <btThreadSupportInterface> thread_support_collision;
#endif

		AutoPtr <BulletDebugDraw> debug_draw;

public:

		PhysicItem		*NewItem();
		PhysicConstraint *NewConstraint();

		BulletConvex	*LoadConvex(const char *);
		BulletMesh		*LoadMesh(const char *, const char *suffix);
		void			ClearConvexMeshCache();

		bool			HasDebugger() const;
		void			CreateDebugger(Renderer * = 0);

		void			DrawDebug(Renderer &, Camera *, RasterFont *, bool xray_first_pass);

		/// Raytrace world, the callback object Process() method is called on each hit.
		bool			Raytrace(const Vector4 &s, const Vector4 &d, PhysicTrace &, int collision_mask = ~0, int shape_mask = ~0, float max_distance = -1.f);

		uint			GetCollisionPairCount();
		bool			GetCollisionPair(uint, CollisionPair &);

		void			Step(const Time &dt);

		bool			Create();
		void			Delete();

		BulletWorld();
		~BulletWorld();
};

	} // S3D
} // GS


#endif	// __NBULLETPHYSICWORLD__
