#include "MadMap.h"


void MadMap::XMLRead(vcg::Xml &xml)
{
char  buffer[200]; 
    int i,a;
    const char *s;
    assert(xml.id == "MadMap");
    //Dimensione della Mappa
    Dim.X = (int)atoi(xml["SizeX"].c_str());
    Dim.Z = (int)atoi(xml["SizeZ"].c_str());
    numtex = (int)atoi(xml["numtex"].c_str());

    for (i=0;i<numtex;i++)
    {
        sprintf(buffer,"Tex_%d",i);
        s=xml[buffer].c_str();
        a=strlen(s);
        strncpy(Tex[i],s,a);
        Tex[i][a]='\0';

    }
    sprintf(buffer,"Enemys_Tex");
    TexEnemy=(int) atoi(xml[buffer].c_str());

    for(i=0;i<Dim.X;++i)
        {
            for(int j=0;j<Dim.Z;++j)
            {   
                //Costruisce la MadTile nella posizione (i,j) nella mappa
                
                sprintf(buffer,"NO_%d_%d",i,j);
                Map[i][j].NE = (double) atof(xml[buffer].c_str());
                sprintf(buffer,"NE_%d_%d",i,j);
                Map[i][j].NW = (double) atof(xml[buffer].c_str());
                sprintf(buffer,"SO_%d_%d",i,j);
                Map[i][j].SE = (double) atof(xml[buffer].c_str());
                sprintf(buffer,"SE_%d_%d",i,j);
                Map[i][j].SW = (double) atof(xml[buffer].c_str());
                sprintf(buffer,"C_%d_%d",i,j);
                Map[i][j].C  = (double) atof(xml[buffer].c_str());
                
                sprintf(buffer,"typet_%d_%d",i,j);
                Map[i][j].typet = (int) atoi(xml[buffer].c_str());
                sprintf(buffer,"typew_%d_%d",i,j);
                Map[i][j].typew = (int) atoi(xml[buffer].c_str());
                sprintf(buffer,"goal_%d_%d",i,j);
                Map[i][j].goal = (int) atoi(xml[buffer].c_str());
                sprintf(buffer,"grav_%d_%d",i,j);
                Map[i][j].grav = (double) atof(xml[buffer].c_str());
                sprintf(buffer,"artr_%d_%d",i,j);
                Map[i][j].attr  = (double) atof(xml[buffer].c_str());
        
            }   
        }
    int x,z;
    //Start
    x =(int) atoi(xml["X_S"].c_str());
    z =(int) atoi(xml["Z_S"].c_str());
    Start.first.X=x;
    Start.first.Z=z;
    Start.last.X=x;
    Start.last.Z=z;
   
    //Goal


    for (i=0;i<MAXENEMY;i++) {
    sprintf(buffer,"Enemy_%d_X",i);
    x =(int) atoi(xml[buffer].c_str());
    sprintf(buffer,"Enemy_%d_Z",i);
    z =(int) atoi(xml[buffer].c_str());
    Enemys[i].first.X=x; Enemys[i].first.Z=z;
    Enemys[i].last.X=x; Enemys[i].last.Z=z;

    }


}



MadMap::MadMap(int SizeX,int SizeZ)
{  

    //Lo Start non è presenta nella Mappa
    Start.first.X=NOMAP;
    Start.first.Z=NOMAP;
    Start.last.X=NOMAP;
    Start.last.Z=NOMAP;
    //Dimenzione della Mappa
    Dim.X = SizeX;
    Dim.Z = SizeZ;
    //Mappa Valida
    Meaningful=true;
    strncpy(Tex[0],"tile.jpg\0",9);
    strncpy(Tex[1],"wall.jpg\0",9);
    strncpy(Tex[2],"enemy.jpg\0",16);

    TexEnemy=2;
    for (int i=0;i<Dim.Z;i++)
    {

       for (int j=0;j<Dim.X;j++)
       {
            //Tile nella posizione (i,j) altezza DEFAULT!
            Map[i][j].C = DEFAULT_Y;
            Map[i][j].NE = DEFAULT_Y;
            Map[i][j].NW = DEFAULT_Y;
            Map[i][j].SE = DEFAULT_Y;
            Map[i][j].SW = DEFAULT_Y;
            Map[i][j].typet=TILE;
            Map[i][j].typew=WALL;
            Map[i][j].goal=0;
            Map[i][j].grav=-160;
            Map[i][j].attr=7;
       }
        

    } 
    numtex=3;
    CalcNorm();

}
void MadMap::CalcNorm()
{
   //con area colorata

    
    Point3f nw;
    Point3f ne;
    Point3f sw;
    Point3f se;
    Point3f c;
    c[XX]=0;
    c[ZZ]=0;
    nw[XX]=-1;
    nw[ZZ]=-1;
    ne[XX]=1;
    ne[ZZ]=-1;
    sw[XX]=-1;
    sw[ZZ]=1;
    se[XX]=1;
    se[ZZ]=1;
for (int i=0;i<Dim.Z;i++)
    for (int j=0;j<Dim.X;j++)
    {   
        c[YY]=Map[j][i].C;
        nw[YY]=Map[j][i].NW;
        ne[YY]=Map[j][i].NE;
        sw[YY]=Map[j][i].SW;
        se[YY]=Map[j][i].SE;

 
        Nl[j][i][STH]=Normal(c,sw,se); 
        Nl[j][i][EST]=Normal(ne,c,se); 
    Nl[j][i][NTH]=-Normal(ne,c,nw); 

        Nl[j][i][WST]=-Normal(nw,c,sw); 
    
    }   
    



}
MadMap::MadMap(){Meaningful=false;}

