#include "stdafx.h"

#include <vector>

#include "SpriteMapper.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 : 4244 )

SpriteMapper* SpriteMapper::_instance = 0;

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

/****************************************************************************/
/** \brief Konstruktor
*****************************************************************************/
SpriteMapper::SpriteMapper()
{
m_ZBuffer = 0;
}

/****************************************************************************/
/** \brief Destruktor
*****************************************************************************/
SpriteMapper::~SpriteMapper()
{
_instance = 0; // Singleton !!!
}

/******************************************************************************/
/** \brief Rendert das Partikel auf die Pane (aka Canvas)
    \param partikel Das Partikel
    \param pane die Canvas hier mal pane genannt
    \param ZBuffer der Z-Buffer
    \param width Breite der pane
    \param height Hoehe der pane 
*******************************************************************************/
void SpriteMapper::render(Partikel* partikel, BYTE* pane, float* ZBuffer, int width, int height)
  {
  m_planePixels = pane;
  m_ZBuffer = ZBuffer;

  float zBuf, z;

  //unsigned int i=0, n=0;
  int u_screen, v_screen, k_screen;  
  int /*u_sprite, v_sprite,*/ k_sprite;  
  
  z = partikel->m_pos.m_z;

  if (z < 0)
     return;

  if (partikel->isON() == false)
     return;

  partikel->querySprite();
//  TRACE ("Partikel.scale=%f\n", partikel->m_scale);


  // uv-Koordinaten aus der Nearplane in die Canvas verschubsen und y-Komplement beruecksichtigen
  float w_halbe = width  / 2;
  float v_halbe = height / 2;

  int u0 = (int)(w_halbe + partikel->m_u0);
  int v0 = height - (int)(v_halbe + partikel->m_v0);

  int u1 = (int)(w_halbe + partikel->m_u1);
  //int v1 = height - (int)(v_halbe + partikel->m_v1);

  //int u2 = (int)(w_halbe + partikel->m_u2);
  //int v2 = height - (int)(v_halbe + partikel->m_v2);

  //int u3 = (int)(w_halbe + partikel->m_u3);
  int v3 = height - (int)(v_halbe + partikel->m_v3);

  //int du_partikel = u1-u0;
  //int dv_partikel = v2-v0;

  Sprite* sprite = partikel->m_sprite; 
  int du_sprite = sprite->getWidth();
  //int dv_sprite = sprite->getHeight();

  float delta =  (float)sprite->getWidth() / (float)(u1-u0);
  float vs, us;
  int yy, xx;

  float af = 1; 
  if (partikel->m_isFading == true)
      {
      af = af - partikel->getONtime(); // 0 ... 1
      }

  for (vs=0, v_screen=v0; v_screen<v3; vs += delta, v_screen++) 
     {
     yy = du_sprite * 4 * (int)vs;
     for (us=0, u_screen=u0; u_screen<u1; us+=delta, u_screen++) 
        {
        if ((u_screen < 0) || (u_screen >= width) || (v_screen < 0) || (v_screen >= height))
           continue;

        zBuf = m_ZBuffer[(v_screen * width) + u_screen];
        if (z > zBuf)
           continue;

        xx = (int)us * 4;
        k_sprite  = yy + xx; 
        k_screen  = (v_screen * width * 3) + (u_screen*3);

        float ro, go, bo;
        float rs, gs, bs, as;
        float rd, gd, bd;
        BYTE r, g, b, a;

         // Sprite: ARGB, Plane:BGR
        a = partikel->m_sprite->m_indexArray[k_sprite];   // Sprite.Alpha (0:transparent, 255:undurchsichtig
        if (a == 0)
           continue;

        r = partikel->m_sprite->m_indexArray[k_sprite+1]; // Sprite.Red
        g = partikel->m_sprite->m_indexArray[k_sprite+2]; // Sprite.Green
        b = partikel->m_sprite->m_indexArray[k_sprite+3]; // Sprite.Blue

        as = (float) a / 255.0f; // Alpha der Source (Sprite)  0...1
        as = as * af;            // Alpha als eine Zeitfunktion 
        rs = (float) r / 255.0f; 
        gs = (float) g / 255.0f; 
        bs = (float) b / 255.0f; 

        r = m_planePixels[k_screen+2];
        g = m_planePixels[k_screen+1];
        b = m_planePixels[k_screen];
        
        rd = (float) r / 255.0f; 
        gd = (float) g / 255.0f; 
        bd = (float) b / 255.0f; 

        ro = as * rs + (1.0f - as) * rd;
        go = as * gs + (1.0f - as) * gd;
        bo = as * bs + (1.0f - as) * bd;

        m_planePixels[k_screen+2] = (BYTE) (ro * 255.0f);
        m_planePixels[k_screen+1] = (BYTE) (go * 255.0f);
        m_planePixels[k_screen]   = (BYTE) (bo * 255.0f);
        }
     }
  }
