/*======================================================================*/
/* 3DLib								*/
/*									*/
/* Math header file							*/
/*									*/
/* AUTHOR:	Gabor Nagy						*/
/* DATE:	1996-Dec-18 23:52:02					*/
/*									*/
/* 3DLib(TM) Copyright (C) 1995 by Gabor Nagy. All rights reserved.	*/
/*======================================================================*/
#ifndef _E3DMath_h
#define _E3DMath_h

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


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

// Return values for E3d_2DIntersection
//
enum
{
 E3dDISJOINT=0,
 E3dINTERSECT,
 E3dINTERSECT_P1,
 E3dINTERSECT_P2,
 E3dINTERSECT_Q1,
 E3dINTERSECT_Q2,
 E3dSHARE_P1,
 E3dSHARE_P2,
 E3dSHARE_Q1,
 E3dSHARE_Q2,
 E3dPARALLEL,
 E3dOVERLAP,
 E3dOVERLAP_P1,
 E3dOVERLAP_P2,
 E3dOPPOSITE,
 E3dEQUAL
};


#define M_ToInt(x)	(*(unsigned int*)(&(x)))
#define M_ToFloat(x)	(*(float*)(&x))
#define M_SIGN(x)	(M_ToInt(x)&0x80000000)


//----------------------------------------------------------------
// Inline functions
//----------------------------------------------------------------

#ifndef sgi
//================================
// Fast float absolute value
//================================
static inline float E3dI_FABS(float LF)
{
 unsigned int LI = (M_ToInt(LF)&0x7FFFFFFF);

 return(M_ToFloat(LI));
}
#endif

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


//================================================
// Initialize vector
//================================================
#define E3dM_VectorInit(mVector, mX, mY, mZ)	(mVector).X=(mX), (mVector).Y=(mY), (mVector).Z=(mZ), (mVector).Length=sqrt((mX)*(mX)+(mY)*(mY)+(mZ)*(mZ))

//================================================
// Cross product of two vectors
//================================================
#define E3dM_VectorCrossProduct(mAX, mAY, mAZ, mBX, mBY, mBZ, mCX, mCY, mCZ) mCX = mAY*mBZ - mAZ*mBY,mCY = mAZ*mBX - mAX*mBZ,mCZ = mAX*mBY - mAY*mBX

//================================================
// 3D cross product of two vectors
//================================================
#define E3dM_CrossProduct3D(mAX, mAY, mAZ, mBX, mBY, mBZ, mCX, mCY, mCZ) mCX = mAY*mBZ - mAZ*mBY,mCY = mAZ*mBX - mAX*mBZ,mCZ = mAX*mBY - mAY*mBX


//================================================
// 3D dot product of two vectors
//================================================
#define E3dM_DotProduct3D(mAX, mAY, mAZ, mBX, mBY, mBZ) (mAX*mBX + mAY*mBY + mAZ*mBZ)


//================================================
// 3D dot product of two vectors in structs
//================================================
#define E3dM_DotProduct3Ds(mA, mB) (mA.X*mB.X + mA.Y*mB.Y + mA.Z*mB.Z)


//================================================
// Normalize 3D vector
//================================================
#define E3dM_Normalize3D(mX, mY, mZ)\
{\
 E3dCoordinate	mL=sqrt(mX*mX+mY*mY+mZ*mZ);\
\
 if(mL>0.0)\
 {\
  mL=1.0/mL;\
  mX*=mL;mY*=mL;mZ*=mL;\
 }\
 else\
 {\
  mX=mY=mZ=0.0;\
 }\
}


//========================================
// Normalize 3D vector in a struct
//========================================
#define E3dM_Normalize3Ds(mVec)\
{\
 E3dCoordinate	mL=sqrt(mVec.X*mVec.X+mVec.Y*mVec.Y+mVec.Z*mVec.Z);\
\
 if(mL>0.0)\
 {\
  mL=1.0/mL;\
  mVec.X*=mL;mVec.Y*=mL;mVec.Z*=mL;\
 }\
 else\
 {\
  mVec.X=mVec.Y=mVec.Z=0.0;\
 }\
}


//========================================
// Normalize 3D vector in a struct
//========================================
#define E3dM_Normalize3DsDist(mVec, mDistance)\
{\
 mDistance=sqrt(mVec.X*mVec.X+mVec.Y*mVec.Y+mVec.Z*mVec.Z);\
\
 if(mDistance>0.0)\
 {\
  E3dCoordinate	mL=1.0/mDistance;\
\
  mVec.X*=mL;mVec.Y*=mL;mVec.Z*=mL;\
 }\
 else\
 {\
  mVec.X=mVec.Y=mVec.Z=0.0;\
 }\
}



//----------------------------------------------------------------
// Function prototypes
//----------------------------------------------------------------
extern E3dAngle		E3d_GetAngle2D(E3dCoordinate LXPos, E3dCoordinate LYPos);

extern void		E3d_Orbit(double LLongitude, double LLatitude, double LDistance, E3d3DPosition* L3DPosition);

extern void		E3d_VectorsToQuaternion(E3dVector* LVector0, E3dVector* LVector1, E3dQuaternion* LQuaternion);

extern void		E3d_NormalV(E3dVector* LNormal, E3d3DPosition* LPoint0, E3d3DPosition* LPoint1, E3d3DPosition* LPoint2);
extern E3dCoordinate	E3d_PointDistanceFromLine(double LX, double LY, double LZ, double LX0, double LY0, double LZ0, double LX1, double LY1, double LZ1, double LX2, double LY2, double LZ2);
extern EBool		E3d_Colinear(double LP1X, double LP1Y, double LP2X, double LP2Y, double LP3X, double LP3Y);
extern EBool		E3d_Intersect(double LP1X, double LP1Y, double LP2X, double LP2Y, double LQ1X, double LQ1Y, double LQ2X, double LQ2Y);
extern EBool		E3d_2DIntersection(double LP1X, double LP1Y, double LP2X, double LP2Y, double LQ1X, double LQ1Y, double LQ2X, double LQ2Y, E3d2DPosition* LIntersection);

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

#endif	// _E3DMath_h