void MadMap::Draw (int option)
{
glMatrixMode(GL_MODELVIEW);

        
                
    for (int i=0;i<Dim.Z;i++) 
                for (int j=0;j<Dim.X;j++)
                {DrawTile(j,i,option);
                    if ((i+1)<Dim.Z)
                    {if ((Map[j][i].SW!=Map[j][i+1].NW)||
                            ((Map[j][i].SE!=Map[j][i+1].NE)))   
                    
                            DrawWall(j,i,NORTH,option);}
                        else DrawWall(j,i,NORTH,option);
                    if ((i-1)>=0) {
                        if ((Map[j][i].NE!=Map[j][i-1].SE)||
                            (Map[j][i].NW!=Map[j][i-1].SW))
                    
                            DrawWall(j,i,SOUTH,option);}
                    else DrawWall(j,i,SOUTH,option);
                    if ((j-1)>=0) {
                        if ((Map[j][i].NW!=Map[j-1][i].NE)||
                            (Map[j][i].SW!=Map[j-1][i].SE)) 
                            DrawWall(j,i,EAST,option);}
                    else DrawWall(j,i,EAST,option);
                    if ((j+1)<Dim.X){
                        if ((Map[j][i].SE!=Map[j+1][i].SW)||
                            (Map[j][i].NE!=Map[j+1][i].NW))
                            DrawWall(j,i,WEST,option);}
                    else DrawWall(j,i,WEST,option);
                }

}


void MadMap::XMLWrite(FILE *fp)
{
    fprintf(fp,"<MadMap\n");

    //Dimensione
    fprintf(fp," SizeX=\"%d\" \n", Dim.X);
    fprintf(fp," SizeZ=\"%d\" \n", Dim.Z);
    
    int i,j;
    fprintf(fp," numtex=\"%d\" \n",numtex);
    for (i=0;i<numtex;i++)
    {
        fprintf(fp," Tex_%d=\"%s\"\n",i,Tex[i]);
    }
    fprintf(fp," Enemys_Tex=\"%i\" \n",TexEnemy);


    for(i=0;i<Dim.X;++i) {
        for(j=0;j<Dim.Z;++j)
        {
            //Tile
            fprintf(fp," NO_%d_%d =\"%f\"\n",i,j, Map[i][j].NE);
            fprintf(fp," NE_%d_%d =\"%f\"\n",i,j, Map[i][j].NW);
            fprintf(fp," SO_%d_%d =\"%f\" \n",i,j, Map[i][j].SE);
            fprintf(fp," SE_%d_%d =\"%f\" \n",i,j, Map[i][j].SW);
            fprintf(fp," C_%d_%d =\"%f\" \n",i,j, Map[i][j].C);
            fprintf(fp," typet_%d_%d =\"%d\" \n",i,j, Map[i][j].typet);
            fprintf(fp," typew_%d_%d =\"%d\" \n",i,j, Map[i][j].typew);
            fprintf(fp," goal_%d_%d =\"%d\" \n",i,j, Map[i][j].goal);
            fprintf(fp," grav_%d_%d =\"%f\" \n",i,j, Map[i][j].grav);
            fprintf(fp," artr_%d_%d =\"%f\" \n",i,j, Map[i][j].attr);   
        }
    }
    //Start
    fprintf(fp," X_S=\"%d\"\n", Start.last.X);
    fprintf(fp," Z_S=\"%d\"\n", Start.last.Z);
    
    for (i=0;i<MAXENEMY;i++) {
    fprintf(fp," Enemy_%d_X=\"%d\" \n",i,Enemys[i].first.X);
    fprintf(fp," Enemy_%d_Z=\"%d\" \n",i,Enemys[i].first.Z);
    
    }
    

    fprintf(fp,"/>\n");
}

