
//---------------------------------------------------------------------------------
// part of the Chimera 3D Engine - (c)2006-2014 Giovanni Dal Negro giodalnegro@me.com
//---------------------------------------------------------------------------------

#define LIBNAME "Chimera Lite 1.3"

//#define USE_BULLET
//#define USE_BOX2D
//#define USE_BOX2D_DEPRECATED
//#define USE_SOUNDS
//#define USE_3DFILES
//#define USE_NORMALS
//#define USE_VISIBILITY_TEST
//#define FULLRES_DEVICE                //non adatta lo schermo lo mantiene 1:1
//#define FULLRES_DEVICE_DEPRECATED

//----------------------------------------------------------------------------------
// progetti TODO: DA SPOSTARE NEI PREPROCESSOR DEFINE
//----------------------------------------------------------------------------------

/*
#ifdef ULISSE
    #define USE_BOX2D 
    #define USE_BOX2D_DEPRECATED
    #define USE_SOUNDS
#endif

#ifdef GAMBALUNGA
    #define USE_BOX2D 
    #define USE_BOX2D_DEPRECATED
    #define USE_SOUNDS
#endif

#ifdef LUCAS
    #define USE_SOUNDS
    #define USE_BOX2D
#endif

#ifdef TREASURE
    #define USE_BOX2D 
    #define USE_SOUNDS
#endif

#ifdef ISTERZO
    #define USE_SOUNDS 
#endif
*/

//----------------------------------------------------------------------------------

#import <Cocoa/Cocoa.h>
#include <stdio.h>
#include <stdlib.h>
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#include <OpenGL/OpenGL.h>


//----------------------------------------------------------------------------------
//
//----------------------------------------------------------------------------------

#define MAX_SOUNDS              999
#define MAX_ENTITIES			299
#define BASE_TIMER				10
#define SPEED_VAL				200
#define ACCELEROMETER_DEADZONE	0.2

//----------------------------------------------------------------------------------
//macroz
//----------------------------------------------------------------------------------

#define GFXVERSION				3
#define MAX_PATH				1024
#define ALIGN_TEX_BOUNDARY		1
#define	FOV_ANGLE				60.0f
#define ALPHA_MIN_COLOR			0.00001f
#define MAX_TEX_NAMES			64

#ifdef PINOCCHIO
    #define GETRANDOM(min,max)		(( rand() % (int)((( max ) + 1 ) - ( min ))) + ( min ))
    #define GETRANDOMF(min,max)     (fmod((float)rand(),(float)(((max) + (((max)-(min))/10.0f) - (min)))) + (min))
#else
    #define GETRANDOM(min,max)		(( arc4random() % (int)((( max ) + 1 ) - ( min ))) + ( min ))
    #define GETRANDOMF(min,max)     (fmod((float)arc4random(),(float)(((max) + (((max)-(min))/10.0f) - (min)))) + (min))
#endif

#define SWAP_2(x) ( (((x) & 0xff) << 8) | ((unsigned short)(x) >> 8) )
#define SWAP_4(x) ( ((x) << 24) | (((x) << 8) & 0x00ff0000) | (((x) >> 8) & 0x0000ff00) | ((x) >> 24) )
#define FIX_SHORT(x) (*(unsigned short *)&(x) = SWAP_2(*(unsigned short *)&(x)))
#define FIX_INT(x)   (*(unsigned int *)&(x)   = SWAP_4(*(unsigned int *)&(x)))
#define FIX_FLOAT(x) FIX_INT(x)

#define SAFE_DELETE(p)			{ if(p){ delete (p);(p)=NULL;}}
#define SAFE_FREE(p)			{ if(p){ free (p);  (p)=NULL;}}
#define SAFE_DELETE_ARRAY(p)	{ if(p){ delete[] (p);   (p)=NULL; } }
#define SAFE_RELEASE(p)			{ if(p){ (p)->Release(); (p)=NULL; } }
#define PI						3.14159265359
#define DOUBLEPI				6.283185308
#define D2R(x)					((x*PI)/180.0f)
#define R2D(x)					(x*(180.0f / PI))
#define __max(a,b)				(((a) > (b)) ? (a) : (b))
#define __min(a,b)				(((a) < (b)) ? (a) : (b))
#define CLAMP(p,min,max)		__min(max,__max(p,min))

//----------------------------------------------------------------------------------
// metrica del testo
//----------------------------------------------------------------------------------

#define WORD unsigned short
#define BYTE unsigned char

//#pragma pack(1)
struct charInfo
{
    WORD  id;
    WORD  x;
    WORD  y;
    WORD  width;
    WORD  height;
    short xoffset;
    short yoffset;
    short xadvance;
    BYTE  page;
    BYTE  chnl;
};

//#pragma pack(1)
struct kerningPair
{
    WORD  first;
    WORD  second;
    short amount;
};

//----------------------------------------------------------------------------------
//classes
//----------------------------------------------------------------------------------

class cVertex;
class cMatrix;
class cTex;
class cTexture;
class cColor;
class cParticle;
class cScene;
class cObj;
class cTexGfx;
class cKeyFramer;
class cLight;
class cBox;
class cFlare;
class cFramebuffer;
class cTransition;
class cFluide;

//----------------------------------------------------------------------------------
// 
//----------------------------------------------------------------------------------

class cVertex{

public:

	float x,y,z;
   
public:
   
	cVertex(void)
		{ x = y = z = 0.0;}

	cVertex(float xx,float yy,float zz)
		{ x = xx; y = yy; z = zz;}
	
	cVertex(int xx,int yy,int zz)
		{ x = (float)xx; y =(float) yy; z =(float)zz;}
		
	inline cVertex& operator=(const cVertex& pVec)
		{ x = pVec.x ;  y = pVec.y ;  z = pVec.z ; return *this; } 
   
   inline cVertex& operator=(const float& tFloat)
		{ x = tFloat ;  y = tFloat ;  z = tFloat ; return *this; } 
		
	inline int operator==(cVertex &pVec)
		{ return (x == pVec.x && y == pVec.y && z == pVec.z);}

	inline int operator==(float *pVec)
		{ return (x == pVec[0] && y == pVec[1] && z == pVec[2]);}

	inline int operator!=(cVertex &pVec)
		{ return !(pVec == (*this));}

	inline cVertex& operator+=(cVertex &pVec){
		x += pVec.x; y += pVec.y;  z+= pVec.z; return *this;}
   
	inline cVertex& operator-=(cVertex &pVec){
		x -= pVec.x; y -= pVec.y;  z-= pVec.z; return *this;}

	inline cVertex& operator*=(cVertex &pVec){
		x *= pVec.x; y *= pVec.y;  z*= pVec.z; return *this;}

	inline cVertex& operator/=(cVertex &pVec){
		x /= pVec.x; y /= pVec.y;  z/= pVec.z; return *this;}

	inline cVertex& operator/=(float val){
		x /= val;    y /= val;     z/= val;    return *this;}

	inline cVertex& operator*=(float val){
		x *= val;    y *= val;     z*= val;    return *this;}

	inline cVertex operator+(const cVertex& pVec){
		cVertex ret; ret.x = x+pVec.x; ret.y = y+pVec.y; ret.z = z+pVec.z; return ret;}

	inline cVertex operator-(const cVertex& pVec){
		cVertex ret; ret.x = x-pVec.x; ret.y = y-pVec.y; ret.z = z-pVec.z; return ret;}

	inline cVertex operator*(const cVertex& pVec){
		cVertex ret; ret.x = x* pVec.x; ret.y = y*pVec.y; ret.z = z*pVec.z; return ret;}

	inline cVertex operator/(const cVertex& pVec){
		cVertex ret; ret.x = x/pVec.x; ret.y = y/pVec.y; ret.z = z/pVec.z; return ret;}

	inline cVertex operator*(float val){
		cVertex ret; ret.x = x*val; ret.y = y*val; ret.z = z* val; return ret;}

	inline cVertex operator/(float val){
		cVertex ret; ret.x = x/val; ret.y = y/val; ret.z = z/val; return ret;}

	void Clear(void)
		{x = y = z = 0;}

	void Set(float  xx, float yy,  float zz){
		x = xx; 
		y = yy; 
		z = zz;}

	void Set(double xx, double yy, double zz){
		x = (float)xx; 
		y = (float)yy; 
		z = (float)zz;}

	void Set(int xx, int yy, int zz) {
		x = (float)xx; 
		y = (float)yy; 
		z = (float)zz;}

	void Deg2Rad(){
		x = (float)D2R((double)x); 
		y = (float)D2R((double)y); 
		z = (float)D2R((double)z);}

