/*

default efekt

return:
  0 - doslo k chybe
  1 - este nezacal
  2 - prebehol v poriadku
  3 - uz skoncil
*/

#include <iostream>
#include <cstdlib>
#include "api3ds.h"
#include "efekt.h"
#include "efekt_03.h"
#include "syncs.h"

extern int sync_id;

float drnd(float o_d,float d_o)
{
if (d_o==0) return o_d;
return o_d-d_o+0.02*(rand()%int(100*d_o));
}

void setinvtarcam(CameraTarget3DS& cmr,TUNEL& tun,float p,float angle,float r)
{
INFO3D or=tun.getinfo(p+18);   //origin
INFO3D tg=tun.getinfo(p+13); //target

float c=cos(angle)*r;
float s=sin(angle)*r;
or.pos=or.pos+c*or.v+s*or.n;

cmr.Origin((or.pos).x,(or.pos).y,(or.pos).z);
cmr.Target((tg.pos).x,(tg.pos).y,(tg.pos).z);
cmr.GL();
}


void settarcam(CameraTarget3DS& cmr,TUNEL& tun,float p,float angle,float r)
{
INFO3D or=tun.getinfo(p);   //origin
INFO3D tg=tun.getinfo(p+5); //target

float c=cos(angle)*r;
float s=sin(angle)*r;
or.pos=or.pos+c*or.v+s*or.n;

cmr.Origin((or.pos).x,(or.pos).y,(or.pos).z);
cmr.Target((tg.pos).x,(tg.pos).y,(tg.pos).z);
cmr.GL();
}

void setdesccam(CameraDescent3DS& cmr,TUNEL& tun,float p,float angle,float r)
{
INFO3D or=tun.getinfo(p);   //position
INFO3D tg=tun.getinfo(p+2); //orientation

float c=cos(angle)*r;
float s=sin(angle)*r;
(or.pos).x=(or.pos).x+c*(or.v).x+s*(or.n).x;
(or.pos).y=(or.pos).y+c*(or.v).y+s*(or.n).y;
(or.pos).z=(or.pos).z+c*(or.v).z+s*(or.n).z;

cmr.SetAll( or.pos, tg.n, tg.v, tg.u);
cmr.GL();
}

void setinvdesccam(CameraDescent3DS& cmr,TUNEL& tun,float p,float angle,float r)
{
INFO3D or=tun.getinfo(p+18); //position
INFO3D tg=tun.getinfo(p+16); //orientation

float c=cos(angle)*r;
float s=sin(angle)*r;
(or.pos).x=(or.pos).x+c*(or.v).x+s*(or.n).x;
(or.pos).y=(or.pos).y+c*(or.v).y+s*(or.n).y;
(or.pos).z=(or.pos).z+c*(or.v).z+s*(or.n).z;

cmr.SetAll( or.pos, -tg.n, -tg.v, -tg.u);
cmr.GL();
}


void setlight(OmniLight3DS *l, TUNEL& tun, float po, float angle, float r)
{
INFO3D or=tun.getinfo(po);

float c=cos(angle)*r;
float s=sin(angle)*r;
(or.pos)=(or.pos)+c*(or.v)+s*(or.n);
l->Position((or.pos).x,(or.pos).y,(or.pos).z);
}



int  efekt_03::init()
{
    cout << "Efekt 03 init ... ";
    start=TRUE;
    counter=ZACIATOK03*refresh;
//->init

    time=a1=a2=a3=d1=d2=d3=0.0;
    campos=1.0;
    nxt=2;
    wav_counter=0.0;
    wav_scale=0.0;

    fade=0.0;
    fadeset=FALSE;
    cnter=0;
    waved=TRUE;

    obal.reset(outen,270);
    obal.step=100;
    obal.rgb(cout_r,cout_g,cout_b);

    transp.reset(inen,80);
    transp.step=100;
    transp.rgb(cin_r,cin_g,cin_b);
    for (int i=0;i<TRLEN;i++)
      {
      transp.pridaj_obruc(1);
      obal.pridaj_obruc(1);
      }

    l1 = new OmniLight3DS;
    l2 = new OmniLight3DS;
    l1->LinearAttenuation(0.009);
    l2->LinearAttenuation(0.009);
    lgts+=l1;
    lgts+=l2;

    ca.HorizontalFOV(PI/3);
    ca.VerticalFOV(PI/4);
    ca.FarClipplane(vis);
    ca.NearClipplane(minvis);

    cam.HorizontalFOV(PI/3);
    cam.VerticalFOV(PI/4);
    cam.FarClipplane(vis);
    cam.NearClipplane(minvis);

//<-
    cout << "ok" << endl;
    return 1;
}

int  efekt_03::load()
{
    cout << "Loading efekt03 ... ";
// -> load

    char texin_name[30];
    char texout_name[30];

    FILE *stream;
    
    stream=fopen(CFGNAME03,"r");
    if (!stream) return 0;
    fscanf(stream,"camera speed         %f\n\n",&cam_speed);
    fscanf(stream,"inner texture        %s\n",texin_name);
    fscanf(stream,"inner tunel color    %f,%f,%f\n",&cin_r,&cin_g,&cin_b);
    fscanf(stream,"steny in-tunela      %i\n\n",&inen);    
    fscanf(stream,"outer texture        %s\n",texout_name);
    fscanf(stream,"outer tunel color    %f,%f,%f\n",&cout_r,&cout_g,&cout_b);
    fscanf(stream,"steny out-tunela     %i\n\n",&outen);    
    fscanf(stream,"visibility           %f\n",&vis);
    fscanf(stream,"minvisibility        %f\n",&minvis);
    fclose(stream);

    texin=texture_library->GetOrCreate(texin_name);
    texout=texture_library->GetOrCreate(texout_name);

   tunel_material1.Diffuse(cout_r,cout_g,cout_b);
   tunel_material1.Texture1(texout);
   tunel_material2.Diffuse(cin_r,cin_g,cin_b);
   tunel_material2.Texture1(texin);

// <-
    cout << "ok!"<<endl;
    return 1;
}

