/****************************************************************************
*
* 3DGEN.H
*
* PROGRAMMER : Chris
*    VERSION : 00.00
*    CREATED : 05/06/98
*   MODIFIED : 05/06/98
*       TABS : 5
*
* DESCRIPTION
*	Header file for 3DGEN.C
*
*****************************************************************************/

#ifndef _3DGEN_H
#define _3DGEN_H

/*---------------------------------------------------------------------------
 *	Import Headers
\*--------------------------------------------------------------------------*/

#include "typedefs.h"
#include "maths.h"
#include "gpu.h"

/*---------------------------------------------------------------------------
 *	Constants
\*--------------------------------------------------------------------------*/

#define USE_ASM

#define W2V_SHIFT	12			// Shift scale of View.Frame to World.Frame
//#define W2V_SHIFT	14			// Shift scale of View.Frame to World.Frame
#define W2V_SCALE 	(1<<W2V_SHIFT)	//  Scale of View Frame to World Frame

#define MAX_OBJECT_VERTICES 256

enum {
	M00,M01,M02,M03,
	M10,M11,M12,M13,
	M20,M21,M22,M23
};

#define SHADE_SHIFT	5
#define DPQ_LENGTH	(256<<SHADE_SHIFT)
#define DPQ_START	(DPQ_END - DPQ_LENGTH)
#define DPQ_END	(20*1024)

#define phd_viewdist	DPQ_END
#define phd_zfar		phd_viewdist
#define phd_znear		20

#define phd_scrwidth	MY_PSX_W
#define phd_scrheight	MY_PSX_H
#define phd_winwidth	MY_PSX_W
#define phd_winheight	MY_PSX_H
#define phd_winxmax		(MY_PSX_W-1)
#define phd_winymax		(MY_PSX_H-1)
#define phd_centerx		(MY_PSX_W/2)
#define phd_centery		(MY_PSX_H/2)

#define OBJ_FLAG_BITS	0x7fc7e000          // GTE Flag for Overflows

/*---------------------------------------------------------------------------
 *	Type Definitions
\*--------------------------------------------------------------------------*/

typedef struct	{
	sint32 x;
	sint32 y;
	sint32 z;
}PHD_VECTOR;

typedef sint16 PHD_ANGLE;

typedef struct	{
	sint32 	x_pos;
	sint32 	y_pos;
	sint32	z_pos;
	PHD_ANGLE	x_rot;
	PHD_ANGLE	y_rot;
	PHD_ANGLE	z_rot;
}PHD_3DPOS;

typedef struct {
	PHD_3DPOS	pos;
	sint32 ambient;	// Ambient Light Level
	sint32 intensity;	// 0-16384 inclusive
	sint32 fodist;		// distance squared of fall off
}PHD_LIGHT;

/*---------------------------------------------------------------------------
 *	Macros
\*--------------------------------------------------------------------------*/

#define ABS(x)	  ((x)<0 ? (-(x)):(x))
#define MIN(x,y) ((x)<=(y) ? (x):(y))
#define MAX(x,y) ((x)>=(y) ? (x):(y))

#define TRIGMULT2(A, B)		(((A)*(B)) >> W2V_SHIFT)
#define TRIGMULT3(A, B, C)	(TRIGMULT2((TRIGMULT2(A, B)), C ))

//###define phd_PopMatrix()	phd_mxptr -= 12

#define phd_atan	phd_atan_asm
#define phd_sqrt	phd_sqrt_asm

//#define phd_cos	phd_cos_asm
//#define phd_sin 	phd_sin_asm

//#define phd_cos(a)	((sint32)(rcossin_tbl[(((a)>>3)&8190)+1]<<2))
//#define phd_sin(a)	((sint32)(rcossin_tbl[(((a)>>3)&8190)]<<2))

//#define phd_RotYXZ 		phd_RotYXZ_asm
//#define phd_RotYXZpack	phd_RotYXZpack_asm
//###define phd_TranslateRel	phd_TranslateRel_asm
//###define phd_TranslateAbs	phd_TranslateAbs_asm
//###define phd_PushMatrix	phd_PushMatrix_asm

//#define InterpolateMatrix InterpolateMatrix_asm

/* -------- replace all Tomb II's shitty maths with some nice maths */

#define phd_cos(a)	((sint32)(rcossin_tbl[(((a)>>3)&8190)+1]))
#define phd_sin(a)	((sint32)(rcossin_tbl[(((a)>>3)&8190)]))

//###define phd_mxptr Matrix
//###define w2v_matrix Matrix
//###define matrix_stack MatrixStack