	void Rad2Deg(){
		x = (float)R2D((double)x); 
		y = (float)R2D((double)y); 
		z = (float)R2D((double)z);}

	float Dot(const cVertex& pVec)
	{
		return (float)(x*pVec.x + y*pVec.y + z*pVec.z);	
	}

	inline void Normalize(void)
	{
		float length = Length();
		if (length == 0)
			return;
		float len = 1.0f / length;
		x *= len;
		y *= len;
		z *= len;
	}

	inline cVertex operator*(const cMatrix& tMat);
	
	inline float Length(void) 
	{
		double length = (x * x) + (y * y) + (z * z);
		return (float)sqrt(length);
	}

	inline void Cross(cVertex &p, cVertex &q)
	{
		x = p.y * q.z - p.z * q.y;
		y = p.z * q.x - p.x * q.z;
		z = p.x * q.y - p.y * q.x;
	}

	inline void Clamp(int min, int max)
	{
		x = __min(max,__max(x,min));
		y = __min(max,__max(y,min));
		z = __min(max,__max(z,min));
	}

	inline void RotateX(float amount)
	{
		float s = (float)sin(D2R(amount));
		float c = (float)cos(D2R(amount));
		float yy = y;
		float zz = z;
		  
		y = (yy * c) - (zz * s);
		z = (yy * s) + (zz * c);
	}

	inline void RotateY(float amount)
	{
		float s = (float)sin(D2R(amount));
		float c = (float)cos(D2R(amount));
		float xx = x;
		float zz = z;
		  
		x = (xx * c) + (zz * s);
		z = (zz * c) - (xx * s);
	}

	inline void RotateZ(float amount)
	{
		float s = (float)sin(D2R(amount));
		float c = (float)cos(D2R(amount));
		float xx = x;
		float yy = y;
		  
		x = (xx * c) - (yy * s);
		y = (yy * c) + (xx * s);
	}

	inline void RotateXbyValues(float s,float c)
	{
		float yy = y;
		float zz = z;
		  
		y = (yy * c) - (zz * s);
		z = (yy * s) + (zz * c);
	}

	inline void RotateYbyValues(float s,float c)
	{
		float xx = x;
		float zz = z;
		  
		x = (xx * c) + (zz * s);
		z = (zz * c) - (xx * s);
	}

	inline void RotateZbyValues(float s,float c)
	{
		float xx = x;
		float yy = y;
		  
		x = (xx * c) - (yy * s);
		y = (yy * c) + (xx * s);
	}

	inline void World2Local(cVertex &inVert,cMatrix &inMat);

};

//---------------------------------------------------------------------------------

class cBox{

public:

	cVertex	pt[8];				

};

//----------------------------------------------------------------------------------
// 
//----------------------------------------------------------------------------------

class cMatrix{

public:

	float	m[16];

public:

	cMatrix() {
		Identity();}
	
	inline float *Get(void) {
		return m;}
	
	inline void Set(float *src) {
		memcpy(m, src, sizeof(float) * 16);}
	
	inline void Clear(void) {
		memset(m, 0, sizeof(float) * 16);}

	inline cMatrix& operator=(const cMatrix& src)
	{
		memcpy(m, src.m, sizeof(float) * 16); 
		return *this;
	}

	inline void Identity(void)
	{
		memset(m, 0, sizeof(float) * 16);
		m[0]  = 
		m[5]  = 
		m[10] = 
		m[15] = 1.0f;
	}

	inline void Translate(const cVertex& vec)
	{ 
		m[12] += vec.x; 
		m[13] += vec.y; 
		m[14] += vec.z;
	}

	void Translate(float x, float y, float z)
	{ 
		m[12] += x; 
		m[13] += y; 
		m[14] += z;
	}

	inline cMatrix Transpose(void)
	{
		cMatrix ret;
		ret.m[0]  = m[0];  
		ret.m[1]  = m[4];  
		ret.m[2]  = m[8];   
		ret.m[3]  = ret.m[12];
		ret.m[4]  = m[1];  
		ret.m[5]  = m[5];  
		ret.m[6]  = m[9];   
		ret.m[7]  = ret.m[13];
		ret.m[8]  = m[2];  
		ret.m[9]  = m[6];  
		ret.m[10] = m[10]; 
		ret.m[11] = ret.m[14];
		ret.m[12] = m[3];  
		ret.m[13] = m[7];  
		ret.m[14] = m[11]; 
		ret.m[15] = ret.m[15];
		return ret;
	}

	inline void Invert(void){

		cMatrix r;
		
		float d=1.0f/( 
			m[0] * ( m[5] * m[10] - m[6] * m[9] ) -
			m[1] * ( m[4] * m[10] - m[6] * m[8] ) +
			m[2] * ( m[4] * m[9]  - m[5] * m[8] ) );
			
		r.m[0] =  d * ( m[5] * m[10] - m[6] * m[9] );
		r.m[1] = -d * ( m[1] * m[10] - m[2] * m[9] );
		r.m[2] =  d * ( m[1] * m[6]  - m[2] * m[5] );
		r.m[3] = 0;
			
		r.m[4] = -d * ( m[4] * m[10] - m[6] * m[8] );
		r.m[5] =  d * ( m[0] * m[10] - m[2] * m[8] );
		r.m[6] = -d * ( m[0] * m[6]  - m[2] * m[4] );
		r.m[7] = 0;

		r.m[8] =  d * ( m[4] * m[9]  - m[5] * m[8] );
		r.m[9] = -d * ( m[0] * m[9]  - m[1] * m[8] );
		r.m[10] =  d * ( m[0] * m[5] - m[1] * m[4] );
		r.m[11] = 0;

		r.m[12] = -( m[12] * r.m[0] + m[13] * r.m[4] + m[14] * r.m[8] );
		r.m[13] = -( m[12] * r.m[1] + m[13] * r.m[5] + m[14] * r.m[9] );
		r.m[14] = -( m[12] * r.m[2] + m[13] * r.m[6] + m[14] * r.m[10] );
		r.m[15] = 0;

		*this = r;
	}

	inline cMatrix operator+(const cMatrix& src)
	{
		cMatrix ret;
		ret.m[0]  = m[0]  + src.m[0]; 
		ret.m[1]  = m[1]  + src.m[1];
		ret.m[2]  = m[2]  + src.m[2]; 
		ret.m[3]  = m[3]  + src.m[3];
		ret.m[4]  = m[4]  + src.m[4]; 
		ret.m[5]  = m[5]  + src.m[5];
		ret.m[6]  = m[6]  + src.m[6]; 
		ret.m[7]  = m[7]  + src.m[7];
		ret.m[8]  = m[8]  + src.m[8]; 
		ret.m[9]  = m[9]  + src.m[9];
		ret.m[10] = m[10] + src.m[10]; 
		ret.m[11] = m[11] + src.m[11];
		ret.m[12] = m[12] + src.m[12]; 
		ret.m[13] = m[13] + src.m[13];
		ret.m[14] = m[14] + src.m[14]; 
		ret.m[15] = m[15] + src.m[15];
		return ret;
	}

	inline cMatrix operator-(const cMatrix& src)
	{
		cMatrix ret;

		ret.m[0]  = m[0] -  src.m[0]; 
		ret.m[1]  = m[1] -  src.m[1];
		ret.m[2]  = m[2] -  src.m[2]; 
		ret.m[3]  = m[3] -  src.m[3];
		ret.m[4]  = m[4] -  src.m[4]; 
		ret.m[5]  = m[5] -  src.m[5];
		ret.m[6]  = m[6] -  src.m[6]; 
		ret.m[7]  = m[7] -  src.m[7];
		ret.m[8]  = m[8] -  src.m[8]; 
		ret.m[9]  = m[9] -  src.m[9];
		ret.m[10] = m[10] - src.m[10]; 
		ret.m[11] = m[11] - src.m[11];
		ret.m[12] = m[12] - src.m[12]; 
		ret.m[13] = m[13] - src.m[13];
		ret.m[14] = m[14] - src.m[14]; 
		ret.m[15] = m[15] - src.m[15];
		return ret;
	}

