/*****************************************************************************
 * $Id: gfx_math_deprecated.hh,v 1.7 2006/07/23 02:04:39 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	Deprecated/unused math functions that possibly could be reinstated.
 * @remarks
 *//*
 * LEGAL:	COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#if 0

////////////////////////////////////////////////////////////////////////////////
/////////////////////////////  M A T R I X   ///////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

/*****************************************************************************
 * Transform a 3D vertex thru two coordinate systems.
 *
 * Two transformations are done.  Typically used to transform objects
 * (such as aircraft) which have their own local coordinate systems.
 * local coords --> world coords --> eye coords
 *
 * @remarks PrepTransformVertex2() must be called prior to TransformVertex2().
 * This requirement is for an optimization that combines two translations
 * (local-->world, world-->eye).
 *****************************************************************************/
static const fp*	tv2_m;
static const fp*	tv2_m2;
static fp			tv2_Ox;
static fp			tv2_Oy;
static fp			tv2_Oz;

static inline void
PrepTransformVertex2( const fp m[MATRIX_ELEMS], const fp m2[MATRIX_ELEMS] )
{
	tv2_m	= m;
	tv2_m2	= m2;
	tv2_Ox	= m[Ox] + m2[Ox];	// combine translations (optimization)
	tv2_Oy	= m[Oy] + m2[Oy];
	tv2_Oz	= m[Oz] + m2[Oz];
}
static inline void
TransformVertex2( EyeVertex* v /*OUT*/, fp x, fp y, fp z ) /* (x,y,z)=LocalVertex */
{
#undef m
#undef m2
#define m  tv2_m
#define m2 tv2_m2
	fp x2, y2, z2;

	// Map local system --> world system
	x2 = x * m[Xx] + y * m[Xy] + z * m[Xz];
	y2 = x * m[Yx] + y * m[Yy] + z * m[Yz];
	z2 = x * m[Zx] + y * m[Zy] + z * m[Zz];

	// Two combined translations: local --> world --> eye
	x2 += tv2_Ox;
	y2 += tv2_Oy;
	z2 += tv2_Oz;

	// Map world system --> eye system
	v->x = x2 * m2[Xx] + y2 * m2[Xy] + z2 * m2[Xz];
	v->y = x2 * m2[Yx] + y2 * m2[Yy] + z2 * m2[Yz];
	v->z = x2 * m2[Zx] + y2 * m2[Zy] + z2 * m2[Zz];
#undef m
#undef m2
}

/*****************************************************************************
 * Translate a matrix relative to itself (local translation).
 * For translating an object.
 *****************************************************************************/
template<typename FPM>
void
TranslateMatrixLocal( uint axis, FPM inc, FPM m[MATRIX_ELEMS]/*OUT*/ )
{
	// Slower but more understandable.
	FPM x, y, z;
	switch ( axis )
	{
		case 0:
			x = inc; y = 0.0; z = 0.0;
			break;
		case 1:
			x = 0.0; y = inc; z = 0.0;
			break;
		case 2:
			x = 0.0; y = 0.0; z = inc;
			break;
	}
	m[Ox] += x * m[Xx] + y * m[Xy] + z * m[Xz];
	m[Oy] += x * m[Yx] + y * m[Yy] + z * m[Yz];
	m[Oz] += x * m[Zx] + y * m[Zy] + z * m[Zz];
}

/*****************************************************************************
 * Template class for a matrix (unusual).
 * Note: Matrix W elements are ignored/invalid.
 *****************************************************************************/
template<typename FPM>
class Matrix
{
public:
	Matrix( const FPM matrix[MATRIX_ELEMS] ) { CopyMatrix( mMatrix, matrix ); }
	FPM mMatrix[MATRIX_ELEMS];
};

/*****************************************************************************
 * Matrix stack template class.
 * Note: Matrix W elements are ignored/invalid.
 *****************************************************************************/
template<typename FPM>
class MatrixStack
{
private:
	/// Stack of pointers to Matrix objects.
	/// Pushing/popping is done at back of vector (vector back = stack top).
	std::vector< Matrix<FPM>* > mMatrixStack;

public:
	MatrixStack( void )
	{
		// nothing
	}
	~MatrixStack()
	{
		while ( ! mMatrixStack.empty() )
		{
			delete mMatrixStack.back(); mMatrixStack.pop_back();
		}
	}

	/// Push a matrix onto the stack.
	void Push( const FPM m[MATRIX_ELEMS] )
	{
		mMatrixStack.push_back( new Matrix<FPM>( m ) ); // Matrix object is a copy
	}

	/// Pop a matrix from the stack.
	/// @return false if stack is empty.
	bool Pop( FPM m[MATRIX_ELEMS] /*OUT*/ )
	{
		if ( ! mMatrixStack.empty() )
		{
			// Pop from head (stack).
			// The STL is tricky: pop_back() returns nothing.
			Matrix<FPM>* popped = mMatrixStack.back(); mMatrixStack.pop_back();
			CopyMatrix( m, popped->mMatrix );
			delete popped;
			return true;
		}
		else return false;
	}

	/// Return size of the matrix stack.
	int Size( void )
	{
		return mMatrixStack.size();
	}
};

////////////////////////////////////////////////////////////////////////////////
///////////////////////////////  T R I G   /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

static inline fp
DistanceSkipSqrt( fp X1, fp Y1, fp Z1,
                  fp X2, fp Y2, fp Z2 )
{
	DISTANCE_SKIP_SQRT_RETURN( X1, Y1, Z1, X2, Y2, Z2 );
}

////////////////////////////////////////////////////////////////////////////////
//////////////////////////////  V E C T O R   //////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

// These would be partial templates if not for Mickeysoft VC++ 6.0 deficiencies.
#define RETURN_DOT_PRODUCT_PV_AR( PV, AR )					\
{															\
	return   (PV)->x * (AR)[0]								\
           + (PV)->y * (AR)[1]								\
           + (PV)->z * (AR)[2];								\
}
static inline fp
DotProduct( const NormalVertex* v1, const fp v2[3] )
{
	RETURN_DOT_PRODUCT_PV_AR( v1, v2 );
}

#endif // 0
