function Faccia(matVertici)
{
   /*Private:*/

   /*Matrice RAW contenente [Vertici]*/
   /*Deve essere [Hsx,Hdx,Ldx,Lsx] se Verticale*/
   /*Deve essere [Fsx,Fdx,Ndx,Nsx] se Orizzontale*/
   /*Deve essere [HN,HF,LF,LN] se Laterale*/
   /*H-->High L-->Low F-->Far N-->Near sx-->Left dx-->Right*/
   this.matrix3D = matVertici;

   /*Matrice RAW contenente [[Col,Col,..,Col],..,[..]]*/
   /*Pseudo Texture. Definisce l'aspetto della Faccia*/
   this.texture = null;

   /*Matrice RAW contenente [DimSC_X,DimSC_Y,LengthCubetto,ColoreBordo]*/
   /*Dati relativi agli Adesivi da Texturizzare*/
   this.dati_texture = null;

   /*Vertici che compongono la Faccia Ruotata*/
   this.vertice_ruotato = new Array(4);

   /*Normale Originale alla Faccia*/
   this.normale_originale = null;

   /*Normale Ruotata alla Faccia*/
   this.normale_ruotata = null;

   /*Visibilita' della Faccia*/
   this.visibility = null;

   /*Matrice RAW contenente Vertici 2D ottenuti da Conversione 3D -> 2D*/
   /*Matrice di supporto non strettamente necessaria (ma conveniente)*/
   this.matrix2D = null;

   /*Matrice RAW contenente Vertici 2D degli Adesivi*/
   /*Deve avere formato [[VHsxA0,VHdxA0,VHsxA1,VHdxA1,..],[VL],[VH],..]*/
   this.matrix_texture_2D = null;

   /*Metodo per Verificare Visibilita' Faccia*/
   this.IsVisible = IsVisibleFaccia;

   /*Metodo per la Conversione 3D -> 2D della Faccia*/
   /*Il risultato della conversione e' immesso in "matrix2D"*/
   this.convFaccia3D2D = conversioneFaccia3D2D;

   /*Metodo per la Conversione 3D -> 2D della Texture*/
   /*Il risultato della conversione e' immesso in "matrix_texture_2D"*/
   this.conv_Texture_Faccia3D2D = conversione_Texture_Faccia3D2D;

   /*Metodo per Renderizzare Texture Faccia*/
   this.drawTexture = draw_Texture_Faccia;

   /*Public:*/

   /*Metodo di Inizializzazione Faccia*/
   this.init = InitFaccia;

   /*Metodo per Settare la Normale Originale alla Faccia*/
   this.SetNormale = Setta_Normale_Originale_Faccia;

   /*Metodo per Settare la Texture della Faccia*/
   this.SetTexture = SettaTextureFaccia;

   /*Metodo per la rotazione della Faccia*/
   /*Devono essere passati un angolo e un tipo di operazione*/
   /*Se l'operazione e' 0 la rotazione viene eseguita come ultima rotazione*/
   /*Se l'operazione e' 1 la rotazione viene eseguita come prima rotazione*/
   this.ruotaX = ruotaXFaccia; //attorno all'asse x
   this.ruotaY = ruotaYFaccia; //attorno all'asse y
   this.ruotaZ = ruotaZFaccia; //attorno all'asse z

   /*Metodo per la Renderizzazione*/
   this.draw = drawFaccia;
}

function InitFaccia()
{
   /*Vertici della Faccia Ruotata*/
   for(var i=0;i<4;i++)
   {
      this.vertice_ruotato[i] = new Coord(this.matrix3D[i]);
      this.vertice_ruotato[i].init();
   }

   /*Normale Originale alla Faccia*/
   this.normale_originale = null;

   /*Normale alla Faccia*/
   this.normale_ruotata = null;

   /*Matrice RAW contenente [[Col,Col,..,Col],..,[..]]*/
   /*Pseudo Texture. Definisce l'aspetto della Faccia*/
   this.texture = null;

   /*Matrice RAW contenente [DimSC_X,DimSC_Y,LengthCubetto,ColoreBordo]*/
   /*Dati relativi agli Adesivi da Texturizzare*/
   this.dati_texture = null;

   /*Visibilita' della Faccia*/
   this.visibility = null;

   /*Matrice RAW contenente Vertici Faccia 2D ottenuti da Conversione 3D -> 2D*/
   this.matrix2D = null;

   /*Matrice RAW contenente Vertici 2D degli Adesivi*/
   /*Deve avere formato [[VHsxA0,VHdxA0,VHsxA1,VHdxA1,..],[VL],[VH],..]*/
   this.matrix_texture_2D = null;
}