#define phd_PushMatrix		mPushMatrix
#define phd_PopMatrix		mPopMatrix
#define phd_PushUnitMatrix 	mPushUnitMatrix
#define phd_TranslateRel		mTranslateXYZ
#define phd_TranslateAbs 	mTranslateAbsXYZ
#define phd_RotX			mRotX
#define phd_RotY    		mRotY
#define phd_RotZ			mRotZ
#define phd_RotYXZ			mRotYXZ
#define phd_RotYXZpack		mRotPackedYXZ
#define gar_RotYXZsuperpack	mRotSuperPackedYXZ

#define InitInterpolate		InitInterpolation
#define phd_PushMatrix_I		iPushMatrix
#define phd_PopMatrix_I		iPopMatrix
#define phd_TranslateRel_I	iTranslateXYZ
#define phd_TranslateRel_ID	iTranslateXYZ2
#define phd_RotX_I(ang)		{ mRotX(ang); iRotX(ang); }
#define phd_RotY_I(ang)		{ mRotY(ang); iRotY(ang); }
#define phd_RotZ_I(ang)		{ mRotZ(ang); iRotZ(ang); }
#define phd_RotYXZ_I(x, y, z)	{ mRotYXZ(x, y, z); iRotYXZ(x, y, z); }
#define gar_RotYXZsuperpack_I(p1, p2, s) { mRotSuperPackedYXZ(p1, s); iRotSuperPackedYXZ(p2, s); }


#define S_GetObjectBounds	mClipBoundingBox

/*---------------------------------------------------------------------------
 *	Prototypes
\*--------------------------------------------------------------------------*/

extern sint16 rcossin_tbl[];

extern sint32 phd_left;
extern sint32 phd_right;
extern sint32 phd_top;
extern sint32 phd_bottom;
extern sint32 phd_persp;

extern PHD_ANGLE phd_ls_yaw;
extern PHD_ANGLE phd_ls_pitch;
extern PHD_VECTOR ls_vector_view;

extern void phd_GenerateW2V(PHD_3DPOS *viewpos);
extern void phd_LookAt(sint32 xsrc, sint32 ysrc, sint32 zsrc, sint32 xtar, sint32 ytar, sint32 ztar, PHD_ANGLE roll );
extern void phd_GetVectorAngles(sint32 x, sint32 y, sint32 z, PHD_ANGLE *dest );
extern void phd_NormaliseVector(sint32 x, sint32 y, sint32 z, sint32 *dest );
extern void phd_NormaliseMatrix();
extern void phd_GetMatrixAngles(PHD_ANGLE *dest );
//##extern void phd_RotX(PHD_ANGLE rx );
//##extern void phd_RotY(PHD_ANGLE ry );
//##extern void phd_RotZ(PHD_ANGLE rz );
//###extern void phd_RotYXZ(PHD_ANGLE ry, PHD_ANGLE rx, PHD_ANGLE rz );
//##extern void phd_RotYXZpack(sint32	rots );
//##extern void phd_RotateLight(PHD_ANGLE pitch, PHD_ANGLE yaw );
//##extern void phd_PointLight(PHD_3DPOS *destpos, PHD_3DPOS *lightpos );
extern void phd_InitWindow(int view_angle );
extern void AlterFOV(sint16 view_angle );
//###extern void phd_PushMatrix();
//##extern void phd_PushUnitMatrix();
//##extern void phd_UnitMatrix();
//##extern void phd_TransposeMatrix();
extern void S_ScaleMatrix(sint32 scale );
//##extern int phd_TranslateRel(sint32 x, sint32 y, sint32 z );
//##extern void phd_TranslateAbs(sint32 x, sint32 y, sint32 z );
//##extern int S_GetObjectBounds(sint16 *bptr);

//##extern void phd_RotYXZ_asm(PHD_ANGLE ry,PHD_ANGLE rx,PHD_ANGLE rz);
//##extern void phd_RotYXZpack_asm(sint32 rots);
//##extern int  phd_TranslateRel_asm(sint32 x,sint32 y,sint32 z);
//##extern void phd_TranslateAbs_asm(sint32 x,sint32 y,sint32 z);
//##extern void phd_PushMatrix_asm(void);
//##extern void InterpolateMatrix_asm(void);

extern sint32 phd_atan_asm(sint32 x,sint32 y);
//##extern sint32 phd_cos_asm(sint32 angle);
//##extern sint32 phd_sin_asm(sint32 angle);
extern uint32 phd_sqrt_asm(uint32 n);

//##extern sint32* phd_mxptr;
extern sint32 w2v_matrix[];
//##extern sint32 matrix_stack[];

#endif