	inline cMatrix operator*(const cMatrix& src)
	{
		cMatrix ret;

		ret.m[0] = m[0] * src.m[0] + m[4] * src.m[1] + m[8] * src.m[2] + m[12] * src.m[3];
		ret.m[1] = m[1] * src.m[0] + m[5] * src.m[1] + m[9] * src.m[2] + m[13] * src.m[3];
		ret.m[2] = m[2] * src.m[0] + m[6] * src.m[1] + m[10] * src.m[2] + m[14] * src.m[3];
		ret.m[3] = m[3] * src.m[0] + m[7] * src.m[1] + m[11] * src.m[2] + m[15] * src.m[3];
		ret.m[4] = m[0] * src.m[4] + m[4] * src.m[5] + m[8] * src.m[6] + m[12] * src.m[7];
		ret.m[5] = m[1] * src.m[4] + m[5] * src.m[5] + m[9] * src.m[6] + m[13] * src.m[7];
		ret.m[6] = m[2] * src.m[4] + m[6] * src.m[5] + m[10] * src.m[6] + m[14] * src.m[7];
		ret.m[7] = m[3] * src.m[4] + m[7] * src.m[5] + m[11] * src.m[6] + m[15] * src.m[7];
		ret.m[8] = m[0] * src.m[8] + m[4] * src.m[9] + m[8] * src.m[10] + m[12] * src.m[11];
		ret.m[9] = m[1] * src.m[8] + m[5] * src.m[9] + m[9] * src.m[10] + m[13] * src.m[11];
		ret.m[10]= m[2] * src.m[8] + m[6] * src.m[9] + m[10] * src.m[10] + m[14] * src.m[11];
		ret.m[11]= m[3] * src.m[8] + m[7] * src.m[9] + m[11] * src.m[10] + m[15] * src.m[11];
		ret.m[12]= m[0] * src.m[12] + m[4] * src.m[13] + m[8] * src.m[14] + m[12] * src.m[15];
		ret.m[13]= m[1] * src.m[12] + m[5] * src.m[13] + m[9] * src.m[14] + m[13] * src.m[15];
		ret.m[14]= m[2] * src.m[12] + m[6] * src.m[13] + m[10] * src.m[14] + m[14] * src.m[15];
		ret.m[15]= m[3] * src.m[12] + m[7] * src.m[13] + m[11] * src.m[14] + m[15] * src.m[15];

		return ret;
	}

	inline cVertex operator*(const cVertex& vec)
	{
		cVertex ret;
		ret.x = vec.x* m[0] + vec.y * m[4] + vec.z * m[8] + m[12];
		ret.y = vec.x* m[1] + vec.y * m[5] + vec.z * m[9] + m[13];
		ret.z = vec.x* m[2] + vec.y * m[6] + vec.z * m[10]+ m[14];
		return ret;
	}

	inline cMatrix& operator+=(cMatrix &src)
	{
		//for (int i=0;i<16:i++)
		//	m[i] += src.m[i]; 

		m[0]  += src.m[0]; 
		m[1]  += src.m[1];
		m[2]  += src.m[2]; 
		m[3]  += src.m[3];
		m[4]  += src.m[4]; 
		m[5]  += src.m[5];
		m[6]  += src.m[6]; 
		m[7]  += src.m[7];
		m[8]  += src.m[8]; 
		m[9]  += src.m[9];
		m[10] += src.m[10]; 
		m[11] += src.m[11];
		m[12] += src.m[12]; 
		m[13] += src.m[13];
		m[14] += src.m[14]; 
		m[15] += src.m[15];
		return *this;
	}

	inline cMatrix& operator*=(cMatrix &src)
	{
		//for (int i=0;i<16:i++)
		//	m[i] *= src.m[i]; 

		m[0]  *= src.m[0]; 
		m[1]  *= src.m[1];
		m[2]  *= src.m[2]; 
		m[3]  *= src.m[3];
		m[4]  *= src.m[4]; 
		m[5]  *= src.m[5];
		m[6]  *= src.m[6]; 
		m[7]  *= src.m[7];
		m[8]  *= src.m[8]; 
		m[9]  *= src.m[9];
		m[10] *= src.m[10]; 
		m[11] *= src.m[11];
		m[12] *= src.m[12]; 
		m[13] *= src.m[13];
		m[14] *= src.m[14]; 
		m[15] *= src.m[15];
		return *this;
	}

	inline cMatrix& operator-=(cMatrix &src)
	{
		//for (int i=0;i<16:i++)
		//	m[i] -= src.m[i]; 

		m[0]  -= src.m[0]; 
		m[1]  -= src.m[1];
		m[2]  -= src.m[2]; 
		m[3]  -= src.m[3];
		m[4]  -= src.m[4]; 
		m[5]  -= src.m[5];
		m[6]  -= src.m[6]; 
		m[7]  -= src.m[7];
		m[8]  -= src.m[8]; 
		m[9]  -= src.m[9];
		m[10] -= src.m[10]; 
		m[11] -= src.m[11];
		m[12] -= src.m[12]; 
		m[13] -= src.m[13];
		m[14] -= src.m[14]; 
		m[15] -= src.m[15];
		return *this;
	}

	inline cVertex dp3(const cVertex& vec)
	{
		cVertex ret;
		ret.x = vec.x* m[0] + vec.y * m[4] + vec.z * m[8];
		ret.y = vec.x* m[1] + vec.y * m[5] + vec.z * m[9];
		ret.z = vec.x* m[2] + vec.y * m[6] + vec.z * m[10];
		return ret;
	}

	inline void Rotate(float angle, const cVertex& vec)
	{
		cMatrix ret;
		float c = (float)cos(angle);
		float s = (float)sin(angle);
		float mc = 1- c;

		ret.m[0]  = (vec.x * vec.x * mc) + c;
		ret.m[1]  = (vec.y * vec.x * mc) + (vec.z * s);
		ret.m[2]  = (vec.x * vec.z * mc) - (vec.y * s);
		ret.m[4]  = (vec.x * vec.y * mc) - (vec.z * s);
		ret.m[5]  = (vec.y * vec.y * mc) + c;
		ret.m[6]  = (vec.y * vec.z * mc) + (vec.x * s);
		ret.m[8]  = (vec.x * vec.z * mc) + (vec.y * s);
		ret.m[9]  = (vec.y * vec.z * mc) - (vec.x * s);
		ret.m[10] = (vec.z * vec.z * mc) + c;

		(*this) *= ret;
	}

};

//---------------------------------------------------------------------------------

inline void cVertex::World2Local(cVertex &inVert,cMatrix &inMat)
{
		cVertex tmp;
		tmp.x = inVert.x - inMat.m[12];
		tmp.y = inVert.y - inMat.m[13];
		tmp.z = inVert.z - inMat.m[14];

		x = inMat.m[0]*tmp.x + inMat.m[1]*tmp.y +inMat.m[2] *tmp.z;
		y = inMat.m[4]*tmp.x + inMat.m[5]*tmp.y +inMat.m[6] *tmp.z;
		z = inMat.m[8]*tmp.x + inMat.m[9]*tmp.y +inMat.m[10]*tmp.z;
}

inline cVertex cVertex::operator*(const cMatrix& tMat)
{
		cVertex ret;
		ret.x = x* tMat.m[0] + y * tMat.m[4] + z * tMat.m[8] + tMat.m[12];
		ret.y = x* tMat.m[1] + y * tMat.m[5] + z * tMat.m[9] + tMat.m[13];
		ret.z = x* tMat.m[2] + y * tMat.m[6] + z * tMat.m[10]+ tMat.m[14];
		return ret;
}

//----------------------------------------------------------------------------------
// 
//----------------------------------------------------------------------------------

class cTex{
	
public:

	float u,v;				

public:

	void Set(float uu, float vv)
	{
		u = uu; 
		v = vv;
	}

};

//----------------------------------------------------------------------------------
// 
//----------------------------------------------------------------------------------

class cColor{

public:
	
	float r,g,b,a;

public:

	cColor(void)
		{r = g = b = a = 1;}

	cColor(float ff)
		{ r = ff; g = ff; b = ff; a = 1.0;}
		
	cColor(float rr,float gg,float bb)
		{ r = rr; g = gg; b = bb; a = 1.0;}
	
	cColor(float rr,float gg,float bb,float aa)
		{ r = rr; g = gg; b = bb; a = aa;}
	
	void Set(float rr, float gg, float bb, float aa)
		{ r = rr; g = gg; b = bb; a = aa;}

	void Set(float rr, float gg, float bb)
		{ r = rr; g = gg; b = bb;}

	void Set(float cc)
		{ r = cc; g = cc; b = cc;}
	
	void Clear(void)
		{ r = g = b = a = 0;}
		
	inline cColor& operator=(float val)
		{r = val;    g = val;     b = val;    a = val; return *this;}
		
	inline cColor& operator/(float val)
		{r /= val;    g /= val;     b /= val;    a /= val; return *this;}
		
	inline cColor& operator*(float val)
		{r *= val;    g *= val;     b *= val;    a *= val; return *this;}