function Setta_Normale_Originale_Faccia(vettNormale)
{
   this.normale_originale = vettNormale;

   this.normale_ruotata = new Coord(vettNormale);
   this.normale_ruotata.init();
}

function IsVisibleFaccia()
{
   /*Forzatura: Utilizzo un metodo Privato (per convenienza)*/
   this.normale_ruotata.applica_rotazioni();

   /*Forzatura: Leggo un membro Privato (per convenienza)*/
   var soglia=this.normale_ruotata.vett3D_ruotato[2];
   /*Arrotondo per diminuire il grado di precisione eccessivo*/
   soglia = Math.round(soglia*100)/100;
   if(soglia>=0) this.visibility = false;
   else this.visibility = true;
}

function SettaTextureFaccia(matTexture,vettTexture)
{
   this.texture = matTexture;
   this.dati_texture = vettTexture;
}

function ruotaXFaccia(omega,tipo)
{
   for(var i=0;i<4;i++) this.vertice_ruotato[i].ruotaX(omega,tipo);

   this.normale_ruotata.ruotaX(omega,tipo);
}

function ruotaYFaccia(omega,tipo)
{
   for(var i=0;i<4;i++) this.vertice_ruotato[i].ruotaY(omega,tipo);

   this.normale_ruotata.ruotaY(omega,tipo);
}

function ruotaZFaccia(omega,tipo)
{
   for(var i=0;i<4;i++) this.vertice_ruotato[i].ruotaZ(omega,tipo);

   this.normale_ruotata.ruotaZ(omega,tipo);
}

function conversioneFaccia3D2D()
{
   for(var i=0;i<4;i++) this.vertice_ruotato[i].conv3D2D();

   /*La Matrice "matrix2D" e' usata solo per Convenienza (non strettamente necessaria)*/
   this.matrix2D = [this.vertice_ruotato[0].vett2D,this.vertice_ruotato[1].vett2D,this.vertice_ruotato[2].vett2D,this.vertice_ruotato[3].vett2D];
}

function conversione_Texture_Faccia3D2D()
{
   var punto = new Array(4);

   for(var i=0;i<4;i++)
   {
      punto[i] = new Coord([0,0,0]);
      punto[i].init();

      /*Forzatura: Leggo e Scrivo un membro Privato (per convenienza)*/
      punto[i].matrix_rotazionale = this.normale_ruotata.matrix_rotazionale;
   }

   /*Forzatura: Leggo membri Privati (per convenienza)*/
   var posX = this.vertice_ruotato[0].vett3D_originale[0];
   var posY = this.vertice_ruotato[0].vett3D_originale[1];
   var posZ = this.vertice_ruotato[0].vett3D_originale[2];

   /*Spessore bordino nero attorno agli Adesivi*/
   /*Spessore/Len_Cubetto = 6/100 (ossia 6%)*/
   var s = 0.06*this.dati_texture[2];
   var len_adesivo = this.dati_texture[2]-(2*s)-1;

   this.matrix_texture_2D = new Array(2*this.dati_texture[1]);

   for(var rig=0;rig<this.dati_texture[1];rig++)
   {
      var vettRigaH = new Array(2*this.dati_texture[0]);
      var vettRigaL = new Array(2*this.dati_texture[0]);

      for(var col=0;col<this.dati_texture[0];col++)
      {
         if(this.normale_originale[0] != 0)
         {
            punto[0].traslaXYZ([posX,posY-(1+s)-(this.dati_texture[2]*rig),posZ+(1+s)+(this.dati_texture[2]*col)]);
            punto[1].traslaXYZ([posX,posY-(1+s)-(this.dati_texture[2]*rig),posZ+(1+s)+(this.dati_texture[2]*col)+len_adesivo]);
            punto[2].traslaXYZ([posX,posY-(1+s)-(this.dati_texture[2]*rig)-len_adesivo,posZ+(1+s)+(this.dati_texture[2]*col)+len_adesivo]);
            punto[3].traslaXYZ([posX,posY-(1+s)-(this.dati_texture[2]*rig)-len_adesivo,posZ+(1+s)+(this.dati_texture[2]*col)]);
         }
         if(this.normale_originale[1] != 0)
         {
            punto[0].traslaXYZ([posX+(1+s)+(this.dati_texture[2]*col),posY,posZ-(1+s)-(this.dati_texture[2]*rig)]);
            punto[1].traslaXYZ([posX+(1+s)+(this.dati_texture[2]*col)+len_adesivo,posY,posZ-(1+s)-(this.dati_texture[2]*rig)]);
            punto[2].traslaXYZ([posX+(1+s)+(this.dati_texture[2]*col)+len_adesivo,posY,posZ-(1+s)-(this.dati_texture[2]*rig)-len_adesivo]);
            punto[3].traslaXYZ([posX+(1+s)+(this.dati_texture[2]*col),posY,posZ-(1+s)-(this.dati_texture[2]*rig)-len_adesivo]);
         }
         if(this.normale_originale[2] != 0)
         {
            punto[0].traslaXYZ([posX+(1+s)+(this.dati_texture[2]*col),posY-(1+s)-(this.dati_texture[2]*rig),posZ]);
            punto[1].traslaXYZ([posX+(1+s)+(this.dati_texture[2]*col)+len_adesivo,posY-(1+s)-(this.dati_texture[2]*rig),posZ]);
            punto[2].traslaXYZ([posX+(1+s)+(this.dati_texture[2]*col)+len_adesivo,posY-(1+s)-(this.dati_texture[2]*rig)-len_adesivo,posZ]);
            punto[3].traslaXYZ([posX+(1+s)+(this.dati_texture[2]*col),posY-(1+s)-(this.dati_texture[2]*rig)-len_adesivo,posZ]);
         }

         for(var i=0;i<4;i++) punto[i].conv3D2D();

         vettRigaH[col*2] = punto[0].vett2D;
         vettRigaH[col*2+1] = punto[1].vett2D;
         vettRigaL[col*2] = punto[3].vett2D;
         vettRigaL[col*2+1] = punto[2].vett2D;
      }

      this.matrix_texture_2D[rig*2] = vettRigaH;
      this.matrix_texture_2D[rig*2+1] = vettRigaL;

      delete vettRigaH;
      delete vettRigaL;
   }

   for(var i=0;i<4;i++) delete punto[i];
}