int MadMap::PickElement(int x, int y, int option)
{
    long hits;  
    static unsigned int selectBuf[16384];
    glSelectBuffer(16384, selectBuf);
    glRenderMode(GL_SELECT);
    glInitNames();

  /* Because LoadName() won't work with no names on the stack */
    glPushName(-1);
    double mp[16];
    
    int viewport[4];
    glGetIntegerv(GL_VIEWPORT,viewport);
    glMatrixMode(GL_PROJECTION);
    glGetDoublev(GL_PROJECTION_MATRIX ,mp);
    glPushMatrix();
    glLoadIdentity();
    gluPickMatrix(x, viewport[3]-y, 7, 7, viewport);

    glMultMatrixd(mp);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();

    Draw(option);      //disegno della mappa
 
    glPopMatrix();
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    hits = glRenderMode(GL_RENDER);
    if (hits <= 0)     return -1;
    vector< pair<double,unsigned int> > H;
    for(int ii=0;ii<hits;ii++)
        H.push_back( make_pair(selectBuf[ii*4+1]/4294967295.0,selectBuf[ii*4+3]));
     
    sort(H.begin(),H.end());



   return H[0].second;
}

void MadMap::upTile(int X,int Z,double Y)
{
    Map[X][Z].C=Map[X][Z].C+Y;
    Map[X][Z].NW=Map[X][Z].NW+Y;
    Map[X][Z].SE=Map[X][Z].SE+Y;
    Map[X][Z].SW=Map[X][Z].SW+Y;
    Map[X][Z].NE=Map[X][Z].NE+Y;
}

void MadMap::zeroTile(int X,int Z,double k)
{
    Map[X][Z].C=0+k;
    Map[X][Z].NW=0+k;
    Map[X][Z].SE=0+k;
    Map[X][Z].SW=0+k;
    Map[X][Z].NE=0+k;
}