int  efekt_03::free()  //vrati 3 ako ok, 0 ak doslo k chybe
{
    end=true;
    cout << "Efekt 08 free ... ";
// -> free

// <-
    cout << "ok!" << endl;
    return 3;
}

int  efekt_03::update()
{
if (fade<1.0) fade+=0.01;
   	 else {fade=1.0;fadeset=true;}

id=Sync[GetSyncNum(float(counter)/float(refresh))].id;
// -> update
if (id>=SYNC_TUNEL_WAVING)
  {
  if(wav_scale<0.3) wav_scale+=0.01;
  wav_counter-=0.2;
  }


campos+=cam_speed;
if (id>=SYNC_TUNEL_3RD_CHANGE)
  {
  cnter++;
  if ((cnter==60)&&(transp.en>3))
    {
    transp.en--;
    cnter=0;
    }
  campos+=cam_speed;
  wav_scale=0.15;
  }
if (campos>=nxt)
  {
  transp.pridaj_obruc(1);
  obal.pridaj_obruc(1);
  nxt++;
  if (!time)
    {
    time=10+rand()%10;
    d1=drnd(0,0.1);
    d2=drnd(0,0.1);
    d3=drnd(0,0.1);
    }
  (transp.t).Rotate(a1,a2,a3);
  (obal.t).Rotate(a1,a2,a3);
  if (a1>d1+0.01) a1-=0.01;
  if (a2>d2+0.01) a2-=0.01;
  if (a3>d3+0.01) a3-=0.01;
  if (a1<d1-0.01) a1+=0.01;
  if (a2<d2-0.01) a2+=0.01;
  if (a3<d3-0.01) a3+=0.01;
  time--;
  }
// <-
return 1;
}

int efekt_03::go(double t)
{
if (t<ZACIATOK03) return 1;
if (end) return 3;
if (counter>=KONIEC03*refresh) return free();

if (!start) if (!init()) return 0;
int cur_frm=(int)(t*refresh);
if (cur_frm>KONIEC03*refresh) cur_frm=int(KONIEC03*refresh);
if (cur_frm>counter)
  while (counter<cur_frm)
    {
    counter++;
    if (counter<KONIEC03*refresh) update();
    }
if (counter>=KONIEC03*refresh) return free();
//tu sa kresli->

  if (!fadeset)
    {
      tunel_material1.Diffuse(cout_r*fade,cout_g*fade,cout_b*fade);
      tunel_material2.Diffuse(cin_r*fade,cin_g*fade,cin_b*fade);
    }
  if ((id==SYNC_TUNEL_WAVING)||(id==SYNC_TUNEL_2ND_CHANGE))
    {
    for (int i=0;i<TRLEN;i++)
      {
      float a=sin(  (i*4*PI/TRLEN)  +wav_counter*0.6);
      float b=cos(  (i*5*PI/TRLEN)  +wav_counter*0.7);
      (transp.data)->polomerx[i]=1.0+ wav_scale*a;
      (transp.data)->polomery[i]=1.0+ wav_scale*b;
      }
    transp.rebuild();
    }

  if (waved&&(id==SYNC_TUNEL_3RD_CHANGE))
    {
    for (int i=0;i<TRLEN;i++)
      {
      (transp.data)->polomerx[i]=1.0;
      (transp.data)->polomerx[i]=1.0;
      }
    transp.rebuild();
    waved=false;
    }


   if ((id==SYNC_TUNEL_WAVING)||(id==SYNC_TUNEL_3RD_CHANGE))
         {

         tunel_material1.Diffuse(1.0F,1.0F,1.0F);
         tunel_material2.Diffuse(1.9F,1.9F,0.9F);

         setinvtarcam(ca,transp,campos,0, 0);
//   	 glFrontFace(GL_CW);
//         setinvdesccam(cam,transp,campos,0, 0);
         }
      else
         {
         settarcam(ca,transp,campos,0, 0);
//         setdesccam(cam,transp,campos,0, 0);
         if (fadeset)
           {
           tunel_material1.Diffuse( cout_r, cout_g, cout_b);
           tunel_material2.Diffuse( cin_r, cin_g, cin_b);
           }

         }

   setlight(l1,transp,campos+3 , 0,40);
   setlight(l2,transp,campos+10, 0, 0);
   l1->Diffuse(0.55F, 0.55F, 0.30F);
   l2->Diffuse(0.8F, 0.3F, 0.0F);


   glEnable(GL_LIGHTING);
   lgts.GL();

   tunel_material1.GL();
   glEnable(GL_CULL_FACE);
   glDepthMask(GL_ONE);  
   glDisable(GL_BLEND);
   obal.render();

   tunel_material2.GL();
   glDisable(GL_CULL_FACE);
   glEnable(GL_BLEND);
   glBlendFunc(GL_ONE,GL_ONE);
   glDepthMask(GL_ZERO);

   transp.render();

   glDepthMask(GL_ONE);  
   glDisable(GL_BLEND);


//   glFrontFace(GL_CCW);
//<-
return 2;
}