///////////////////////////////////////////////////////////
//                                                       //
//  PC MAGAZIN - Demo Projekt                            //
//                                                       //
//  Hier sind die Routinen untergebracht, um Bitmap      //
//  Effekte mit dem 8x8 Mapper zu Zeichnen               //
//                                                       //
///////////////////////////////////////////////////////////
#include "grid.h"
#include "demo.h"

           ///////////////////////////////////////////////////////////
           //                                                       //
           //  Routinen zum Zeichnen der 8x8 Blöcke                 //
           //                                                       //
           ///////////////////////////////////////////////////////////


void Render8x8Block (GridPointUV    &a,
                     GridPointUV    &b,
                     GridPointUV    &c,
                     GridPointUV    &d,
                     unsigned short *dest,
                     long           PixelPerLine,
                     unsigned short *palette,
                     unsigned char  *texture)
// -----------------------------------------------------
// Ein Kästchen mit UV-Koordinaten auf ein Bitmap Rendern
// ------------------------------------------------------
{
        signed long dudx, dvdx;
        signed long dudy_left, dvdy_left;
        signed long dudy_right, dvdy_right;
        signed long u, v;
        GridPointUV left, right;

        // Vorberechung der Steigung für die Y-Interpolation
        dudy_left = (b.u - a.u)/8;
        dvdy_left = (b.v - a.v)/8;
        dudy_right= (d.u - c.u)/8;
        dvdy_right= (d.v - c.v)/8;

        // Initialisieren der Y-Interpolations Variablen
        left  = a;
        right = c;

        // Schleife über die Höhe des Kästchens:
        for ( unsigned char y=0; y<8; y++)
        {

                // Vorberechung der Steigung für die X-Interpolation
                dudx = (right.u-left.u)/8;
                dvdx = (right.v-left.v)/8;

                // Initialisieren der X-Interpolations Variablen
                u = left.u;
                v = left.v;

                // Schleife über die Breite des Kästchens.
                for ( unsigned char x=0; x<8; x++)
                {
                        unsigned char pixel = texture[ ((u>>16) & 0x00ff) | ((v>>8) & 0xff00)];
                        *(dest++) = palette[pixel];
                        // Steigung addieren:
                        u+=dudx;
                        v+=dvdx;
                }

                // Ziel-Pointer auf nächste Bitmap-Zeile stellen:
                dest    += PixelPerLine-8;
                // Ausführen der Y-Interpolation für Links und Rechts
                left.u  += dudy_left;
                left.v  += dvdy_left;
                right.u += dudy_right;
                right.v += dvdy_right;
        }
}


void Render8x8Block (GridPointUV    &a,
                     GridPointUV    &b,
                     GridPointUV    &c,
                     GridPointUV    &d,
                     unsigned short  *dest,
                     long           PixelPerLine,
                     unsigned short  *texture)
// -----------------------------------------------------
// Ein Kästchen mit UV-Koordinaten auf ein Bitmap Rendern
// Diese Variante zeichnent direkt in 16-Bit.
// ------------------------------------------------------
{
        signed long dudx, dvdx;
        signed long dudy_left, dvdy_left;
        signed long dudy_right, dvdy_right;
        signed long u, v;
        GridPointUV left, right;

        // Vorberechung der Steigung für die Y-Interpolation
        dudy_left = (b.u - a.u)/8;
        dvdy_left = (b.v - a.v)/8;
        dudy_right= (d.u - c.u)/8;
        dvdy_right= (d.v - c.v)/8;

        // Initialisieren der Y-Interpolations Variablen
        left  = a;
        right = c;

        // Schleife über die Höhe des Kästchens:
        for ( unsigned char y=0; y<8; y++)
        {

                // Vorberechung der Steigung für die X-Interpolation
                dudx = (right.u-left.u)/8;
                dvdx = (right.v-left.v)/8;

                // Initialisieren der X-Interpolations Variablen
                u = left.u;
                v = left.v;

                // Schleife über die Breite des Kästchens.
                for ( unsigned char x=0; x<8; x++)
                {
                        *(dest++) =texture[ ((u>>16) & 0x00ff) | ((v>>8) & 0xff00)];
                        // Steigung addieren:
                        u+=dudx;
                        v+=dvdx;
                }

                // Ziel-Pointer auf nächste Bitmap-Zeile stellen:
                dest    += PixelPerLine-8;
                // Ausführen der Y-Interpolation für Links und Rechts
                left.u  += dudy_left;
                left.v  += dvdy_left;
                right.u += dudy_right;
                right.v += dvdy_right;
        }
}