double MadMap::getY(double X, double Z)
{   
    double hB,hC,dB,dC,ret;
    if ((X<0)||(Z<0)) return -200;
    int iX=(int)X; //parte intera X
    int iZ=(int)Z; //parte intera Z
    
    double dX=X -iX; //parte decimale X
    double dZ=Z-iZ; //parte decimale Z

    if ((iX>=0) && (iZ>=0) && (iX<Dim.X) && ( iZ<Dim.Z))
                    //se le coordinate sono nella mappa
    {   
        double hA= Map[iX][iZ].C; //altezza A = altezza Centro Tile
        double  dA=sqrt(pow((dX-0.5),2)+pow((dZ-0.5),2)); 
                //Distanza A = Distanza punto (X,Z) dal Centro Tile
                     /*     
               SE
            +--+    quale è il punto B?
            |\ |    
            | \|      
            +--+ 
           NW       */
        if (dZ>(1-dX)){
            hB=Map[iX][iZ].SE;  //altezza B = altezza Nord-Ovest della tile
            dB=sqrt(pow((1-dX),2)+pow((1-dZ),2));
            //Distanza B= distanza punto(X,Z) dal punto + a Nord-Ovest Tile
            }
        else {
            hB=Map[iX][iZ].NW;  //altezza B = altezza Sud Est della tile
            dB=sqrt(pow((dX),2)+pow((dZ),2));
            //Distanza B= distanza punto(X,Z) dal punto + a Sud-Est Tile
            }
             /*     
           SW   
            +--+     quale è il punto C?
            | /|    
            |/ |      
            +--+ 
               NE       */
    if (dZ>dX){  hC=Map[iX][iZ].SW; //altezza C = altezza Nord-Est della tile
                    dC=sqrt(pow((dX),2)+pow((1-dZ),2));
                //Distanza C= distanza punto(X,Z) dal punto + a Nord-Est Tile
                }
    else {hC=Map[iX][iZ].NE;    //altezza C = altezza Sud-Ovest della tile
        dC=sqrt(pow((1-dX),2)+pow((dZ),2));
                //Distanza C= distanza punto(X,Z) dal punto + a Sud-Ovest Tile
                }

    
    double maxdA=sqrt(pow(0.5,2)+pow(0.5,2)); 
            //distanza massima di un punto (dX,dZ) dal centro della tile


     ret= hA*(1-dA/maxdA)+ (hB*(1-dB)+hC*(dB))*(dA/maxdA);
     //calcolo dell'altezza del punto (dX,dZ) in base alle altezze conosciute della tile


    }
    else ret=-200;
     return ret;
}
void MadMap::getTriangle(double X, double Z,MarbleTriangle *currentTriangle )
{
    Point3f p1,p2,p3;

    int iX=(int)X; //parte intera X
    int iZ=(int)Z; //parte intera Z
    int ch=0;
    double dX=X -iX; //parte decimale X
    double dZ=Z-iZ; //parte decimale Z

    if ((iX>=0) && (iZ>=0) && (iX<Dim.X) && ( iZ<Dim.Z))
                    //se le coordinate sono nella mappa
    {   
        p1= vcg::Point3f(iX+0.5,Map[iX][iZ].C,iZ+0.5);
        
                     /*     
               SE
            +--+    quale è il punto B?
            |\ |    
            | \|      
            +--+ 
           NW       */
        if (dZ>=(1-dX)) {
                    p2= vcg::Point3f(iX+1,Map[iX][iZ].SE,iZ+1);
                    ch=SOUTH+EAST;
        }
        else {
                p2= vcg::Point3f(iX,Map[iX][iZ].NW,iZ);
                ch=NORTH+WEST;
        }

             /*     
           SW   
            +--+     quale è il punto C?
            | /|    
            |/ |      
            +--+ 
               NE       */
        if (dZ>=dX) {
                p3= vcg::Point3f(iX,Map[iX][iZ].SW,iZ+1);
                ch=(ch+SOUTH+WEST)/2;
        }
        else {
            p3= vcg::Point3f(iX+1,Map[iX][iZ].NE,iZ);
                ch=(ch+NORTH+EAST)/2;
            }
        
    switch(ch)
    {
        case NORTH: currentTriangle->a=p3; 
                    currentTriangle->b=p2;
                    currentTriangle->c=p1;
                    break;
        case SOUTH: currentTriangle->a=p3;
                    currentTriangle->b=p2;
                    currentTriangle->c=p1;
                    break;
        case EAST:  currentTriangle->a=p1; 
                    currentTriangle->b=p2;
                    currentTriangle->c=p3;
                    break;
        case WEST:  currentTriangle->a=p1; 
                    currentTriangle->b=p2;
                    currentTriangle->c=p3;
                    break;
        default:break;
    }
    }
                
return ;
} 
void MadMap::setY(double X,double Z, double Y)
{
    double max,min;
    int iX=(int)X;
    int iZ=(int)Z;
int ch,ch1,ch2;
    double dX= X -iX;


    double dZ=Z-iZ;
        if ((iX>=0) && (iZ>=0) && (iX<Dim.X) && ( iZ<Dim.Z)) 
    {
    double hA= Map[iX][iZ].C;

    double hB,hC,dB,dC;
    
    double  dA=sqrt(pow((dX-0.5),2)+pow((dZ-0.5),2));
    
    if ((dZ>(1-dX))){ hB=Map[iX][iZ].SE; ch1=SOUTH+EAST;
            dB=sqrt(pow((1-dX),2)+pow((1-dZ),2));}
    else
    
    {   hB=Map[iX][iZ].NW; ch1=NORTH+WEST;
            dB=sqrt(pow((dX),2)+pow((dZ),2)); }

    if (dZ>dX){  hC=Map[iX][iZ].SW; ch2=SOUTH+WEST;
                    dC=sqrt(pow((dX),2)+pow((1-dZ),2));
                }
    else {hC=Map[iX][iZ].NE;
        ch2=NORTH+EAST;
        dC=sqrt(pow((1-dX),2)+pow((dZ),2));
            }


if ((dA<dB) & (dA<dC)) Map[iX][iZ].C=Y;
else {
    if (dB<dC) ch=ch1;
        else   ch=ch2;

    switch(ch) {
        case NORTH+EAST: Map[iX][iZ].NE=Y;break;
        case SOUTH+WEST: Map[iX][iZ].SW=Y;break;
        case NORTH+WEST: Map[iX][iZ].NW=Y;break;
        case SOUTH+EAST: Map[iX][iZ].SE=Y;break;
        default: break;}

    if (Map[iX][iZ].NE>Map[iX][iZ].SW) 
        {max=Map[iX][iZ].NE; min= Map[iX][iZ].SW;}
    else {min=Map[iX][iZ].NE; max= Map[iX][iZ].SW;}
    if (Map[iX][iZ].SE>=max) max=Map[iX][iZ].SE;
    if (Map[iX][iZ].SE<=min) min=Map[iX][iZ].SE;
    if (Map[iX][iZ].NW>=max) max=Map[iX][iZ].NW;
    if (Map[iX][iZ].NW<=min) min=Map[iX][iZ].NW;
    //Map[iX][iZ].C= (Map[iX][iZ].NW+Map[iX][iZ].SE+
    //                      Map[iX][iZ].NE+Map[iX][iZ].SW)/4;
    Map[iX][iZ].C = (max+min)/2;
    
    }
}
}