	inline cColor& operator+=(float val)
		{r += val;    g += val;     b += val;    a+=val;  return *this;}

	inline cColor& operator-=(float val)
		{r -= val;    g -= val;     b-= val;    a-=val; return *this;}
		
	inline cColor& operator/=(float val)
		{r /= val;    g /= val;     b/= val;    a/=val; return *this;}

	inline cColor& operator*=(float val)
		{r *= val;    g *= val;     b*= val;    a*=val; return *this;}

	inline cColor& operator+=(cColor &cCol)
		{return (*this + cCol);}

	inline cColor operator-=(cColor &cCol)
		{return (*this - cCol);}
	 
	inline cColor& operator+(cColor &cCol)
	{
		r += cCol.r; 
		g += cCol.g;
		b += cCol.b;
		a += cCol.a;
		return (*this);
	}
	
	inline cColor& operator-(cColor &cCol)
	{
		r -= cCol.r; 
		g -= cCol.g;
		b -= cCol.b;
		a -= cCol.a;
		return (*this);
	}
	
	inline cColor& operator=(cColor &cCol)
	{
		r = cCol.r; 
		g = cCol.g;
		b = cCol.b;
		a = cCol.a;
		return (*this);
	}
	
	inline int operator==(cColor &cCol)
		{ return (r == cCol.r && g == cCol.g && b == cCol.b && a == cCol.a );}
		
	inline int operator!=(cColor &cCol)
		{ return !(cCol == (*this));}
		
	inline void Clamp(float min,float max)
	{
		r = __min(max,__max(r,min));
		g = __min(max,__max(g,min));
		b = __min(max,__max(b,min));
	}
};

//----------------------------------------------------------------------------------
// transition
//----------------------------------------------------------------------------------

enum TRANSITION_TYPE
{
	TRANSITION_COMPRESS_RIGHT = 0,
    TRANSITION_COMPRESS_LEFT,
    TRANSITION_COMPRESS_UP,
    TRANSITION_COMPRESS_DOWN,
	TRANSITION_SLIDE_LEFT,
	TRANSITION_SLIDE_RIGHT,
    TRANSITION_SLIDE_UP,
	TRANSITION_SLIDE_DOWN,
    TRANSITION_CIACK_RIGHT,
    TRANSITION_CIACK_LEFT,
    TRANSITION_CIACK_UP,
    TRANSITION_CIACK_DOWN,
    TRANSITION_PAGE_SHADOWED_RIGHT,     //transitions_old only
    TRANSITION_PAGE_SHADOWED_LEFT,      //transitions_old only
    TRANSITION_ROTATE_AND_SCALE,        //transitions_old only
	TRANSITION_NONE
};

class cTransition
{

public:

	cTransition(cScene* parent,TRANSITION_TYPE kindOfTransition=TRANSITION_SLIDE_LEFT);
	~cTransition();
	
	void Render(void);
	void SetTransition(TRANSITION_TYPE kindOfTransition);
	bool HasEnded(void);
	void Copy(int whatTex=0);
	void Start(void);
	void Stop(void);
	
public:

	GLuint		tex_transition[2];
	cTexture*	tex_transition1;
	cTexture*	tex_transition2;
	float		transition_step;
	bool		transition_active;
	int			transition_kind;
	cScene*		parent;
};

//----------------------------------------------------------------------------------
// texture
//----------------------------------------------------------------------------------

class cTexture
{

public:

	cTexture(char* tfName,int wrapMode=GL_CLAMP_TO_EDGE,bool useFilter=true);
	~cTexture();
	
	GLuint  memAddr;
	char	name[MAX_PATH];
	char    depth;
	Point   size;
};

//----------------------------------------------------------------------------------
// object class
//----------------------------------------------------------------------------------

class cFace{

public:
	
	cFace(){
		v[0] = v[1] = v[2] = 0;}

	cFace(int v0,int v1,int v2)
	{
		v[0] = (unsigned short)v0;
		v[1] = (unsigned short)v1;
		v[2] = (unsigned short)v2;
	}

	cFace operator=(cFace &pFace){
		return cFace(v[0] = pFace.v[0], v[1] = pFace.v[1], v[2] = pFace.v[2]);}

	unsigned short v[3];	//FACE_MODE
	
};

//----------------------------------------------------------------------------------

typedef struct
{

public:

	//from file
	cFace			*face;
	cVertex			*normal;

	int				totFaces;
	cColor			ambient;  
	cColor			diffuse;
	cColor			specular;
	
	//internals
	short			tex_diffuse;
    short           tex_envmap;


}cMat;

//----------------------------------------------------------------------------------

class cSub
{
	
public:

	cVertex		*vertex;
	cTex		*map;
	cMat		*mat;
	cVertex		*normal;

	cBox		localBox;
	cBox		worldBox;
	bool        isVisible;
    
	int			totVertex;
	int			totMaps;
	int			totMaterials;

	char		name[MAX_TEX_NAMES];

};

//----------------------------------------------------------------------------------

typedef struct
{

public:

	cVertex		start_position;
	cVertex		end_position;
	cVertex		start_angle;
	cVertex		end_angle;
	float		steps;
	float		curr_step;
	cColor		start_color;
	cColor		end_color;
	bool		enabled;
	
}sTransition;

class cObj
{
	
public:

	cObj(class cScene* ptr,char* fileName=NULL);
	~cObj();

	void		SetColor(cColor tColor);
	void		SetColor(float r=1,float g=1,float b=1,float a=1);
	void		SetPickColor(GLubyte r=0,GLubyte g=0,GLubyte b=0,GLubyte a=255);
	void		SetAngle(float rx,float ry,float rz);
	void		SetAngle(cVertex rot);
	void		SetPosition(cVertex tPosition);
	void		SetPosition(cVertex tPosition,cVertex tAngle);
	void		SetPosition(float mx,float my,float mz);
	void		SetWorldAngle(float rx,float ry,float rz,float ox,float oy,float oz);
	void		SetScale(float scale);
	void		SetScale(float scaleX,float scaleY,float scaleZ);
    void        SetScalef(float scaleX,float scaleY,float scaleZ);
    void        SetTempScale(float tScale);
    void        SetTempScale(float tScaleX,float tScaleY);
    void        ZeroVertices(void);
    float       GetExtentX(void);
    float       GetExtentY(void);
	void		SetOffset(bool excludeNegative,float scaleX,float scaleY,float scaleZ);
	void		SetBlend(int mode=0,int additive=0);
	void		SetActive(bool activate);
	int			Render(void);
	int			PickRender(void);
	void		PushPosition(void);
	void		SetFixed(int fixMode);
	void		PopPosition(void);
	void		CalcNormals(void);
	void		UpdateBoundBoxes(void);
	void		CreateBoundBoxes(void);
    void        VisibilityTest(void);
    void        SetDrawMode(bool filled=true);
    
	int         BBoxTest(cBox &bb);
	void		StepTransition(void);
	void		StartTransition(int steps, 
					cVertex start_pos,	 cVertex end_pos,
					cVertex start_angle, cVertex end_angle,
					cColor start_color,  cColor end_color);
	
    void        FadeOut(int speed);
    void        FadeIn(int speed);
    void        FadeRelativeIn(int speed);
    void        FadeRelativeOut(int speed);
    void        FadeRelativeAuto(int speed);
    
//#ifdef USE_3DFILES
	int			TDSRead(char* fName);
	bool		GFXReadHeader(FILE* ff,unsigned char &out_version);
	int			GFXLoad(char* fName);
	int         GFXWriteHeader(FILE* ff);
	int			GFXWrite(char* fName);
//#endif

#ifdef USE_BULLET	
	void		PhysicSetPos(void);
	void		PhysicGetPos(void);
	btVector3	getRayTo(int x,int y);
	void		PhysicAddConstraint( int x, int y);
	void		PhysicAddConstraint( float x, float y ,float z);
	void		PhysicUpdateConstraint(int x,int y);
	void		PhysicUpdateConstraint( float x, float y, float z);
	void		PhysicDeleteConstraint(void);
	void		PhysicSetFriction(float friction);
	void		PhysicSetDamping(float dump1=0.05,float dump2=0.85);
	void		PhysicAdd(plCollisionShapeHandle tShape=NULL,float tMass = 100, float tFriction = 1.0);
	void		PhysicApplyVelocity(float mx=0,float my=0,float mz=0,float rx=0,float ry=0,float rz=0);
	void		PhysicApplyImpulse(float ix=0,float iy=0,float iz=0,float rposx=0,float rposy=0,float rposz=0);
	void		PhysicSetBodyAngularVelocity(float ax,float ay,float az);
	void		PhysicSetActivationState(bool active);
	void		PhysicSetGravity(float gravx,float gravy,float gravz);
	void		PhysicSet2DConstraint(void);
#endif

#ifdef USE_BOX2D
    
