#ifndef __CAMERA_H
#define __CAMERA_H


enum cameraModeT
	{
	CAMERAMODE_ABSOLUTE=1,
	CAMERAMODE_LOOKRELATIVE,
	CAMERAMODE_CAMERARELATIVE,
	CAMERAMODE_FOLLOW,
	CAMERAMODE_FOLLOW2D
	};
typedef enum cameraModeT cameraModeT;


struct cameraCommonT
	{
	float
			look[3],camera[3],
			up[3],toUp[3],toUpRate,
			fov,toFov,toFovRate,
			slide[2],toSlide[2],toSlideRate[2];
	};
typedef struct cameraCommonT cameraCommonT;


struct cameraAbsoluteT
	{
	float
			toLook[3],toLookRate,
			toCamera[3],toCameraRate;
	};
typedef struct cameraAbsoluteT cameraAbsoluteT;

struct cameraCommonAbsoluteT
	{
	cameraCommonT common;
	cameraAbsoluteT absolute;
	};
typedef struct cameraCommonAbsoluteT cameraCommonAbsoluteT;


struct cameraRelativeT
	{
	float
			basePoint[3],baseDirection,baseAngle,
			distance,toDistance,toDistanceRate,
			direction,toDirection,toDirectionRate,
			angle,toAngle,toAngleRate;
	};
typedef struct cameraRelativeT cameraRelativeT;

struct cameraCommonRelativeT
	{
	cameraCommonT common;
	cameraRelativeT relative;
	};
typedef struct cameraCommonRelativeT cameraCommonRelativeT;


struct cameraFollowT
	{
	float
			basePoint[3],
			followPoint[3],followDistance,
			forward[3],forwardRate,
			cameraDistance,toCameraDistance,toCameraDistanceRate,
			cameraDirection,toCameraDirection,toCameraDirectionRate,
			cameraAngle,toCameraAngle,toCameraAngleRate;
	};
typedef struct cameraFollowT cameraFollowT;

struct cameraCommonFollowT
	{
	cameraCommonT common;
	cameraFollowT follow;
	};
typedef struct cameraCommonFollowT cameraCommonFollowT;


struct cameraFollow2dT
	{
	float
			basePoint[3],standardHeight,baseMinHeight,baseMaxHeight,
			follow2dPoint[2],follow2dDistance,
			forward2d[2],forward2dRate,forward2dMax,
			velocity2d,velocity2dRate,velocity2dMax,
			lookHeightMinRate,lookHeightMaxRate,
			cameraDistance,toCameraDistance,toCameraDistanceRate,
			cameraDirection,toCameraDirection,toCameraDirectionRate,
			cameraAngle,toCameraAngle,toCameraAngleRate,cameraHeightRate,
			cameraBankRate;
	int axis[3],  /* axis[0,1] : 2D field axis , axis[2] : vertical axis */
			cameraBank;  /* flag of camera banking */
	};
typedef struct cameraFollow2dT cameraFollow2dT;

struct cameraCommonFollow2dT
	{
	cameraCommonT common;
	cameraFollow2dT follow2d;
	};
typedef struct cameraCommonFollow2dT cameraCommonFollow2dT;


struct cameraT
	{
	cameraModeT mode;  /* the value in CAMERAMODE_* */
	struct cameraCommonT common;
	union 
		{
		cameraAbsoluteT absolute;
		cameraRelativeT relative;
		cameraFollowT follow;
		cameraFollow2dT follow2d;
		}
		data;
	};
typedef struct cameraT cameraT;


void cameraCommon(cameraT *pCamera);

void initializeCameraAbsolute(cameraT *pCamera,
		const cameraCommonT *pCommon,const cameraAbsoluteT *pAbsolute);
void initializeCameraCommonAbsolute(cameraT *pCamera,
		const cameraCommonAbsoluteT *pCommonAbsolute);
void cameraSetAbsoluteUpFov(cameraT *pCamera,const float *pfToLook,
		const float *pfToCamera,const float *pfToUp,const float *pfToFov);
void cameraAbsolute(cameraT *pCamera);

void initializeCameraRelative(cameraT *pCamera,cameraModeT mode,
		const cameraCommonT *pCommon,const cameraRelativeT *pRelative);
void initializeCameraCommonRelative(cameraT *pCamera,cameraModeT mode,
		const cameraCommonRelativeT *pCommonRelative);
void cameraSetRelativeUpFov(cameraT *pCamera,const float *pfBasePoint,
		const float *pfRelative,const float *pfToUp,const float *pfToFov);
void cameraRelative(cameraT *pCamera);

#ifdef CAMERAFOLLOW
void initializeCameraFollow(cameraT *pCamera,
		const cameraCommonT *pCommon,const cameraFollowT *pFollow);
void initializeCameraCommonFollow(cameraT *pCamera,
		const cameraCommonFollowT *pCommonFollow);
void cameraFollow(cameraT *pCamera);
#endif  /* CAMERAFOLLOW */

void initializeCameraFollow2d(cameraT *pCamera,
		const cameraCommonT *pCommon,const cameraFollow2dT *pFollow2d);
void initializeCameraCommonFollow2d(cameraT *pCamera,
		const cameraCommonFollow2dT *pCommonFollow2d);
void cameraSetFollow2dUpFov(cameraT *pCamera,const float *pfBasePoint,
		const float *pfForward2d,const float *pfVelocity2d,
		const float *pfRelativeCamera,const float *pfToUp,const float *pfToFov);
void cameraFollow2d(cameraT *pCamera);

void cameraProper(cameraT *pCamera);


#endif  /* __CAMERA_H */