void MadMap::InitTexture(void)
{
    
    ilInit();
    iluInit();
    ilutRenderer(ILUT_OPENGL);
    for (int i=0;i<numtex;i++)
    {
        ti[i]=ilutGLLoadImage(Tex[i]);
        printf("Texture %d:%s\n",i,Tex[i]);
        ilutGLBuildMipmaps();
    }

Start.InitTexture("start.jpg");
Wall.InitTexture("wall.jpg");

}

void MadMap::setColoredArea(coord a, coord b)
{
 Colored.first.X=a.X;
 Colored.first.Z=a.Z;
 Colored.last.X=b.X;
 Colored.last.Z=b.Z;
}

bool MadMap::isColored(double x, double z)
{ bool ret=FALSE;
if ((x >= Colored.first.X) && (x <= Colored.last.X) &&
    (z >= Colored.first.Z) && ( z<= Colored.last.Z) )
    ret = TRUE;
 return ret;
}


void MadMap::copy ( MadMap *map_copy , coord first , coord last)

  {
      int x1,z1;
        int k=Map[first.X][first.Z].C;
       for (x1 = first.X ; x1 <= last.X; x1++)
           for ( z1 = first.Z ; z1 <= last.Z ; z1++)
           {
                 map_copy->Map[x1 -first.X ][z1 -first.Z].C = Map[x1][z1].C-k;
                 map_copy->Map[x1 -first.X ][z1 -first.Z].NE = Map[x1][z1].NE-k;
                 map_copy->Map[x1 -first.X ][z1 -first.Z].NW = Map[x1][z1].NW-k;
                 map_copy->Map[x1 -first.X ][z1 -first.Z].SE = Map[x1][z1].SE-k;
                 map_copy->Map[x1 -first.X ][z1 -first.Z].SW = Map[x1][z1].SW-k;

           }
      map_copy->Dim.X=(last.X-first.X)+1;
      map_copy->Dim.Z=(last.Z-first.Z)+1;
      map_copy->Meaningful=true;

  }

   void MadMap::copy ( MadMap *map_copy)

  { coord F;
    coord L;
    F.X=0;
    F.Z=0;
    L.X=Dim.X-1;
    L.Z=Dim.Z-1;
    copy(map_copy,F,L);
    Meaningful=false;

  }