    void  PhysicSetPos(float x,float y,float angle=0);
	void  PhysicGetPos(void);
    void  PhysicSetMotor(bool tEnabled=true,float speed=1000,float torque=100);
	void  PhysicDestroy(void);
	void  PhysicState(bool tActive=true);
	void  PhysicAdd(float dimx,float dimy,float mass=0,float density=1,float friction=0.3,int groupIndex=0,short catBits=0x0001,float gravityScale=0);
    void  PhysicAddBox(float dimx,float dimy,float mass=0,float density=1,float friction=0.3,int groupIndex=0,short catBits=0x0001,float gravityScale=0);
	void  PhysicAddCircle(float radius,float mass=0,float density=1,float friction=0.3,int groupIndex=0,short catBits=0x0001);
	void  PhysicAddEdge(b2Vec2* vertices,int32 vcount,float mass=0,float density=1,float friction=0.3,int groupIndex=0,short catBits=0x0001);
	void  PhysicAddPoly(b2Vec2* vertices,int32 vcount,float mass=0,float density=1,float friction=0.3,int groupIndex=0,short catBits=0x0001);
	void  PhysicApplyForce(float x1,float y1,float x2,float y2);
	void  PhysicSetLinearVelocity(float x1,float y1);
    float PhysicGetHorizontalVelocity(void);
    float PhysicGetVerticalVelocity(void);
    float PhysicGetAngularVelocity(void);
    void  PhysicSetFixedRotation(bool tRot);
    void  PhysicApplyAngularImpulse(float impulse);
	void  PhysicApplyImpulse(float x1,float y1,float x2=0,float y2=0);
	void  PhysicSetRestitution(float restitution);
	void  PhysicSetFriction(float friction=0.3);
	void  PhysicSetDamping(float linear=0, float angular=0.01);
    void  PhysicSetUserID(int tId);
    int   PhysicGetUserID(void);

#endif

	sTransition	transition;
	cVertex		position;
	cVertex		rotation;
	cVertex		wrotation;
	cVertex     wrotoffset;
	cVertex		scale;
	cVertex     offset;
	int			totObjects;
    int         drawMode;
	cMatrix		identity;
	
	cSub		*subObj;
	
	cBox		localBox;
	cBox		worldBox;
	float		alphaTest;
	bool		active;
	bool		isLighted;
    bool        isVisible;
	int			blendMode;
	cScene*		parent;
	bool		fogMode;
	int			cullMode;
	bool		depthTest;
    int         additiveTexture;
	int			fixedMode;
	GLubyte		pickColor[4];
	bool		updatePos;
	char		name[MAX_TEX_NAMES];

#ifdef USE_BULLET	
	plCollisionShapeHandle	p_Shape;
	plRigidBodyHandle		p_Body;
	bool					p_static;
	btPoint2PointConstraint* p_constraint;
#endif

#ifdef USE_BOX2D

    #define MAX_JOINT   5
    
    #ifndef USE_BOX2D_DEPRECATED
        #define b2LineJoint     b2WheelJoint //NEW
        #define b2LineJointDef  b2WheelJointDef
        b2RopeJoint*        rope_joint;
        b2GearJoint*        gear_joint[MAX_JOINT];
        b2WeldJoint*        weld_joint[MAX_JOINT];
    #endif

	b2Body*					body;
	b2RevoluteJoint*		revolute_joint[MAX_JOINT];
	b2DistanceJoint*		distance_joint[MAX_JOINT];
	b2PrismaticJoint*		prismatic_joint[MAX_JOINT];
    b2LineJoint*            line_joint[MAX_JOINT];
    
	bool					p_static;

#endif

};
//----------------------------------------------------------------------------------
// fluide (operator)
//----------------------------------------------------------------------------------

struct cPerturb
{
	float	upSpd;
	float	newZ;
	bool	inUse;
	float	amplitude;	
	float	frequency;
};

class cFluide
{

public:

	~cFluide();
	cFluide(cScene* ptr);
	
	void SetActive(bool activate);
	void SetSpeed(int tSpeed);
	void SetDuration(int tSpeed=1000);
	void SetObject(int numObj,int numSubObj);
	void SetWaveTime(float tTime=0.004f);
	void SetWaveWeight(float tWeight=0.0002f);
	int  AddImpulse(int row,int col,float tAmplitude=40.0f,float tFrequency=20.0f);
    void ResetPerturb(int pIndex = -1);
	void AddPerturb(int row,int col,float tHeight);
	void SortFaces();
    void Reset(void);
	int  FlatSurface(float speed);
	void Update();
	
	cPerturb *pPerturb;
	cScene* parent;
	long	lifeTimer;
	long	fluideTimer;
	bool	impulseInUse;
	int		speed;
	int		object;
	int		subObj;
	int		totVertex;
	int		rowSize;
	int		duration;
	float	weight;
	float	startupTime;
	float	waveTime;
	bool	processed;
	bool	active;
};

//----------------------------------------------------------------------------------
// flares
//----------------------------------------------------------------------------------

class cFlare{

public:
	
	cFlare(class cScene* ptr);
	~cFlare();

	void		SetActive(bool activate);
	void		SetPosition(float mx,float my,float mz);
	void		SetParms(float r,float g,float b,float a,float fSize,int depthTestType,short faderSpeed);
	void		SetSize(float siz);
	void		SetTexture(char* texName);
	void		SetChangeSpeed(int texChangeSpeed=BASE_TIMER);
	void		SetTexture(int numTex);
	void		SetSpeed(short faderSpeed);
	void		SetDepthTest(int what);
	int			AddEmitter(int numObj,int numSubObj,int numVertex,float offsetX=0,float offsetY=0,float offsetZ=0);
	int			SetOffset(int emitter,short offsetX=0,short offsetY=0,short offsetZ=0);
	void		SetReflect(float reflSize,float reflBright,short reflShape,bool reflFilled);
	int			AddTexChanger(short texChangeSpeed,char* texName);
	void		SetSet(int fSet);
	void		SetColor(float r,float g,float b,float a);
	void		SetColor(cColor tColor);
	void		SetRotation(float tAngle=0);
	
	int			Render();
	void		RenderLensFlare();
	void		Draw(cVertex& x,cVertex& y);
	void		MakeLensFlare(float sx,float sy,float P,float S,float r,float g,float b,float a);
	
	cVertex		position;
	bool		active;
	cScene*		parent;
	cColor		color;
	float		fsize;
	float		flareSize;
	short		flareSet;
	int			object;
	short		texture[MAX_ENTITIES];
	short		totTextures;
	short		emitter[MAX_ENTITIES][2];
	short		totEmitters;
	long		changeTimer;
	short		changeSpeed;
	long		fadeTimer;
	short		fadeSpeed;
	short		curTex;
	float		brightLevel;
	bool		filled;
	short		shape;
	short		alfa[MAX_ENTITIES];
	short		alfaStep;
	float		offset[MAX_ENTITIES][3];
	int			depthTest;
	short		isVisible;
	float		fixedDeltaRot;
	float		deltaRot;
	
};

//----------------------------------------------------------------------------------
// framebuffer
//----------------------------------------------------------------------------------

class cFramebuffer
{
public:
	
	cFramebuffer(cScene* scene,float size,float worldSizeH,float worldSizeV=0);
	~cFramebuffer();
	
	void SetActive(bool tActive);
    void SetPrerender(bool preRendered);
	void CopyTextureInto(char* preloadTexName);
	void SwitchToFBO(bool clear=false);
	void SwitchToMain(void);
	void Render(void);
	void SetPosition(float px,float py,float pz);
		
	cScene*		m_engine;
	float		m_texsize;
	float       m_worldsizeH;
    float       m_worldsizeV;
	bool		m_active;
	bool		m_success;
	GLuint		m_framebuffer;
	GLuint		m_texture;
	GLuint		m_depthBuffer;
	cVertex		m_position;
    bool        m_prerender;
};

int NewFrameBuffer(cScene* scene,float zDepth);

//----------------------------------------------------------------------------------
// particle system
//----------------------------------------------------------------------------------

typedef struct
{

public:

	cVertex		position;
	cVertex		radius;
	cVertex		acceleration;
	cColor		color;
	cColor		iColor;
	int			fLeft;
	
}pUnit;

class cParticle
{	

public:

	cParticle(cScene* ptr);
	~cParticle();
	
