// ===================================================================
// $Id: matrix4.h,v 1.3 2002/12/05 14:46:39 havran Exp $
//
// matrix4.h
//	Header file for CMatrix4 class in BRDFLIB.
//
// Class: CMatrix4
//
// Licence and usage conditions in November 2003:
// This file can be used and modified only with written permission of
// Vlastimil Havran, Pohodli 27, 57001 Litomysl, the Czech Republic.
// This library is granted to be used by Polina Kondratieva within
// her MPI HIWI job working on BRDFLIB library. The usage condition
// may change in the next version of the library. At the moment,
// the library development is supported by Max-Planck-Institut for
// Informatik, Stuhlsatzenhausweg 85, 66123 Saarbruecken Germany
// See WWW: http://www.mpi-sb.mpg.de
// REPLACEMENT_STRING
//
// Initial coding by Nicholas Wilt, recoded by Vlastimil Havran, 2000.
//
// Given to BRDFLIB project for the Polina Kondratieva's
// HIWI JOB assignment in November 2003.
// ===================================================================

#ifndef __MATRIX4_H__
#define __MATRIX4_H__

// BRDFLIB headers
#include "configh.h"


__BEGIN_BRDFLIB_HEADER

// Forward declarations
class CVector3D;
class CVector4D;
class CMatrix3;

class CMatrix4
{
public:
  float x[4][4]; // first index is column [x], the second is row [y]

  CMatrix4() { }

  // here xXY - 'X' is row, and 'Y' is column - classical mathematical notation
  CMatrix4(float x11, float x12, float x13, float x14,
	   float x21, float x22, float x23, float x24,
	   float x31, float x32, float x33, float x34,
	   float x41, float x42, float x43, float x44);
  
  // copy submatrix to this one, other elements are zero
  CMatrix4(const CMatrix3 &src);

  // Assignment operators
  CMatrix4& operator+= (const CMatrix4 &A); 	// add-to
  CMatrix4& operator-= (const CMatrix4 &A); 	// subtract-from
  CMatrix4& operator*= (const CMatrix4 &A); 	// multiply by matrix
  CMatrix4& operator*= (float A); 		// scale by scalar

  // Fundamental operations
  int Invert();		      // Invert the matrix .. returns 0 = regular
  void Transpose();				// Transpose the matrix
  friend CMatrix4 Invert(const CMatrix4 &M);	// Invert a given matrix
  friend CMatrix4 Transpose(const CMatrix4 &M);	// Transpose a given matrix

  // Create various types of matrix.
  static CMatrix4 IdentityMatrix();
  friend CMatrix4 ZeroMatrix();
  friend CMatrix4 TranslationMatrix(const CVector3D &Location);
  friend CMatrix4 RotationXMatrix(float Angle);
  friend CMatrix4 RotationYMatrix(float Angle);
  friend CMatrix4 RotationZMatrix(float Angle);
  friend CMatrix4 RotationYPRMatrix(float Yaw, float Pitch, float Roll);
  // about axis 'axis' by angle 'Angle'
  friend CMatrix4 RotationAxisMatrix(const CVector3D &axis, float Angle);
  // create the rotation matrix that rotates 'vecFrom' to 'vecTo'
  friend CMatrix4 RotationVectorsMatrix(const CVector3D &vecFrom,
					const CVector3D &vecTo);
  
  friend CMatrix4 ScaleMatrix(float X, float Y, float Z);
  friend CMatrix4 GenRotation(const CVector3D &x, const CVector3D &y,
			     const CVector3D &z);
  friend CMatrix4 QuadricMatrix(float a, float b, float c, float d, float e,
			      float f, float g, float h, float j, float k);
  // returns matrix for transforming normal
  friend CMatrix4 NormalTransformMatrix(const CMatrix4 &M);

  friend CMatrix4 MirrorX();
  friend CMatrix4 MirrorY();
  friend CMatrix4 MirrorZ();
  friend CMatrix4 RotationOnly(const CMatrix4 &x);

  // Binary operators
  friend CMatrix4 operator+ (const CMatrix4 &A, const CMatrix4 &B);
  friend CMatrix4 operator- (const CMatrix4 &A, const CMatrix4 &B);
  friend CMatrix4 operator* (const CMatrix4 &A, float B);
  friend CMatrix4 operator* (const CMatrix4 &A, const CMatrix4 &B);

  // friends returning CVector3D
  friend CVector3D operator*(const CMatrix4 &M, const CVector3D &v);
  friend CVector3D RotateOnly(const CMatrix4 &M, const CVector3D &v);
  friend CVector3D TransformNormal(const CMatrix4 &M, const CVector3D &v);
  friend CVector3D GetTranslation(const CMatrix4 &M);

  // Construct rotation description according VRML'97 specification
  const CVector4D SFRotation(void) const;
  
  // Overloaded output operator.
  friend ostream& operator<< (ostream &s, const CMatrix4 &M);
};


__END_BRDFLIB_HEADER

#endif // __MATRIX4X4_H__

