#include "stdafx.h"

#include "Renderer.h"

// MFC - Assists in finding memory leaks:
#ifdef MFC_DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#pragma warning( disable : 4996 )

Renderer* Renderer::_instance = 0;

/****************************************************************************/
/** \brief Liefert die Singleton-Instanz
    \return Pointer auf die Instanz
*****************************************************************************/
Renderer* Renderer::getInstance()
{
 if (_instance == 0) 
   _instance = new Renderer();
 return _instance;
}

/****************************************************************************/
/** \brief Destruktor
*****************************************************************************/
Renderer::~Renderer()
{
delete (m_textureMapper);

delete (m_frustum);

delete (m_spriteMapper);
delete (m_textMapper);
delete (m_surfaceCache);

free(m_ZBuffer);

_instance = 0; // Singleton !!!
}

/****************************************************************************/
/** \brief Konstruktor
*****************************************************************************/
Renderer::Renderer()
  {
  m_drawInfo = false;
  m_isRendererInitialized = false;

  m_textureMapper = TextureMapper::getInstance();
  m_spriteMapper  = SpriteMapper::getInstance();
  m_textMapper    = TextMapper::getInstance();
  m_surfaceCache  = SurfaceCache::getInstance();
  m_textMapper    = TextMapper::getInstance();
   
  m_height      = 0;
  m_width       = 0;
  m_PlanePixels = 0;
  m_ZBuffer     = 0;
  }

/******************************************************************************/
/** \brief Initialisiert den Renderer
    \param width Breite der Canvas (Bildschirmfenster)
    \param height Hoehe der Canvas (Bildschirmfenster)
    \param data Referenz auf den Canvas-Datenbereich 
*******************************************************************************/
void Renderer::initRenderer(int width, int height, BYTE* data)
{
m_height      = height;
m_width       = width;
m_PlanePixels = data;
m_ZBuffer = (float*) malloc (m_height*m_width*sizeof(float));

m_frustum = new Frustum(m_width, m_height); 

clearPlane();

m_isRendererInitialized = true;
}

/******************************************************************************/
/** \brief Rendert genau ein Frame  
*******************************************************************************/
void Renderer::renderFrame()
  {
  }

/******************************************************************************/
/** \brief Render alle Tiles aus der Zone
*******************************************************************************/
void Renderer::renderTiles(std::vector<Tile*> & tileList)
{
Tile* tile; 

// Gehe ueber alle Tiles, die gerendert werden muessen 
for (unsigned int i=0; i < tileList.size(); i++)
   {
   tile = (Tile*)tileList[i];
   
   // Aus der geclippten Vertexliste die 2D Koordinaten ermitteln
   tile->project((float)m_frustum->NearPlaneDist);
   
   // Das geclippte Polygon in Dreiecke aufteilen:
   tile->triangulate();
 
   // Dreiecke rendern:
   for (int n=0; n < tile->m_maxTri; n++)
     {
     m_textureMapper->render((float)m_frustum->NearPlaneDist, tile->m_tri[n], m_PlanePixels, m_ZBuffer, m_width, m_height);
     }
   }
   
   m_surfaceCache->refresh();   
}

/******************************************************************************/
/** \brief Rendert Partikel
    \param partikelList Liste mit allen Prtikeln (Referenzen)
*******************************************************************************/
void Renderer::renderParticles(std::vector<Partikel*> & partikelList)
{
Partikel* partikel; 

for (unsigned int i=0; i < partikelList.size(); i++)
   {
   partikel = (Partikel*)partikelList[i];
   m_spriteMapper->render(partikel, m_PlanePixels, m_ZBuffer, m_width, m_height);
   }
}

/******************************************************************************/
/** \brief Rendert Text
    \param textList Liste mit den Textobjekten (Referenzen) 
*******************************************************************************/
void Renderer::renderText(std::vector<Text*> & textList)
{
Text* text; 

for (unsigned int i=0; i < textList.size(); i++)
   {
   text = (Text*)textList[i];
   if (text->m_text != 0)
      m_textMapper->drawText(m_PlanePixels, text->m_text, text->m_startX, text->m_startY);
   }
}

/******************************************************************************/
/** \brief Loescht den Z-Buffer
*******************************************************************************/
void Renderer::clearZBuffer(void)
{
//   for (int n=0; n < (m_width*m_height); n++)
//       m_ZBuffer[n]=100000000.0f;
   memset(m_ZBuffer, 80, m_width*m_height*sizeof(float));
}

/******************************************************************************/
/** \brief Loescht die Canvas
*******************************************************************************/
void Renderer::clearPlane()
  {
  for (int i=0; i < (m_width*m_height*3); i++)
    m_PlanePixels[i] = 255;
  }