	void	SetActive(bool toActivate);
	void	SetColor(float r,float g,float b,float r2,float g2,float b2);
	void	SetSize(float siz);
	void	SetSpace(bool localSpace);
	void	SetPosition(float mx,float my,float mz);
	void	SetDirection(float vx,float vy,float vz);
	void    SetAcceleration(float ax,float ay,float az);
	void	SetVolume(float bx,float by,float bz);
	void    SetStartColor(float r,float g,float b,float a=1);
	void	SetEndColor(float r,float g,float b,float a=1);
	void	SetNumbers(short numParts);
	void	SetRandom(bool randomColor);
	void	SetLife(short liveFrame);
	void	SetRadius(float validRadius);
	void	SetBlend(bool active=TRUE);
	void	SetRate(int emissionRate=1,int tEmissionDelay=0);
	void	SetSpeed(short faderSpeed);
	void	SetTexture(char* texName);
	void	SetTexture(int numTex);
	void	SetDead(bool i=TRUE);
	void	SetDepthTest(bool i);
	void    Reset(void);
	void	SetBlendMode(int tBlendMode=1);
	void	SetAngle(float rx,float ry,float rz);
	void	Deploy(int i,float x,float y,float z);
	int		AddEmitter(int numObj,int numSubObj=0,int numVertex=0,float offsetX=0,float offsetY=0,float offsetZ=0);
	int		SetOffset(int numEmitter,float offsetX,float offsetY,float offsetZ);
	
	int		Render(void);
	void	UpdatePositions(void);
	
	cVertex		position;
	float		size;
	short		life;
	float		radius;	
	cVertex		direction;
	cVertex		acceleration;
	cVertex		speed;
	cVertex		rotation;
	cVertex		volume;
	float		emitted;
	bool        allDead;
	int         emissionRate;
    int         emissionDelay;
    int         emissionCounter;
    int			blendMode;
	bool		random;
	bool		deployed;
	bool		depthtest;
	int			dead;
	short		texture;
	bool		active;	
	cColor		sColor;
	cColor		eColor;
	short		totParts;
	cScene*		parent;
	bool		worldSpace;
	
	int			object;
	float		offset[20][3];
	int			emitter[20][2];
	int			totEmitters;
	
	pUnit*		part;
	cVertex*	part_vertices;
	cTex*		part_coords;
	cColor*		part_color;
};

//----------------------------------------------------------------------------------
// 
//----------------------------------------------------------------------------------

class cTexGfx
{

public:
	
	cTexGfx(cScene* main);
	~cTexGfx();
	
	void SetActive(bool activate);
	void Update(void);
	void SetObject(int numObj,int numSubObj,int numMaterial);
	void SetChanger(int texChangeSpeed,int duration=-1,int startRange=-1,int endRange=-1);
	void AddTexture(int texID);
	
	void SetShift(float shiftOnX,float shiftOnY,short shiftVelocity);

public:
	
	bool	active;
	cScene*	parent;
	int		object;
	int		subObj;
	int		material;
	
	//changer
	int		changeSpeed;
	int		currFrame;
	int		currTex;
	int		currLife;
	int		life;
	int		startRange;
	int		endRange;
	int		textures[MAX_ENTITIES];
	
	//shift
	int		shiftSpeed;
	float	shiftx;
	float	shifty;

};



//----------------------------------------------------------------------------------
// path keyframer
//----------------------------------------------------------------------------------

typedef struct {

public:
	
	friend class cKeyFramer;
	
	short 		frame;
	cVertex 	position;
	cVertex		rotation;
	cVertex		pos_derivate;
	cVertex		rot_derivate;
	
}keyStruct;

//----------------------------------------------------------------------------------
// 
//----------------------------------------------------------------------------------

class cKeyFramer{
	
public:
	
	cKeyFramer(cScene* ptr);
	~cKeyFramer();
	
	void		SetActive(bool activate);
	void		AddKeys(int totKeyz,int numFrames);
	void		AddKey(int numFrames);
	void		SetKey(int numFrames,float mx,float my,float mz,float rx=0,float ry=0,float rz=0);
	void		SetKeyPos(float mx=0,float my=0,float mz=0,float rx=0,float ry=0,float rz=0);
	void		SetKeyAngle(int keyNum,float rx,float ry,float rz);
	void		SetKeyFrames(int keyNum,int framesNum);
	void		SetKeyPosition(int keyNum,float mx,float my,float mz);
	void		Start();
	int			GetFrame(int frame,cVertex &pPos,cVertex &pAng);
	int			GetFrame(cVertex &pPos,cVertex &pAng);
	void		SetAngleTrimmer(float tTrim=0.7f);
	void		SetPositionTrimmer(float tTrim=0.7f);
	void		SetParams(int obj=-1,int itrp=100,int spd=20,float pTrim=0.7f,float aTrim=0.7f);
	void		SetObject(int obj);
	void		SetSpeed(int spd);
	void		LockZeta(bool lockZ);
	void		SetLoop(bool looping);
	void		Clean(void);
	void		SetFreeAngle(bool tFreeAngle=false);
    void        SetFreePosition(bool tFreePosition=false);
	
	bool		active;
	bool		loop;
	int			speed;
	int			object;
	cScene*		parent;
	long		timer;
	int			interpolator;
	keyStruct	*key;
	bool		freeAngle;
    bool        freePosition;
	bool		lockZeta;
	float		posTrimmer;	
	float		angTrimmer;
	short		totKeys;
	short		totFrames;
	bool		inited;
	int			currFrame;
};


//----------------------------------------------------------------------------------
// 
//----------------------------------------------------------------------------------

class cLight{

public:

	cLight(class cScene *ptr,int whatLight=0);
	~cLight();
	
	void		SetPosition(float mx,float my,float mz);
	void		SetDiffuse(float r,float g, float b);
	void		SetAmbient(float r,float g, float b);
	void		SetSpecular(float r,float g, float b);
	void		SetShininess(float level);	//actually unused 
	void		SetActive(bool active);	
	void		SetObject(int obj);	
	void		SetSpotExponent(float val);
	void		SetSpotCutoff(float val);
	void		SetAttenuation(float val);
	void		SetDirection(float dx,float dy,float dz);
	
	void		Render();
	
	cVertex		position;
	bool		active;
	int			object;
	cColor		diffuse;
	cScene*		parent;
	cColor		ambient;
	cColor		specular;
	float		shininess;
	int			radius;
	int			number;
	float		litPos[4];
	
};

//----------------------------------------------------------------------------------
// 
//----------------------------------------------------------------------------------

class cScene
{

public:
	
	cScene(char* bundlePath);
	~cScene();
	
	void Render(GLint resX=0,GLint resY=0);
	void RenderOperators(void);
	void DrawFullScreen(bool pickRender = false);
	void EnableFog(bool enabled=false,float fR=0.0f,float fG=0.0f,float fB=0.0f,float fNear=1.0f,float fFar=300.0f,float fDensity=1.0f);
	int  LoadTexture(char* texName,int texMode=GL_CLAMP_TO_EDGE,bool useFilter=true);
	int  SwapTexture(int idx,char* texName,int texMode=GL_CLAMP_TO_EDGE,bool useFilter=true);
    void SetColorMask(int rr=1,int gg=1,int bb=1,int aa=1);
    void MergeTextures(int texRGB,int texAlpha);
	void Start(void);
	void Stop(void);
	void SetPosition(float x,float y,float z);
	void SetPosition(cVertex tPosition,cVertex tAngle);
	void SetPosition(cVertex tPosition);
	void SetAngle(float x,float y,float z);
	void SetColor(float r,float g,float b, float a);
	void SetGlobalScale(int startObj=0,int endObj=0,float xx=1,float yy=1,float zz=1);
	void SetFrustumFromFOV(bool useOrtho = true,float angle=50,float aspect=0.75,float px=0, float py=0, float zoom=1.0f);
	int  PickObject(int sx,int sy);
	cVertex Convert2Dto3D(float posx, float posy, float posz);
	void DeleteAll(int fromObject=0);
	void EnableAccelerometers(bool tEnable=true);
	void EnableAccelerometerX(bool tEnable=true);
	void EnableAccelerometerY(bool tEnable=true);
	void EnableInteraction(bool tEnable=true);
    cVertex GetExtents();
	void SetAcceleration(float ax,float ay,float az);
	void SetTouchDivider(float tDiv=300.0f,float tAccelFactor=0.005f);
	void SetTouchDividerX(float tDiv=300.0f,float tAccelFactor=0.005f);
	void SetTouchDividerY(float tDiv=300.0f,float tAccelFactor=0.005f);
	void SetAccelerometerSensitivity(float tSensitivity=0.1f);
	void SetShakeSensitivity(float tSensitivity=0.2f);
	void SetAccelerometerDivider(float accelFactor=0.01f,float angle=0);
	void SetAccelerometerDividerX(float accelFactor=0.01f,float angle=0);
	void SetAccelerometerDividerY(float accelFactor=0.01f,float angle=0);
	void SetScale(float scaleX=1.0,float scaleY=1.0,float scaleZ=1.0);
    int  RayToPixel(cVertex &p);
    void StoreFOV(void);
    