void Render8x8Block (GridPointUVG   &a,
                     GridPointUVG   &b,
                     GridPointUVG   &c,
                     GridPointUVG   &d,
                     unsigned short *dest,
                     long           PixelPerLine,
                     unsigned short *palette,
                     unsigned char  *texture)
// -----------------------------------------------------
// Ein Kästchen mit UVG-Koordinaten auf ein Bitmap Rendern
// ------------------------------------------------------
{
        signed long dudx, dvdx, dgdx;
        signed long dudy_left, dvdy_left, dgdy_left;
        signed long dudy_right, dvdy_right, dgdy_right;
        signed long g, u, v;
        GridPointUVG left, right;

        // Vorberechung der Steigung für die Y-Interpolation
        dudy_left = (b.u - a.u)/8;
        dvdy_left = (b.v - a.v)/8;
        dgdy_left = (b.g - a.g)/8;
        dudy_right= (d.u - c.u)/8;
        dvdy_right= (d.v - c.v)/8;
        dgdy_right= (d.g - c.g)/8;

        // Initialisieren der Y-Interpolations Variablen
        left  = a;
        right = c;

        // Schleife über die Höhe des Kästchens:
        for ( unsigned char y=0; y<8; y++)
        {
                // Vorberechung der Steigung für die X-Interpolation
                dudx = (right.u-left.u)/8;
                dvdx = (right.v-left.v)/8;
                dgdx = (right.g-left.g)/8;

                // Initialisieren der X-Interpolations Variablen
                u = left.u;
                v = left.v;
                g = left.g;

                // Schleife über die Breite des Kästchens.
                for ( unsigned char x=0; x<8; x++)
                {

                        *(dest++) = palette[ texture[ ((u>>16) & 0x00ff) | ((v>>8) & 0xff00)]
                                             + ((g>>8)&0xff00)];
                        // Steigung addieren:
                        u+=dudx;
                        v+=dvdx;
                        g+=dgdx;
                }

                // Ziel-Pointer auf nächste Bitmap-Zeile stellen:
                dest    += PixelPerLine-8;
                // Ausführen der Y-Interpolation für Links und Rechts
                left.u  += dudy_left;
                left.v  += dvdy_left;
                left.g  += dgdy_left;
                right.u += dudy_right;
                right.v += dvdy_right;
                right.g += dgdy_right;
        }
}



void Render8x8Block (GridPointRGB   &a,
                     GridPointRGB   &b,
                     GridPointRGB   &c,
                     GridPointRGB   &d,
                     unsigned short *dest,
                     long           PixelPerLine)
// -------------------------------------------------------
// Ein Kästchen mit RGB-Koordinaten auf ein Bitmap Rendern
// -------------------------------------------------------
{
        signed long drdx, dgdx, dbdx;
        signed long drdy_left, dgdy_left, dbdy_left;
        signed long drdy_right, dgdy_right, dbdy_right;
        signed long rot, gruen, blau;
        GridPointRGB left, right;

        // Vorberechung der Steigung für die Y-Interpolation
        drdy_left = (b.r - a.r)/8;
        dgdy_left = (b.g - a.g)/8;
        dbdy_left = (b.b - a.b)/8;
        drdy_right= (d.r - c.r)/8;
        dgdy_right= (d.g - c.g)/8;
        dbdy_right= (d.b - c.b)/8;

        // Initialisieren der Y-Interpolations Variablen
        left  = a;
        right = c;

        // Schleife über die Höhe des Kästchens:
        for ( unsigned char y=0; y<8; y++)
        {
                // Vorberechung der Steigung für die X-Interpolation
                drdx = (right.r-left.r)/8;
                dgdx = (right.g-left.g)/8;
                dbdx = (right.b-left.b)/8;

                // Initialisieren der X-Interpolations Variablen
                rot   = left.r;
                gruen = left.g;
                blau  = left.b;

                // Schleife über die Breite des Kästchens.
                for ( unsigned char x=0; x<8; x++)
                {

                        *(dest++) = Rtab[(rot   >>16)&0xff] |
                                    Gtab[(gruen >>16)&0xff] |
                                    Btab[(blau  >>16)&0xff];
                        // Steigung addieren:
                        rot   +=drdx;
                        gruen +=dgdx;
                        blau  +=dbdx;
                }

                // Ziel-Pointer auf nächste Bitmap-Zeile stellen:
                dest    += PixelPerLine-8;
                // Ausführen der Y-Interpolation für Links und Rechts
                left.r  += drdy_left;
                left.g  += dgdy_left;
                left.b  += dbdy_left;
                right.r += drdy_right;
                right.g += dgdy_right;
                right.b += dbdy_right;
        }
}


           ///////////////////////////////////////////////////////////
           //                                                       //
           //  Routinen zum Zeichnen der Gitter                     //
           //                                                       //
           ///////////////////////////////////////////////////////////


