// This is matrix.cc CVS version: $Id: matrix.cc,v 1.2 2000/02/28 18:06:24 andreaha Exp $
#include "eng.h"

/************************************************************************/
/* Matrix class                                                         */
/************************************************************************/

/* constructor, do-nothing */
World::Matrix::Matrix() {
  dpush1("World::Matrix::Matrix()");

  dpop();
}

/* constructor, transfer matrix */
World::Matrix::Matrix(float *n) {
  dpush2("World::Matrix::Matrix(%#010x)",(int)n);

  memcpy(m, n, sizeof(m));

  dpop();
}

/* matrix reset (clear all content) */
void World::Matrix::reset() {
  dpush1("World::Matrix::reset()");

  memset(m, 0, sizeof(m));

  dpop();
}

/* matrix identity */
void World::Matrix::genIdentity() {
  dpush1("World::Matrix::genIdentity()");

  reset();

  m[ 0] = 1;
  m[ 5] = 1;
  m[10] = 1;
  m[15] = 1;

  dpop();
}

void World::Matrix::mulWith(Matrix *nmat) {
  dpush2("World::Matrix::mulWith(%#010x)",(int)nmat);

  float o[16];
  float *n = nmat->m;
  int k;

  memset(o, 0, sizeof(o));

  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      o[(j*4) + i] = 0;

      for (k = 0; k < 4; k++)
        o[(j*4) + i] += m[(k*4) + i] * n[(j*4) + k];
    }
  }

  memcpy(m, o, sizeof(m));

  dpop();
}


/* override matrix operator **/
World::Matrix World::Matrix::operator *(const Matrix &nmat) const {
  dpush2("World::Matrix::operator *(%#010x) const",(int)&nmat);
  
  float o[16];
  const float *n = nmat.m;
  int k;

  memset(o, 0, sizeof(o));

  for (int i = 0; i < 4; i++) {
    for (int j = 0; j < 4; j++) {
      o[(j*4) + i] = 0;

      for (k = 0; k < 4; k++) {
        o[(j*4) + i] += m[(k*4) + i] * n[(j*4) + k];
      }
    }
  }

  dpop();
  return Matrix(o);
}

void World::Matrix::printOut() {
  dpush1("World::Matrix::print()");

  printf("Matrix [%#010x] printout:\n", (int)this);
  printf( "  / %10.2f %10.2f %10.2f %10.2f \\\n", m[0], m[1], m[2], m[3]);
  printf( "  | %10.2f %10.2f %10.2f %10.2f |\n", m[4], m[5], m[6], m[7]);
  printf( "  | %10.2f %10.2f %10.2f %10.2f |\n", m[8], m[9], m[10], m[11]);
  printf("  \\ %10.2f %10.2f %10.2f %10.2f /\n", m[12], m[13], m[14], m[15]);
  printf("\n");

  dpop();
}

/* generate translation matrix */
void World::Matrix::genTranslationWith(float tx, float ty, float tz) {
  dpush4("World::Matrix::genTranslationWith(%3.1f, %3.1f, %3.1f)",tx,ty,tz);

  m[ 0] = 1; m[ 1] = 0; m[ 2] = 0; m[ 3] = tx;
  m[ 4] = 0; m[ 5] = 1; m[ 6] = 0; m[ 7] = ty;
  m[ 8] = 0; m[ 9] = 0; m[10] = 1; m[11] = tz;
  m[12] = 0; m[13] = 0; m[14] = 0; m[15] =  1;   

  dpop();
}

/* generate inverse matrix */
void World::Matrix::genInverseTo(Matrix *nmat) {
  dpush2("World::Matrix::genInverseTo(%#010x)",(int)nmat);

  Matrix tmat;
  float *n = nmat->m;
  float *t = tmat.m;

  genTranslationWith(-n[3], -n[7], -n[11]);
  tmat.genIdentity();

  t[ 0] = n[ 0];
  t[ 1] = n[ 4];
  t[ 2] = n[ 8];
  t[ 4] = n[ 1];
  t[ 5] = n[ 5];
  t[ 6] = n[ 9];
  t[ 8] = n[ 2];
  t[ 9] = n[ 6];
  t[10] = n[10];
  
  mulWith(&tmat);

  dpop();
}