	void LoadFont(char* fontName,char* metrikName);
	void DeleteFontMetric(void);
	void Draw3DChars(float iX,float iY,float iZ,float scale,char *writeIn,float r,float g,float b,float a);
	void Draw2DChars(float iX,float iY,float iZ,float scale,char *writeIn,float r,float g,float b,float a);
	void DrawChars(float iX,float iY,float iZ,float xSize,float ySize,char *writeIn,float r,float g,float b,float a);
	void DrawChars(float iX,float iY,float iZ, float scalef, char *writeIn,float r,float g,float b,float a);
	void DrawChars(float iX,float iY,char *writeIn,cColor& inColor);	
	void DrawChars(cVertex v,char *writeIn,cColor& inColor);

#ifdef USE_BULLET
	void PhysicStart(float gravityX=0,float gravityY=-9.8,float gravityZ=0,float stepSimulation=1);
	void PhysicStop(void);
	void PhysicSetGravity(float gravityX=0,float gravityY=0,float gravityZ=0);
	void PhysicAddCallback(void);
	plCollisionShapeHandle PhysicCreateShape(cObj* tObj);
	//void PhysicEnablePlane(int tPlane,bool tEnabled = true);
	//void PhysicAddRevoluteJoint(cObj* obj1,cObj* obj2,float x1 = 0, float y1 = 0,float x2 =0, float y2 =0, float upAngle = 0, float downAngle = 0);
	//void PhysicAddSimpleJoint(cObj* obj,float px,float py);
#endif

#ifdef USE_BOX2D
    #ifndef USE_BOX2D_DEPRECATED
        b2Vec2		PhysicScreenToWorld(float x, float y,bool useCamPos=false);
        void		PhysicStart(float gravityX=0,float gravityY=-10,float stepSimulation=(1.0 / 60.0));
    #else
        b2Vec2		PhysicScreenToWorld(float xx, float yy,bool applyDelta=true,bool ignoreLandscape=false);
        void		PhysicStart(float gravityX=0,float gravityY=-10,float stepSimulation=(1.0 / 60.0));
    #endif
	
    b2Vec2      PhysicGetPos(b2Body* tBody);
	void		PhysicStop(void);
	void		PhysicSetGravity(float gravx,float gravy);
	void		PhysicIdle(void);
    void        PhysicMovePlane(int tPlane,float tPosX, float tPosY);
	void		PhysicEnablePlane(int tPlane,bool tEnabled = true);
	void		PhysicAddRevoluteJoint(cObj* obj1,cObj* obj2,float x1 = 0, float y1 = 0,float x2 =0, float y2 =0, float upAngle = 0, float downAngle = 0);
	void		PhysicAddDistanceJoint(cObj* obj1,cObj* obj2,float x1, float y1,float x2, float y2,float length,float damping=0,float frequency=30);
	void		PhysicAddLineJoint(cObj* obj1,cObj* obj2,float x1, float y1,float x2, float y2,float axis_x,float axis_y,float tLow=0,float tUp=0);

    #ifndef USE_BOX2D_DEPRECATED
        void		PhysicAddRopeJoint(cObj* obj1,cObj* obj2,float x1=-1, float y1=0,float x2=0, float y2=0);
        void		PhysicAddGearJoint(cObj* obj1,b2Joint* tJoint1,b2Joint* tJoint2,float tRatio=0);
        void        PhysicAddWeldJoint(cObj* obj1,cObj* obj2,float wCenterX=0,float wCenterY=0);
        void		PhysicAddPrismaticJoint(cObj* obj1,cObj* obj2,float anchorX, float anchorY,float axysX, float axysY, float tLower, float tUpper);
	#else
        void        PhysicAddPrismaticJoint(cObj* obj1,cObj* obj2,float x1, float y1,float x2, float y2, float tLow, float tUp, float useAnchors=false); //?
    #endif
    
#endif
	
public:
	
#ifdef USE_BULLET
	plPhysicsSdkHandle		p_sdkHandle;
	plDynamicsWorldHandle	p_worldHandle;
	float					p_stepSimulation;
	//b2MouseJoint*			m_mouseJoint;
	//float					m_mouseForce;
	//b2Body*				gBody[3];
#endif

#ifdef USE_BOX2D
	b2World*	world;
	float		sceneScale;
	float32		timeStep; 
	int32		velocityIterations;
	int32		positionIterations;
	b2MouseJoint* m_mouseJoint;
	float		m_mouseForce;
	b2Body*		m_boundBody[4];
	b2Body*		m_mouseBody;
#endif

    cVertex     scale;
	cVertex		position;
	cVertex		angle;
	cVertex		speed;
	cColor		backColor;
	char		dataPath[MAX_PATH];
	bool		useOrtho;
    int         grabImage;
    int         pushWeb;
    int         captureImage;
    int         pushEmail;
    GLuint      grabTexID;
	GLint		resolutionX;
	GLint		resolutionY;
    cVertex     frustumResolution;
    float       frustumZoom;
    float       frustumAngle;
	int			viewport[4];
	bool		renderActive;
    int         renderFxAfter;
    int         showMarkers;
	int			selectedObject;
	float		currCounter;
	int			triggerEvent;
	int			tickCounter;
	long		globalTimer;
	float		frst[6][4];	
    
	cVertex		touchpos;
	bool		touch;
	cVertex		touchDivider;
	cVertex		touchAccelFactor;
	
	bool		accelerometerX;
	bool		accelerometerY;
	cVertex		acceleration;
	cVertex		accelerometerFactor;
	cVertex		accelerometerDeadZone;
	float       accelerometerSensitivity;
	float		shakeSensitivity;
	
	int			totObjs;
	int			totKeyframers;
	int			totParticles;
	int			totTexGfx;
	int			totLights;
	int			totFlares;
	int			totFrameBuffers;
	int			totFluids;
    
	cVertex			globalScale;
	int				globalScaleObj[2];
	
	charInfo*		_charInfo;
	kerningPair*	_kerningPair;
	int				_numChar;
	int				_numKern;
	int				texFont;
	
	cFlare*			pFlare[MAX_ENTITIES];
	cParticle*		pParticle[MAX_ENTITIES];
	cFluide*		pFluide[MAX_ENTITIES];
	cTexture*		pTexture[MAX_ENTITIES];
	cObj*			pObject[MAX_ENTITIES];
	cTexGfx*		pTexGfx[MAX_ENTITIES];
	cLight*			pLight[MAX_ENTITIES];
	cKeyFramer*		pKeyframer[MAX_ENTITIES];
	cFramebuffer*	pFramebuffer[MAX_ENTITIES];
	cTransition*	pTransition;
};


//----------------------------------------------------------------------------------
// SUONI DA SPOSTARE IN SCENES.H
//----------------------------------------------------------------------------------



