#if !defined(TEXTUREMAPPER_H)
#define TEXTUREMAPPER_H

#include "SurfaceCache.h"

/****************************************************************************/
/** \class TextureMapper
    \brief Projiziert eine Texture aus dem 3D Raum in den 2D Raum 
*****************************************************************************/
class TextureMapper  
{
private:

   int m_xmax; 
   int m_ymax; 

   int m_tex_width;
   int m_tex_height;

   BYTE m_rgbIntensity[256][256];

   bool debugFlag;
   int msg_count;
   Texture* m_tex;
   Surface* m_surface;
    
   int m_height;
   int m_height_1;
   int m_width;
   int m_alpha;
   
   float* m_ZBuffer;
   
public:  
   Vec m_p0;
   Vec m_p1;
   Vec m_p2;
   float m_d;      // Distanz vom Ursprung zur Plane

  // ---------------------------------------------------------------------------
  // Parameter der Vertices:
  // ---------------------------------------------------------------------------
   float x0;       // x0' (projiziert auf Plane)
   float y0;       // y0' (projiziert auf Plane)
   float z0;       // z0-Koordinate (im Raum)
   float c0;       // c0 ==> 1/z0-Koordinate (im Raum)
   float uc0;      // u * c0 (u Texelkoordinate in x-Richtung)
   float vc0;      // v * c0 (v Texelkoordinate in y-Richtung)

   float x1;       // x1' (projiziert auf Plane)
   float y1;       // y1' (projiziert auf Plane)
   float z1;       // z1-Koordinate (im Raum)
   float c1;       // c1 ==> 1/z1-Koordinate (im Raum)
   float uc1;      // u * c1 (u Texelkoordinate in x-Richtung)
   float vc1;      // v * c1 (v Texelkoordinate in y-Richtung)

   float x2;       // x2' (projiziert auf Plane)
   float y2;       // y2' (projiziert auf Plane)
   float z2;       // z2-Koordinate (im Raum)
   float c2;       // c2 ==> 1/z2-Koordinate (im Raum)
   float uc2;      // u * c2 (u Texelkoordinate in x-Richtung)
   float vc2;      // v * c2 (v Texelkoordinate in y-Richtung)

private:
  // ---------------------------------------------------------------------------
  // Gradienten:
  // ---------------------------------------------------------------------------
  float dc_dx;   // dc/dx' (mit dy = const!!)
  float dc_dy;   // dc/dy' (mit dx = const!!)
  float duc_dx;  // duc/dx
  float duc_dy;  // duc/dy
  float dvc_dx;  // dvc/dx
  float dvc_dy;  // dvc/dy

  // ---------------------------------------------------------------------------
  // Hilfsvariablen:
  // ---------------------------------------------------------------------------
  float dx_dy_a;  // Steigung dx/dy der linken  Seite
  float dc_dy_a;  // Steigung dc/dy der linken  Seite
  float duc_dy_a; // Steigung duc/dy der linken Seite
  float dvc_dy_a; // Steigung dvc/dy der linken Seite

  float dx_dy_b;  // Steigung dx/dy der rechten Seite
  float dc_dy_b;  // Steigung dc/dy der rechten Seite
  float duc_dy_b; // Steigung duc/dy der rechten Seite
  float dvc_dy_b; // Steigung dvc/dy der rechten Seite

  float xa;
  float xb;
  float ca;
  float uca;
  float vca;

  BYTE* m_planePixels; 

private:
 void project(float d, Vec p0, Vec p1, Vec p2);
 void addOffset();
 void sortVertices();
 void gradients();
 void gradients2();
 void gradients3();
 void doit();
 void renderSegment(int y1, int y2);
 void renderLine(int y, int x1, int x2, float cs, float ucs, float vcs);
 
public:
 void dumpVertices();
 void dumpProjection();
 void dumpGradients();

public:
   static TextureMapper* getInstance();

private:
  static TextureMapper* _instance;

protected:
	TextureMapper();

public:
	virtual ~TextureMapper();

   void render(float d, Triangle& t, BYTE* pane, float* ZBuffer, int width, int height);
};

#endif // !defined(TEXTUREMAPPER_H)