void RenderScreen8x8 (GridPointUV    *gitter,
                      unsigned short *dest,
                      unsigned short *palette,
                      unsigned char  *texture,
                      unsigned int    BlocksX,
                      unsigned int    BlocksY,
                      unsigned int    PixelPerLine)
// -----------------------------------------------------
// Ein Gitter mit UV-Koordinaten in ein Bitmap Rendern
// ------------------------------------------------------
{
        GridPointUV *line     = gitter;
        GridPointUV *nextline = &gitter[BlocksX+1];
        for ( register int y=0; y<BlocksY; y++)
        {
                for ( register int x=0; x<BlocksX; x++)
                {

                        Render8x8Block (line[x+0], nextline[x+0],
                                        line[x+1], nextline[x+1],
                                        &dest[x*8], PixelPerLine, palette, texture);
                }
                dest     += PixelPerLine*8;
                line      = nextline;
                nextline += (BlocksX+1);
        }
}


void RenderScreen8x8 (GridPointUV     *gitter,
                      unsigned short  *dest,
                      unsigned short  *texture,
                      unsigned int    BlocksX,
                      unsigned int    BlocksY,
                      unsigned int    PixelPerLine)
// ------------------------------------------------------------
// Ein Gitter mit UV-Koordinaten in ein Bitmap Rendern (16 bit)
// ------------------------------------------------------------
{
        GridPointUV *line     = gitter;
        GridPointUV *nextline = &gitter[BlocksX+1];
        for ( register int y=0; y<BlocksY; y++)
        {
                for ( register int x=0; x<BlocksX; x++)
                {

                        Render8x8Block (line[x+0], nextline[x+0],
                                        line[x+1], nextline[x+1],
                                        &dest[x*8], PixelPerLine, texture);
                }
                dest     += PixelPerLine*8;
                line      = nextline;
                nextline += (BlocksX+1);
        }
}



void RenderScreen8x8 (GridPointUVG   *gitter,
                      unsigned short *dest,
                      unsigned short *palette,
                      unsigned char  *texture,
                      unsigned int    BlocksX,
                      unsigned int    BlocksY,
                      unsigned int    PixelPerLine)
// -----------------------------------------------------
// Ein Gitter mit UVG-Koordinaten in ein Bitmap Rendern
// ------------------------------------------------------
{
        GridPointUVG *line     = gitter;
        GridPointUVG *nextline = &gitter[BlocksX+1];
        for ( register int y=0; y<BlocksY; y++)
        {
                for ( register int x=0; x<BlocksX; x++)
                {
                        Render8x8Block (line[x+0], nextline[x+0],
                                        line[x+1], nextline[x+1],
                                        &dest[x*8], PixelPerLine, palette, texture);
                }
                dest     += PixelPerLine*8;
                line      = nextline;
                nextline += (BlocksX+1);
        }
}

void RenderScreen8x8 (GridPointRGB   *gitter,
                      unsigned short *dest,
                      unsigned int    BlocksX,
                      unsigned int    BlocksY,
                      unsigned int    PixelPerLine)
// -----------------------------------------------------
// Ein Gitter mit RGB-Koordinaten in ein Bitmap Rendern
// ------------------------------------------------------
{
        GridPointRGB *line     = gitter;
        GridPointRGB *nextline = &gitter[BlocksX+1];
        for ( register int y=0; y<BlocksY; y++)
        {
                for ( register int x=0; x<BlocksX; x++)
                {
                        Render8x8Block (line[x+0], nextline[x+0],
                                        line[x+1], nextline[x+1],
                                        &dest[x*8], PixelPerLine);
                }
                dest     += PixelPerLine*8;
                line      = nextline;
                nextline += (BlocksX+1);
        }
}


           ///////////////////////////////////////////////////////////
           //                                                       //
           //  Routinen zum Mischen von Gittern                     //
           //                                                       //
           ///////////////////////////////////////////////////////////