void MadMap::paste ( MadMap *map_paste , coord first , coord last )
    {
     
     int x1,x2,z1,z2;
    int k=Map[first.X][first.Z].C;
     if ((map_paste->Dim.X-1) > ( (Dim.X-1) -first.X) )
         x1=Dim.X ;
     else x1=(first.X + map_paste->Dim.X)-1;

     if (map_paste->Dim.Z-1 > ( (Dim.Z-1) -first.Z) )
         x2=Dim.Z ;
     else x2=(first.Z + map_paste->Dim.Z)-1 ;


     for (z1 = first.X ; z1 <= x1; z1++)
           for ( z2 = first.Z ; z2 <= x2 ; z2++)
           {

            Map[z1][z2].C = map_paste->Map[z1-first.X][z2-first.Z].C +k;
            Map[z1][z2].NE = map_paste->Map[z1-first.X][z2-first.Z].NE +k;
            Map[z1][z2].NW = map_paste->Map[z1-first.X][z2-first.Z].NW +k ;
            Map[z1][z2].SE = map_paste->Map[z1-first.X][z2-first.Z].SE +k;
            Map[z1][z2].SW = map_paste->Map[z1-first.X][z2-first.Z].SW +k;
           
           }

  Colored.last.X = x1;
  Colored.last.Z = x2;


    }


    void MadMap::merge ( MadMap *map_paste , coord first , coord last )
    {
     
     int x1,x2,z1,z2;
    int k=Map[first.X][first.Z].C;
     if ((map_paste->Dim.X-1) > ( (Dim.X-1) -first.X) )
         x1=Dim.X ;
     else x1=(first.X + map_paste->Dim.X)-1;

     if (map_paste->Dim.Z-1 > ( (Dim.Z-1) -first.Z) )
         x2=Dim.Z ;
     else x2=(first.Z + map_paste->Dim.Z)-1 ;


     for (z1 = first.X ; z1 <= x1; z1++)
           for ( z2 = first.Z ; z2 <= x2 ; z2++)
           {

            Map[z1][z2].C = map_paste->Map[z1-first.X][z2-first.Z].C +Map[z1][z2].C;
            Map[z1][z2].SE = map_paste->Map[z1-first.X][z2-first.Z].SE +Map[z1][z2].SE;
            Map[z1][z2].SW = map_paste->Map[z1-first.X][z2-first.Z].SW +Map[z1][z2].SW ;
            Map[z1][z2].NE = map_paste->Map[z1-first.X][z2-first.Z].NE +Map[z1][z2].NE;
            Map[z1][z2].NW = map_paste->Map[z1-first.X][z2-first.Z].NW +Map[z1][z2].NW;
           
           }



    
    }

    void MadMap::DrawTile(int x,int z,int option)
{ double a=0;
    glLoadName(z*100+x);
if (Map[x][z].goal==1) a=0.2;
else a=0;
if (!Colored.isArea(x,z)) glColor3f(1-a,1-a,1-a);
else glColor3f(0.4-a,0.5-a,0.7-a);

switch (option)
{
    case WIREFRAME:  //Caso "Fildiferro"
        glDisable(GL_TEXTURE_2D);
          //nome per la pick!
                 glBegin(GL_LINE_LOOP); //disegno dei 4 triangoli della tile

                     glVertex3f( x+1 ,Map[x][z].SE,z+1);                       //in wireframe
                     glVertex3f( x+1 ,Map[x][z].NE,z);
                     glVertex3f( x+0.5 ,Map[x][z].C,z+0.5);
                 glEnd();
                
                
                 glBegin(GL_LINE_LOOP);
                     glVertex3f( x+1 ,Map[x][z].SE,z+1);
                     glVertex3f( x ,Map[x][z].SW,z+1);
                     glVertex3f( x+0.5 ,Map[x][z].C,z+0.5);
                 glEnd();
        
                
                 glBegin(GL_LINE_LOOP);
                     glVertex3f( x ,Map[x][z].SW,z+1);
                  glVertex3f( x ,Map[x][z].NW,z);
                     glVertex3f( x+0.5 ,Map[x][z].C,z+0.5);
                 glEnd();
                
                 
                 glBegin(GL_LINE_LOOP);
                     glVertex3f( x+1 ,Map[x][z].NE,z);
                     glVertex3f( x ,Map[x][z].NW,z);
                     glVertex3f( x+0.5 ,Map[x][z].C,z+0.5);
                 glEnd();
                break;
case SOLID:
        glDisable(GL_TEXTURE_2D);
                if(Colored.isArea(x,z)) glColor3f(0,0,1); //Blu
                else glColor3f(1,1,1);  
        glBegin(GL_TRIANGLES);                //disegno dei triangli pieni delle tile
            glNormal(Nl[x][z][STH]);
            glVertex3f( x ,Map[x][z].SW,z+1);
            glVertex3f( x+0.5,Map[x][z].C,z+0.5);     //con area colorata       
            glVertex3f( x+1 ,Map[x][z].SE,z+1);
          
    
    glNormal(Nl[x][z][WST]);        
 
           glVertex3f( x,Map[x][z].NW,z);   
           glVertex3f( x+0.5,Map[x][z].C,z+0.5); 
           glVertex3f( x ,Map[x][z].SW,z+1);




    glNormal(Nl[x][z][EST]);
   glVertex3f( x+1 ,Map[x][z].NE,z);
glVertex3f( x+0.5,Map[x][z].C,z+0.5);  
          glVertex3f( x+1 ,Map[x][z].SE,z+1);


    glNormal(Nl[x][z][NTH]);
    glVertex3f( x+1 ,Map[x][z].NE,z);
  glVertex3f( x+0.5,Map[x][z].C,z+0.5);  
           glVertex3f( x,Map[x][z].NW,z);   


      glEnd(); 

break;
case TEXTURED:

glEnable(GL_TEXTURE_2D);

        glBindTexture(GL_TEXTURE_2D,ti[Map[x][z].typet]); 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    

Start.setTexture(Start.isArea(x,z),Colored.isArea(x,z));



glBegin(GL_TRIANGLES);                //disegno dei triangli pieni delle tile
            glNormal(Nl[x][z][STH]);
        glTexCoord2f(1.0, 1.0); glVertex3f( x ,Map[x][z].SW,z+1);
          glTexCoord2f(0.5, 0.5);   glVertex3f( x+0.5,Map[x][z].C,z+0.5);     //con area colorata       
                glTexCoord2f(0.0, 1.0); glVertex3f( x+1 ,Map[x][z].SE,z+1);
        
          
    
    glNormal(Nl[x][z][WST]);        
 
          glTexCoord2f(1.0, 0.0); glVertex3f( x,Map[x][z].NW,z);    
          glTexCoord2f(0.5, 0.5);    glVertex3f( x+0.5,Map[x][z].C,z+0.5); 
        glTexCoord2f(1.0, 1.0);   glVertex3f( x ,Map[x][z].SW,z+1);




    glNormal(Nl[x][z][EST]);
  glTexCoord2f(0.0, 0.0);  glVertex3f( x+1 ,Map[x][z].NE,z);
  glTexCoord2f(0.5, 0.5);  glVertex3f( x+0.5,Map[x][z].C,z+0.5);  
       glTexCoord2f(0.0, 1.0);   glVertex3f( x+1 ,Map[x][z].SE,z+1);


    glNormal(Nl[x][z][NTH]);
   glTexCoord2f(0.0, 0.0);  glVertex3f( x+1 ,Map[x][z].NE,z);
  glTexCoord2f(0.5, 0.5); glVertex3f( x+0.5,Map[x][z].C,z+0.5);  
    glTexCoord2f(1.0, 0.0);       glVertex3f( x,Map[x][z].NW,z);    


      glEnd();  
break;
default: break;
}
}
void MadMap::DrawWall(int x,int z,int side,int option)
{
    vcg::Point3f wall[4];
  Point3f nl;
nl[YY]=0;
switch (side){
    case NORTH:
        nl[XX]=0;
        
        nl[ZZ]=1;
        wall[0]=vcg::Point3f(x,Map[x][z].SW,z+1);
        wall[1]=vcg::Point3f(x+1,Map[x][z].SE,z+1);
        if ((z+1)<(Dim.Z)) {
            wall[2]=vcg::Point3f(x+1,Map[x][z+1].NE,z+1);
            wall[3]=vcg::Point3f(x,Map[x][z+1].NW,z+1);
                }
        else {wall[2]=vcg::Point3f(x+1,0,z+1);
            wall[3]=vcg::Point3f(x,0,z+1);}
        break;
        
    case SOUTH:
        nl[XX]=0;
    
        nl[ZZ]=-1;
        wall[0]=vcg::Point3f(x,Map[x][z].NW,z);
        wall[1]=vcg::Point3f(x+1,Map[x][z].NE,z);
        if ((z-1)>=0) {
            wall[2]=vcg::Point3f(x+1,Map[x][z-1].SE,z);
            wall[3]=vcg::Point3f(x,Map[x][z-1].SW,z);
                }
        else {wall[2]=vcg::Point3f(x+1,0,z);
            wall[3]=vcg::Point3f(x,0,z);}
        break;
        
    case EAST:
nl[XX]=-1;
    
        nl[ZZ]=0;
        wall[0]=vcg::Point3f(x,Map[x][z].NW,z);
        wall[1]=vcg::Point3f(x,Map[x][z].SW,z+1);
        if ((x-1)>=0) {
            wall[2]=vcg::Point3f(x,Map[x-1][z].SE,z+1);
            wall[3]=vcg::Point3f(x,Map[x-1][z].NE,z);
                }
        else {wall[2]=vcg::Point3f(x,0,z+1);
            wall[3]=vcg::Point3f(x,0,z);}
        break;

    case WEST:
nl[XX]=1;
    
        nl[ZZ]=0;
        wall[0]=vcg::Point3f(x+1,Map[x][z].NE,z);
        wall[1]=vcg::Point3f(x+1,Map[x][z].SE,z+1);
        if ((x+1)<Dim.Z) {
            wall[2]=vcg::Point3f(x+1,Map[x+1][z].SW,z+1);
            wall[3]=vcg::Point3f(x+1,Map[x+1][z].NW,z);
                }
        else {wall[2]=vcg::Point3f(x+1,0,z+1);
            wall[3]=vcg::Point3f(x+1,0,z);}
        break;
    default: break;
}
            
if  (( (wall[0].y()+wall[1].y())/2) >=( (wall[2].y()+wall[3].y())/2) )
    { 
         glLoadName(z*100+x);
        switch (option) {
        case SOLID:
                glDisable(GL_TEXTURE_2D);
                if (Colored.isArea(x,z)) glColor3f(0,0,1);
                else glColor3f(1,1,1);
                glBegin(GL_POLYGON);
                glNormal(nl);
                    glVertex3f(wall[0].x(),wall[0].y(),wall[0].z());  
                    glVertex3f(wall[1].x(),wall[1].y(),wall[1].z());
                    glVertex3f(wall[2].x(),wall[2].y(),wall[2].z());
                    glVertex3f(wall[3].x(),wall[3].y(),wall[3].z()); 
                 glEnd();
            break;
            
        case TEXTURED:

        Wall.setTexture(true,Colored.isArea(x,z));
                glBindTexture(GL_TEXTURE_2D,ti[Map[x][z].typew]); 
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    
    
                glBegin(GL_POLYGON);
                    glNormal(nl);
                    glTexCoord2f(1, 0);  glVertex3f(wall[0].x(),wall[0].y(),wall[0].z());  
                    glTexCoord2f(0, 0); glVertex3f(wall[1].x(),wall[1].y(),wall[1].z());
                    glTexCoord2f(0, (wall[2].y()-wall[1].y()));glVertex3f(wall[2].x(),wall[2].y(),wall[2].z());
                    glTexCoord2f(1, (wall[3].y()-wall[0].y())); glVertex3f(wall[3].x(),wall[3].y(),wall[3].z()); 
                 glEnd();
            break;

        case WIREFRAME:
            if (Colored.isArea(x,z)) glColor3f(0,0,1);
                else glColor3f(1,1,1);
                    glBegin(GL_LINE_LOOP);
                          glVertex3f( wall[0].x(),wall[0].y(),wall[0].z());   
                          glVertex3f( wall[1].x(),wall[1].y(),wall[1].z());
                          glVertex3f( wall[2].x(),wall[2].y(),wall[2].z());
                        glVertex3f( wall[3].x(),wall[3].y(),wall[3].z());
                    glEnd();
            break;
        default: break;
                              } 
    }

}
bool MadMap::intersect(float x1,float y1,float z1,float x2, float y2,float z2)
{

    int j;
    int n=sqrt(pow(x2-x1,2)+pow(z2-z1,2));
    //n=n*n;
    for (j=0;j<=n;j++) 
    {   if (getY((x2*j+x1*(n-j))/n,(z2*j+z1*(n-j))/n)>((y2*j+y1*(n-j))/n))
                return false;
        if (getY((x2*j+(x1-1)*(n-j))/n,(z2*j+z1*(n-j))/n)>((y2*j+y1*(n-j))/n))
                return false;
        if (getY((x2*j+(x1+1)*(n-j))/n,(z2*j+z1*(n-j))/n)>((y2*j+y1*(n-j))/n))
                return false;
        if (getY((x2*j+(x1)*(n-j))/n,(z2*j+(z1-1)*(n-j))/n)>((y2*j+y1*(n-j))/n))
                return false;
        if (getY((x2*j+(x1)*(n-j))/n,(z2*j+(z1+1)*(n-j))/n)>((y2*j+y1*(n-j))/n))
                return false; 
    }

    return true;

}
int MadMap::getColoredGravity()
{
    if (Colored.first.X==-1) return -1; 
int ret=Map[Colored.first.X][Colored.first.Z].grav;
for (int i=Colored.first.X; i<=Colored.last.X;i++)

    for (int j=Colored.first.Z; j<=Colored.last.Z;j++)
        if (ret!=Map[i][j].grav) return -1;
return ret;

}
int MadMap::getColoredTexTile()

{   
if (Colored.first.X==-1) return -1; 
int ret=Map[Colored.first.X][Colored.first.Z].typet;
for (int i=Colored.first.X; i<=Colored.last.X;i++)

    for (int j=Colored.first.Z; j<=Colored.last.Z;j++)
        if (ret!=Map[i][j].typet) return -1;
return ret;
}

int MadMap::getColoredAttrito()

{   
if (Colored.first.X==-1) return -1; 
int ret=Map[Colored.first.X][Colored.first.Z].attr;
for (int i=Colored.first.X; i<=Colored.last.X;i++)

    for (int j=Colored.first.Z; j<=Colored.last.Z;j++)
        if (ret!=Map[i][j].attr) return -1;
return ret;
}
int MadMap::getColoredTexWall()

{   
if (Colored.first.X==-1) return -1; 
int ret=Map[Colored.first.X][Colored.first.Z].typew;
for (int i=Colored.first.X; i<=Colored.last.X;i++)

    for (int j=Colored.first.Z; j<=Colored.last.Z;j++)
        if (ret!=Map[i][j].typew) return -1;
return ret;
}