//****************************************************************************//
// matrix.h                                                                   //
// Copyright (C) 2001, 2002 Bruno 'Beosil' Heidelberger                       //
//****************************************************************************//
// This library is free software; you can redistribute it and/or modify it    //
// under the terms of the GNU Lesser General Public License as published by   //
// the Free Software Foundation; either version 2.1 of the License, or (at    //
// your option) any later version.                                            //
//****************************************************************************//

#ifndef CAL_MATRIX_H
#define CAL_MATRIX_H

//****************************************************************************//
// Includes                                                                   //
//****************************************************************************//

#include "cal3d/global.h"

//****************************************************************************//
// Forward declarations                                                       //
//****************************************************************************//

class CalQuaternion;

//****************************************************************************//
// Class declaration                                                          //
//****************************************************************************//

/*****************************************************************************/
/** The matrix class.
*****************************************************************************/

class CAL3D_API CalMatrix
{
	// member variables
public:
	float dxdx,dydx,dzdx;
	float dxdy,dydy,dzdy;
	float dxdz,dydz,dzdz;
	
	// constructors/destructor
public:
	inline CalMatrix()	: dxdx(0.0), dydx(0.0), dzdx(0.0),
		dxdy(0.0), dydy(0.0), dzdy(0.0),
		dxdz(0.0), dydz(0.0), dzdz(0.0)
	{
	}
	
	CalMatrix(const CalQuaternion &q);
	
	inline CalMatrix(float weight, const CalMatrix &m)
	{
		dxdx = m.dxdx*weight;
		dxdy = m.dxdy*weight;
		dxdz = m.dxdz*weight;
		dydx = m.dydx*weight;
		dydy = m.dydy*weight;
		dydz = m.dydz*weight;
		dzdx = m.dzdx*weight;
		dzdy = m.dzdy*weight;
		dzdz = m.dzdz*weight;
	}
	
	
	inline ~CalMatrix() {};
	
	// member functions
public:
	void operator=(const CalQuaternion& q);
	
	inline void operator=(const CalMatrix& m)
	{
		dxdx=m.dxdx; dxdy=m.dxdy; dxdz=m.dxdz;
		dydx=m.dydx; dydy=m.dydy; dydz=m.dydz;
		dzdx=m.dzdx; dzdy=m.dzdy; dzdz=m.dzdz;
	}
	inline void operator *= (const CalMatrix &m)
	{
		float ndxdx=m.dxdx*dxdx+m.dxdy*dydx+m.dxdz*dzdx;
		float ndydx=m.dydx*dxdx+m.dydy*dydx+m.dydz*dzdx;
		float ndzdx=m.dzdx*dxdx+m.dzdy*dydx+m.dzdz*dzdx;
		
		float ndxdy=m.dxdx*dxdy+m.dxdy*dydy+m.dxdz*dzdy;
		float ndydy=m.dydx*dxdy+m.dydy*dydy+m.dydz*dzdy;
		float ndzdy=m.dzdx*dxdy+m.dzdy*dydy+m.dzdz*dzdy;
		
		float ndxdz=m.dxdx*dxdz+m.dxdy*dydz+m.dxdz*dzdz;
		float ndydz=m.dydx*dxdz+m.dydy*dydz+m.dydz*dzdz;
		float ndzdz=m.dzdx*dxdz+m.dzdy*dydz+m.dzdz*dzdz;
		
		dxdx=ndxdx;
		dydx=ndydx;
		dzdx=ndzdx;
		dxdy=ndxdy;
		dydy=ndydy;
		dzdy=ndzdy;
		dxdz=ndxdz;
		dydz=ndydz;
		dzdz=ndzdz;
	}
	
	inline void operator *= (float factor)
	{
		dxdx *= factor;
		dydx *= factor;
		dzdx *= factor;
		dxdy *= factor;
		dydy *= factor;
		dzdy *= factor;
		dxdz *= factor;
		dydz *= factor;
		dzdz *= factor;
	}
	inline void blend(float factor, const CalMatrix& m)
	{
		dxdx += m.dxdx*factor;
		dydx += m.dydx*factor;
		dzdx += m.dzdx*factor;
		dxdy += m.dxdy*factor;
		dydy += m.dydy*factor;
		dzdy += m.dzdy*factor;
		dxdz += m.dxdz*factor;
		dydz += m.dydz*factor;
		dzdz += m.dzdz*factor;
	}
	
	inline float det() const
	{
		return dxdx * (dydy*dzdz-dydz*dzdy)
            -dxdy* ( dydx*dzdz-dzdx*dydz)
			+dxdz* (dydx*dzdy-dzdx*dydy);
	}
	
};


#endif

//****************************************************************************//