/*

#ifdef ISTERZO
enum 
{
	snd_click   = 0,
    snd_beep,
    kNumSounds
};
#endif

#ifdef GAMBALUNGA
enum 
{
	snd_page        = 0,
	snd_click,
    
    //0 titolo
    snd_bubbles,   
    
    //1
    snd_risata,
    
    //2
    snd_splash2,
    
    //3
    snd_spada,
    
    //4
    snd_cannoni,
    
    //5
    snd_gambalegno,
    
    //6 panorama
    snd_coltelli,
    snd_franke,
    snd_ragno,
    snd_spavento,
    snd_borbotto1,
    snd_borbotto2,
    snd_borbotto3,
    snd_versoboo,
    snd_versococco,
    
    snd_baby,
    
    //8 arrembaggio
    snd_arrembaggio,
    snd_spadapirata,

    //9 porta
    snd_maialegallina,
    snd_porta,
    
    //10 rapimento
    snd_pianto,
    snd_help,
    snd_grunt,
    snd_pirlacasca,
    
    //12
    snd_elettrico,
    
    //15 bussola
    snd_timone,
    
    //16 stiva
    snd_babyvoice,
    snd_biberon,
    snd_pallacannone,
    
    //19
    snd_bimboride19,
    
    //20
    snd_chele1,
    snd_chele2,
    
    //21
    snd_bolle,
    snd_onda,
    snd_orcain,
    snd_orcaout,
    
    //22
    snd_rutto,
    
    //25
    snd_scorpio,
    
    //26
    snd_ragno26,
    
    //29
    snd_boing,
    snd_borbotto,
    
    //32
    snd_dondola1,
    snd_dondola2,
    snd_flash,
    
    //34
    snd_splash,
    
    //36
    snd_granchio,
    snd_gambaentra,
    snd_gambaesce,
    snd_gallina,
    snd_bimboride,
        
    //37
    snd_dettaglio1,
    snd_dettaglio2,
    snd_dettaglio3,
    
    //38
    snd_organetto1,
    snd_organetto2,
    snd_organetto3,
    
    //39
    snd_tvbutton1,
    snd_tvbutton2,
    
    kNumSounds
};
#endif

#ifdef TREASURE
enum 
{
    //tutti
	snd_page = 0,
    snd_click,
    

    kNumSounds
};
#endif

#ifdef LUCAS
enum 
{
    //tutti
	snd_page = 0,
    snd_click,
    
    //1
    snd_school1a,
    
    //2
    snd_school1b,
    snd_bellschoolC,
    
    //3
    snd_school1c,
    snd_porta,
    
    //7,8
    snd_drum2C,
    
    //9
    snd_portapalestra,
    
    //9,10
    snd_school2a,
    snd_school2b,
    
    //11,12
    snd_school2c,
    
    //19
    snd_sbaglio,
    
    //23,24,25,26
    snd_bambiniparco1,
    snd_bambiniparco2,
    snd_bambiniparco3,
    snd_bambiniparco4,
    snd_esternovociM1,
    snd_esternovociM2,
    snd_accendino,
    snd_albar2a,
    
    //27
    snd_albar1c,
    
    //28
    snd_albar1a,
    
    //29
    snd_albar1b,
    
    //30
    snd_albar2b,
    
    //31
    snd_albar2c,
    
    kNumSounds
};
#endif



*/

//----------------------------------------------------------------------------------
// macro
//----------------------------------------------------------------------------------

void InitSoundEngine(void);
void PlayFile(char* wavePath);
void EndSoundEngine(void);
void SoundEffect(int soundID, bool start=true,bool vibrate=false);
void SoundEffectVolume(int soundID, float volumeVal);
void SoundEffectPitch(int soundID, float pitchVal);


void  PlayMusic(char* musicChar,float startTime = 0, bool onLoop = true);
void  StopMusic(void);
void  SetMusicVolume(float volume=0.30);
float GetMusicTime(void);
float GetMusicVolume(void);
int   GetMusicStatus(void);
void  PauseMusic(bool onPause);
void  PauseSpeech(bool onPause);

void  PlayExtra(char* musicChar,float startTime = 0, bool onLoop = true);
void  StopExtra(void);
void  SetExtraVolume(float volume=1.0);
float GetExtraTime(void);
int   GetExtraStatus(void);

void  PlaySpeech(char* languageChar);
void  StopSpeech(void);
void  SetSpeechVolume(float volume=1.0);
float GetSpeechTime(void);
int   GetSpeechStatus(void);

void  RecordStart(void);
void  RecordStop(void);
void  RecordPlay(void);

void PlayVideo(char * videoChar);
void StopVideo(void);
float GetVideoStatus(void);

void TileTexture(cObj* pObject, float repX,float repY,float compensateDeltaX=0.02f,float compensateDeltaY=0.02f);
void SwapTextureCoord(cObj* pObject, int sub, int senseX, int senseY);
void TileSubTexture(cObj* pObject, int sub, float repX,float repY,float compensateDeltaX=0.02f,float compensateDeltaY=0.02f);
bool IdleAccelerators(cScene* scene, int flag=0);
bool IdleTouches(cScene* scene,int flag);
float MapSize(float imageSize);
void ResizeObject(cScene* scene,int numObj,float dimx,float dimy);
int  BuildCube(cScene* scene,float dim,char* tex1,char* tex2,char* tex3,char* tex4,char* tex5,char* tex6);
int  BuildObject(cScene* scene,float px,float py,float pz,float dimx,float dimy,char* texName=NULL,int texMode=GL_CLAMP_TO_EDGE, bool useFilter = true);
int BuildDoubleObject(cScene* scene,float px,float py,float pz,float dimx,float dimy,char* texName1,char* texName2, int texMode=GL_CLAMP_TO_EDGE, bool useFilter = true);
void InvertUMaps(cScene* scene, int objId);
int LoadTexture(cScene* scene,char* texName,int texMode=GL_CLAMP_TO_EDGE,bool useFilter=true);
int SwapTexture(cScene* scene, int idx,char* texName,int texMode=GL_CLAMP_TO_EDGE,bool useFilter=true);
int  BuildGrid(cScene* scene,float px,float py,float pz,float dimx,float dimy,int step,char* texName=NULL,int texMode=GL_CLAMP_TO_EDGE, bool useFilter = true);
int  AddSubObj(cScene* scene,int numObj,float px,float py,float pz,float dimx,float dimy,char* texName,int texMode=GL_CLAMP_TO_EDGE,bool useFilter = true);
void RotateSubObj(cScene* scene,int numObj,int numSub,float amountZ);
void OffsetSubObj(cScene* scene,int numObj,int numSub,float amountX=0,float amountY=0);
void TouchStart(cScene* scene,float px,float py);
void TouchEnd(cScene* scene);
bool WasShaked(cScene* scene, float accX,float accY,float accZ, float currentTimer);
void SetAcceleratorDivider(float tDiv=300.0f);
void SetAcceleratorDividerX(float tDiv=300.0f);
void SetAcceleratorDividerY(float tDiv=300.0f);
void TouchResponder(cScene* scene,int px,int py);
void DragResponder(cScene* scene,int sx,int sy,int ex,int ey);
void ZoomResponder(cScene* scene,float distance);
void MultiTouchResponder(cScene* scene,int opCode,int p1x,int p1y,int p2x,int p2y);
void ReleaseResponder(cScene* scene,int px,int py);
#ifdef USE_BOX2D
	void ContactResponder(cScene* scene,b2Body* bodyA,b2Body* bodyB);
#endif

//dichiarate ma da implementare nei singoli progetti
void UpdateCameraPositionFromAccelerators(cScene* scene, int flag, float& deltax,float& deltay);
void UpdateCameraPositionFromTouches(cScene* scene, int flag, float& deltax,float& deltay);
void ResetSounds(void);
void LoadSounds(char* dataPath,int set=-1,int localization=0);
void SceneTouchResponder(int px,int py);
void SceneDragResponder(int sx,int sy,int ex,int ey);
void SceneZoomResponder(float distance);
void SceneReleaseResponder(int px,int py);
void SceneMultiTouchResponder(int opCode,int p1x,int p1y,int p2x,int p2y);
void SceneIdleResponder(void);
#ifdef USE_BOX2D
	void SceneContactResponder(b2Body* bodyA,b2Body* bodyB);
#endif
//

//----------------------------------------------------------------------------------
// utils
//----------------------------------------------------------------------------------

unsigned char _gluProject( float objx, float objy, float objz,
						   float model[16], float proj[16], int viewport[4],
						   float *winx, float *winy, float *winz );

unsigned char _gluUnProject( float winx, float winy, float winz,
							 float model[16], float proj[16], int viewport[4],
							 float *objx, float *objy, float *objz );

bool util_exists(char* fName);
cTexture*  util_LoadTexture(char* dataPath,char* texName);

//----------------------------------------------------------------------------------
// extern
//----------------------------------------------------------------------------------

void PhysicCollideFromCallback(bool collide);


/*
#import <QTKit/QTKit.h>

@interface ImageSnap : NSObject 
{
    
    QTCaptureSession                    *mCaptureSession;
    QTCaptureDeviceInput                *mCaptureDeviceInput;
    QTCaptureDecompressedVideoOutput    *mCaptureDecompressedVideoOutput;
    CVImageBufferRef                    mCurrentImageBuffer;
    
    IBOutlet QTCaptureView *mCaptureView;
    QTCaptureVideoPreviewOutput *mCaptureOutput;
    uint8_t *imageData, *previousImageData;
}

+(NSArray *)videoDevices;
-(QTCaptureDevice *)deviceNamed:(NSString *)name;

-(id)init;
-(void)dealloc;
-(BOOL)startSession:(QTCaptureDevice *)device;
-(void)stopSession;
-(void)grabSpeed:(float)speed;

@end
*/