function draw_Texture_Faccia(lavagna)
{
   lavagna[0].fillStyle = (this.texture == null)?black:this.dati_texture[3];

   lavagna[0].beginPath();
   lavagna[0].moveTo((lavagna[1]/2)+this.matrix2D[0][0],(lavagna[1]/2)-this.matrix2D[0][1]);
   lavagna[0].lineTo((lavagna[1]/2)+this.matrix2D[1][0],(lavagna[1]/2)-this.matrix2D[1][1]);
   lavagna[0].lineTo((lavagna[1]/2)+this.matrix2D[2][0],(lavagna[1]/2)-this.matrix2D[2][1]);
   lavagna[0].lineTo((lavagna[1]/2)+this.matrix2D[3][0],(lavagna[1]/2)-this.matrix2D[3][1]);
   lavagna[0].fill();

   if(this.texture != null)
   {
      /*Metodo Invocato per la Conversione 3D -> 2D della Texture*/
      this.conv_Texture_Faccia3D2D();

      for(var rig=0;rig<this.dati_texture[1];rig++)
      {
         for(var col=0;col<this.dati_texture[0];col++)
         {
            if(this.dati_texture[1] == 1)
            {
               lavagna[0].fillStyle = this.texture[col];
            }
            else
            {
               if(this.dati_texture[0] == 1)
               {
                  lavagna[0].fillStyle = this.texture[rig];
               }
               else
               {
                  lavagna[0].fillStyle = this.texture[rig][col];
               }
            }

            lavagna[0].beginPath();
            lavagna[0].moveTo((lavagna[1]/2)+this.matrix_texture_2D[rig*2][col*2][0],(lavagna[1]/2)-this.matrix_texture_2D[rig*2][col*2][1]);
            lavagna[0].lineTo((lavagna[1]/2)+this.matrix_texture_2D[rig*2][col*2+1][0],(lavagna[1]/2)-this.matrix_texture_2D[rig*2][col*2+1][1]);
            lavagna[0].lineTo((lavagna[1]/2)+this.matrix_texture_2D[rig*2+1][col*2+1][0],(lavagna[1]/2)-this.matrix_texture_2D[rig*2+1][col*2+1][1]);
            lavagna[0].lineTo((lavagna[1]/2)+this.matrix_texture_2D[rig*2+1][col*2][0],(lavagna[1]/2)-this.matrix_texture_2D[rig*2+1][col*2][1]);
            lavagna[0].fill();
         }
      }
   }
}

function drawFaccia(lavagna)
{
   this.drawTexture(lavagna);
}