/*======================================================================*/
/* 3DLib (E3d)								*/
/*									*/
/* Matrix header file							*/
/*									*/
/* AUTHOR:	Gabor Nagy						*/
/* DATE:	1996-Dec-18 23:53:10					*/
/*									*/
/* 3DLib(TM) Copyright (C) 1995 by Gabor Nagy. All rights reserved.	*/
/*======================================================================*/
#ifndef _E3DMatrix_h
#define _E3DMatrix_h


#ifndef _E3DTypes_h
#include <E3D/Types.h>
#endif


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif

//----------------------------------------------------------------
// Global variables
//----------------------------------------------------------------
extern E3dMatrix	E3d_IdentityMatrix;

//----------------------------------------------------------------
// Function prototypes
//----------------------------------------------------------------
extern void		E3d_PrintMatrix(E3dMatrix LMatrix);
extern void		E3d_MatrixToQuaternion(E3dMatrix LMatrix, E3dQuaternion* LQuaternion);
extern void		E3d_QuaternionToMatrix(E3dQuaternion* LQuaternion, E3dMatrix LMatrix);

extern void		E3d_VectorGetRotMatrix(E3dCoordinate LX1, E3dCoordinate LY1, E3dCoordinate LZ1, E3dCoordinate LX2, E3dCoordinate LY2, E3dCoordinate LZ2, E3dMatrix LMatrix);
extern void		E3d_NormalGetDefRotMatrix(E3dCoordinate LNx, E3dCoordinate LNy, E3dCoordinate LNz, E3dMatrix LMatrix);


extern void		E3d_MatrixInvert3x3(E3dMatrix LM, E3dMatrix LMI);
extern void		E3d_MatrixInvert3x4(E3dMatrix LM, E3dMatrix LMI);
extern EBool		E3d_MatrixInvert4x4(E3dMatrix LSMatrix, E3dMatrix LDMatrix);

extern void		E3d_MatrixPush(void);
extern void		E3d_MatrixPop(void);
extern void		E3d_MatrixCopy(E3dMatrix LSrcMtx, E3dMatrix LDestMtx);
extern void		E3d_MatrixMult(E3dMatrix LSrcMtx, E3dMatrix LDestMtx);
extern void		E3d_MatrixMult3(E3dMatrix LMatrix1, E3dMatrix LMatrix2, E3dMatrix LDestMtx);

extern EBool		E3d_MatricesEqual(E3dMatrix LMtx1,E3dMatrix LMtx2);
extern void		E3d_MatrixLoadIdentity(E3dMatrix LDestMtx);
extern void		E3d_MatrixResetTrans(E3dMatrix LMatrix, double LX, double LY, double LZ);
extern void		E3d_MatrixTranslate(E3dMatrix LMatrix, double LX, double LY, double LZ);
extern void		E3d_MatrixScale(E3dMatrix LMatrix, double LX,double LY, double LZ);
extern void		E3d_MatrixRotate(E3dMatrix LMatrix, int LAxis, double LAngle);
extern void		E3d_MatrixRotateSinCos(E3dMatrix LMatrix, int LAxis, double LSinA, double LCosA);
extern void		E3d_MatrixRotateXYZ(E3dMatrix LMatrix, E3dAngle LX, E3dAngle LY, E3dAngle LZ, int LOrder);

extern void		E3d_MatrixToEuler(int LRotOrder, E3dMatrix LM, float LRot[3]);
extern void		E3d_DecomposeMatrix(E3dMatrix LMatrix, E3dDecompMatrix* LDMatrix, int LRotOrder);
extern void		E3d_MatrixTransformPosition(E3dMatrix LMatrix, E3d3DPosition* LPosition);
extern void		E3d_MatrixTransformHPosition(E3dMatrix LMatrix, E3dHPosition* LPosition);
extern void		E3d_MatrixTransformVector(E3dMatrix LMatrix, E3dVector* LVector);
extern void		E3d_MatrixTransformVector3x3(E3dMatrix LMatrix, E3dVector* LVector);

extern void		E3d_MatrixLookAt(E3dMatrix LMatrix, double LUpX, double LUpY, double LUpZ, double LCamX, double LCamY, double LCamZ, double LIntX, double LIntY, double LIntZ);
extern void		E3d_MatrixLookAlong(E3dMatrix LMatrix, double LFX, double LFY, double LFZ, double LUpX, double LUpY, double LUpZ, double LCamX, double LCamY, double LCamZ);
extern void		E3d_MatrixSetLookAlong(E3dMatrix LMatrix, double LFX, double LFY, double LFZ, double LUpX, double LUpY, double LUpZ, double LCamX, double LCamY, double LCamZ);

#ifdef USEOpenGL
extern void		E3d_MatrixPushGL(void);
extern void		E3d_MatrixPopGL(void);
#endif // USEOpenGL


//----------------------------------------------------------------
// Macro functions
//----------------------------------------------------------------

//================================================================
// Initialize mX, mY and mZ from a structure with X, Y and Z
//================================================================
#define E3dM_InitXYZ(xyzs)	mX=(xyzs).X,mY=(xyzs).Y,mZ=(xyzs).Z

//========================================================
// Transform XYZ with a Matrix's left 3x4 part
//========================================================
#define E3dM_MatrixTransform3x4(mtx, xo, yo, zo)\
 xo=mX*(mtx)[M00]+mY*(mtx)[M10]+mZ*(mtx)[M20]+(mtx)[M30],\
 yo=mX*(mtx)[M01]+mY*(mtx)[M11]+mZ*(mtx)[M21]+(mtx)[M31],\
 zo=mX*(mtx)[M02]+mY*(mtx)[M12]+mZ*(mtx)[M22]+(mtx)[M32]


//================================================================
// Transform XYZW a with a given matrix	
//================================================================
#define E3dM_MatrixTransformHPosition(matrix, xo, yo, zo, wo)\
 xo=mX*matrix[M00]+mY*matrix[M10]+mZ*matrix[M20]+matrix[M30],\
 yo=mX*matrix[M01]+mY*matrix[M11]+mZ*matrix[M21]+matrix[M31],\
 zo=mX*matrix[M02]+mY*matrix[M12]+mZ*matrix[M22]+matrix[M32],\
 wo=mX*matrix[M03]+mY*matrix[M13]+mZ*matrix[M23]+matrix[M33]

//================================================================
// Transform XYZW a with a 4x4 Matrix	
//================================================================
#define E3dM_MatrixTransform4x4(matrix, xo, yo, zo, wo)\
 xo=mX*matrix[M00]+mY*matrix[M10]+mZ*matrix[M20]+mW*matrix[M30],\
 yo=mX*matrix[M01]+mY*matrix[M11]+mZ*matrix[M21]+mW*matrix[M31],\
 zo=mX*matrix[M02]+mY*matrix[M12]+mZ*matrix[M22]+mW*matrix[M32],\
 wo=mX*matrix[M03]+mY*matrix[M13]+mZ*matrix[M23]+mW*matrix[M33]

//================================================================
// Transform XYZ with a Matrix's top-left 3x3 part
//================================================================
#define E3dM_MatrixTransform3x3(mtx,xo,yo,zo)\
 (xo)=mX*(mtx)[M00]+mY*(mtx)[M10]+mZ*(mtx)[M20],\
 (yo)=mX*(mtx)[M01]+mY*(mtx)[M11]+mZ*(mtx)[M21],\
 (zo)=mX*(mtx)[M02]+mY*(mtx)[M12]+mZ*(mtx)[M22]


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration which encloses file.
#endif

#endif	// _E3DMatrix_h