void mix_grids (GridPointUV *grid3,               // Ziel-Gitter
                GridPointUV *grid1,               // quelle 1
                GridPointUV *grid2,               // quelle 2
                int          werte,
                int          Mixwert)
// ---------------------------------------------------------------
// Mischen von zwei UV-Gittern (in 256 Schritten).
// ---------------------------------------------------------------
{
        // Mischwert auf Bereich prüfen, und gegebenenfalls korregieren
        if ( Mixwert < 0)   Mixwert = 0;
        if ( Mixwert > 255) Mixwert = 255;

        // Interpolation aller Stützwerte:
        for ( int i=0; i<werte; i++)
        {
                grid3[i].u = grid1[i].u + ((grid2[i].u - grid1[i].u) * Mixwert) / 256;
                grid3[i].v = grid1[i].v + ((grid2[i].v - grid1[i].v) * Mixwert) / 256;
        }
}


void mix_grids (GridPointUVG *grid3,               // Ziel-Gitter
                GridPointUVG *grid1,               // quelle 1
                GridPointUVG *grid2,               // quelle 2
                int           werte,               // Anzahl der Stützwerte
                int           Mixwert)
// ---------------------------------------------------------------
// Mischen von zwei UVG-Gittern (in 256 Schritten).
// ---------------------------------------------------------------
{
        // Mischwert auf Bereich prüfen, und gegebenenfalls korregieren
        if ( Mixwert < 0)   Mixwert = 0;
        if ( Mixwert > 255) Mixwert = 255;

        // Interpolation aller Stützwerte:
        for ( int i=0; i<werte; i++)
        {
                grid3[i].u = grid1[i].u + ((grid2[i].u - grid1[i].u) * Mixwert) / 256;
                grid3[i].v = grid1[i].v + ((grid2[i].v - grid1[i].v) * Mixwert) / 256;
                grid3[i].g = grid1[i].g + ((grid2[i].g - grid1[i].g) * Mixwert) / 256;
        }
}


void mix_grids (GridPointRGB *grid3,               // Ziel-Gitter
                GridPointRGB *grid1,               // quelle 1
                GridPointRGB *grid2,               // quelle 2
                int           werte,               // Anzahl der Stützwerte
                int           Mixwert)
// ---------------------------------------------------------------
// Mischen von zwei RGB-Gittern (in 256 Schritten).
// ---------------------------------------------------------------
{
        // Mischwert auf Bereich prüfen, und gegebenenfalls korregieren
        if ( Mixwert < 0)   Mixwert = 0;
        if ( Mixwert > 255) Mixwert = 255;

        // Interpolation aller Stützwerte:
        for ( int i=0; i<werte; i++)
        {
                grid3[i].r = grid1[i].r + ((grid2[i].r - grid1[i].r) * Mixwert) / 256;
                grid3[i].g = grid1[i].g + ((grid2[i].g - grid1[i].g) * Mixwert) / 256;
                grid3[i].b = grid1[i].b + ((grid2[i].b - grid1[i].b) * Mixwert) / 256;
        }
}

           ///////////////////////////////////////////////////////////
           //                                                       //
           //  Sonstige kleine Routinen                             //
           //                                                       //
           ///////////////////////////////////////////////////////////



unsigned short *MakeShadedPalette (bitmaptype *Bitmap)
// ---------------------------------------------------------------
// Erzeugen einer 256 Shading, 256 Farben 16-Bit Palette aus einem
// 256 Farben Bitmap.
// ---------------------------------------------------------------
{
        // erstmal kontrollieren, ob auch alles Ok ist:
        if ((!Bitmap) || (!Bitmap->cColors)) return NULL;

        // Speicher für die Palette allozieren
        unsigned short *Palette = new unsigned short[256*256];
        {
              // Lauf-Variable für die Berechung
              unsigned short *DieseFarbe = Palette;

              // Doppelte Schleife über Shading und den Farb-Index:
              for ( int Shading = 0; Shading < 256; Shading ++)
              for ( int Index   = 0; Index   < 256; Index   ++)
              {
                      // Shaden von Rot, Grün und Blau
                      int r = (Bitmap->cColors[ Index * 4 + 0] * Shading)/ 256;
                      int g = (Bitmap->cColors[ Index * 4 + 1] * Shading)/ 256;
                      int b = (Bitmap->cColors[ Index * 4 + 2] * Shading)/ 256;

                      // Zusammensetzen der 16-Bit Farbe
                     *(DieseFarbe++) = Rtab[ r ] | Gtab[ g ] | Btab[ b ];
              }
   }
   return Palette;
}





