///////////////////////////////////////////////////////////
//                                                       //
//  PC MAGAZIN - Demo Projekt                            //
//                                                       //
//  Grid-Generator Routinen für einige Standard          //
//  Effekte (teils mit, teils ohne Shading)              //
//                                                       //
///////////////////////////////////////////////////////////

#include "demo.h"
#include "grid.h"


#ifndef M_PI
#define M_PI 3.1415
#endif

void make_rotzoomer (float time, GridPointUV *grid)
// -----------------------------------------------------------
// Berechnet ein UV-Gitter mit einem Rot-Zoomer Effekt
// -----------------------------------------------------------
{
        float zoom = (float)(300 * sin(time) + 364);
        float sint = (float)(sin(time)*zoom);
        float cost = (float)(cos(time)*zoom);
        long  BlocksX = SCREEN_X/8;
        long  BlocksY = SCREEN_Y/8;

        GridPointUV *data = grid;

        for (int y=0; y<=BlocksY; y++)
        {
               for (int x=0; x<=BlocksX; x++)
               {
                       float xtex = (float)(x-(SCREEN_X/16))*2048.0f;
                       float ytex = (float)(y-(SCREEN_Y/16))*2048.0f;
                       data->u = (long)(cost*xtex - sint * ytex + (128 << 8));
                       data->v = (long)(cost*ytex + sint * xtex + (128 << 8));
                       data++;
               }
    }
}

void make_feedback (float time, GridPointUV *grid, int BlocksX, int BlocksY)
// ------------------------------------------------------------------------------------
// Berechnet ein UV-Gitter mit einem Rot-Zoomer Effekt (einstellbare Größe für Feedback)
// ------------------------------------------------------------------------------------
{
        float zoom = 256.0 +140.0*sin(time*2.0);
        float sint = sin(sin(time))*zoom;
        float cost = cos(sin(time))*zoom;

        float mitte_x = (128.0 + 10.0 * sin(time*0.1))*65536.0;
        float mitte_y = (128.0 + 10.0 * cos(time*0.1))*65536.0;

        GridPointUV *data = grid;

        for (int y=0; y<=BlocksY; y++)
        {
               for (int x=0; x<=BlocksX; x++)
               {
                       float xtex = ((float)x-((float)BlocksX/2.0))*2048.0;
                       float ytex = ((float)y-((float)BlocksY/2.0))*2048.0;
                       data->u = cost*xtex - sint * ytex  - mitte_x;
                       data->v = cost*ytex + sint * xtex  - mitte_y;
                       data++;
               }
    }
}

void make_stretcher (GridPointUV *grid)
// ------------------------------------------------
// strecht ein 256x256 bild auf screen_x * screen_y
// ------------------------------------------------
{
        long  BlocksX = SCREEN_X/8;
        long  BlocksY = SCREEN_Y/8;

        GridPointUV *data = grid;

        for (int y=0; y<=BlocksY; y++)
        {
               for (int x=0; x<=BlocksX; x++)
               {
                       data->u = (65536 * x * 256)/BlocksX;
                       data->v = (65536 * y * 256)/BlocksY;
                       data++;
               }
    }
}


void make_wobble (float time, GridPointUV *grid)
// -----------------------------------------------------------
// Berechnet ein UV-Gitter mit einem Sinus-Wobbler Effekt
// -----------------------------------------------------------
{
        long  BlocksX = SCREEN_X/8;
        long  BlocksY = SCREEN_Y/8;

        GridPointUV *data = grid;

        float so1=sin(time*1*0.3)*20+sin(time*1.23453264)*8;
        float so2=sin(time*0.5232341)*20;

        for (int y=0; y<=BlocksY; y++)
        {
                for (int x=0; x<=BlocksX; x++)
                {
                        float i= x*3;
                        float j= y*3;
                        double ip=6*M_PI/256*i;
                        double jp=6*M_PI/256*j;
                        data->u=2*65536*(7+i+sin(so1+jp*2)*8);
                        data->v=2*65536*(20+j+sin(so1+jp)*6+sin(so2+2*ip)*3+(j-128)*(j-128)*(j-128)*0.2/65536);
                        data++;
                }
       }
}

void make_projecteffect (float time, GridPointUV *grid)
// -----------------------------------------------------------
// Berechnet ein UV-Gitter mit einem Twirl-Projektions Effekt
// -----------------------------------------------------------
{
        long  BlocksX = SCREEN_X/8;
        long  BlocksY = SCREEN_Y/8;

        float spiral_faktor = 0.4 * sin(time*2.0);
        float tiefen_faktor = 1.0 + sin(time*1.3);

        GridPointUV *data = grid;

        for (int y=0; y<=BlocksY; y++)
        {
                for (int x=0; x<=BlocksX; x++)
                {
                        float xtex = (x-(SCREEN_X/16))*0.5;
                        float ytex = (y-(SCREEN_Y/16))*0.5;
                        float z    = sqrt(xtex*xtex+ytex*ytex)*tiefen_faktor + 1.4;
                        float sint = sin(spiral_faktor*z+time*1.0);
                        float cost = cos(spiral_faktor*z+time*1.0);
                        data->u    = 100*65536*(sint * xtex - cost * ytex) / z + (128<<16);
                        data->v    = 100*65536*(cost * xtex + sint * ytex) / z + (128<<16);
                        data++;
                 }
        }
}


void make_projecteffect_shaded (float time, GridPointUVG *grid)
// -----------------------------------------------------------
// Berechnet ein UVG-Gitter mit einem Twirl-Projektions Effekt.
// Diese Variante ist mit Shading!
// -----------------------------------------------------------
{
       long  BlocksX = SCREEN_X/8;
       long  BlocksY = SCREEN_Y/8;

       float spiral_faktor = 0.4 * sin(time*2.0);
       float tiefen_faktor = 1.0 + sin(time*1.3);

       GridPointUVG *data = grid;

       for (int y=0; y<=BlocksY; y++)
       {
               for (int x=0; x<=BlocksX; x++)
               {
                     float xtex    = (x-(SCREEN_X/16))*0.5;
                     float ytex    = (y-(SCREEN_Y/16))*0.5;
                     float abstand = sqrt(xtex*xtex+ytex*ytex);
                     float z       = abstand *tiefen_faktor + 1.4;
                     float sint    = sin(spiral_faktor*z+time*1.0);
                     float cost    = cos(spiral_faktor*z+time*1.0);
                     data->u       = 100*65536*(sint * xtex - cost * ytex) / z + (128<<16);
                     data->v       = 100*65536*(cost * xtex + sint * ytex) / z + (128<<16);
                     data->g       = __min ((abstand)*30*65536, 0xffffff);
                     data++;
               }
      }
}


