package cgp.examples;

import cgp.math.Point2f;
import cgp.math.Point4f;
import cgp.math.Matrix4f;

import cgp.basics.Face3D;
import cgp.basics.Shape3D;
import cgp.basics.Texture2D;

import cgp.render.ClampMode;

  /**
   * Diese Klasse repräsentiert einen Ikosaeder
   *
   * @author Ralf Kunze
   * @version ML 12.06.2002
   */
public class Ikosaeder extends Shape3D {

  /**
   * Seitenverhaeltnis beim goldenen Schnitt.
   */
  public static float phi  = 0.5f*(float)(Math.sqrt(5)+1);

  /** 
   * Einheitswuerfel mit Schwerpunkt im Ursprung; MC2WC wird auf die 
   * Einheitsmatrix gesetzt.
   */
  public Ikosaeder() {
    super();


    Point4f p0  = new Point4f(  0.0f,  phi ,  1.0f,1f);
    Point4f p1  = new Point4f(  0.0f, -phi ,  1.0f,1f);
    Point4f p2  = new Point4f( -1.0f,  0.0f,  phi ,1f);
    Point4f p3  = new Point4f( -phi , -1.0f,  0.0f,1f);
    Point4f p4  = new Point4f( -phi ,  1.0f,  0.0f,1f);
    Point4f p5  = new Point4f( -1.0f,  0.0f, -phi ,1f);
    Point4f p6  = new Point4f(  0.0f,  phi , -1.0f,1f);
    Point4f p7  = new Point4f(  1.0f,  0.0f, -phi ,1f);
    Point4f p8  = new Point4f(  phi ,  1.0f,  0.0f,1f);
    Point4f p9  = new Point4f(  phi , -1.0f,  0.0f,1f);
    Point4f p10 = new Point4f(  1.0f,  0.0f,  phi ,1f);
    Point4f p11 = new Point4f(  0.0f, -phi , -1.0f,1f);
    
    mc.add(p0); //0
    mc.add(p1); //1
    mc.add(p2); //2
    mc.add(p3); //3
    mc.add(p4); //4
    mc.add(p5); //5
    mc.add(p6); //6
    mc.add(p7); //7
    mc.add(p8); //8
    mc.add(p9); //9
    mc.add(p10); //10
    mc.add(p11); //11

    int[][] indices =  {{ 4, 2, 0},
                        { 6, 4, 0},
                        { 8, 6, 0},
                        {10, 8, 0},
                        { 2,10, 0},
                        { 4, 3, 2},
                        { 4, 5, 3},
                        { 6, 5, 4},
                        { 6, 7, 5},
                        { 8, 7, 6},
                        { 8, 9, 7},
                        {10, 9, 8},
                        {10, 1, 9},
                        { 1,10, 2},
                        { 2, 3, 1},
                        { 1, 3,11},
                        { 3, 5,11},
                        { 5, 7,11},
                        { 7, 9,11},
                        { 9, 1,11}};

    Texture2D[] tex = new Texture2D[7];
    tex[0] = new Texture2D("../textures/amir.jpg");
    tex[1] = new Texture2D("../textures/ansgar.jpg");
    tex[2] = new Texture2D("../textures/axel.jpg");
    tex[3] = new Texture2D("../textures/eugenia.jpg");
    tex[4] = new Texture2D("../textures/ewgeni.jpg");
    tex[5] = new Texture2D("../textures/olaf.jpg");
    tex[6] = new Texture2D("../textures/tanja.jpg");
    Point2f[] tc = new Point2f[3];         // Platz fuer Texturkoords

                              // Setze die Texture-Koordinaten an den Ecken
    tc[0] = new Point2f(0.5f, -(float)(Math.sqrt(3)/2));
    tc[1] = new Point2f(-(float)(Math.sqrt(3)/3), 0.999f);
    tc[2] = new Point2f((float)(1+Math.sqrt(3)/3), 0.999f);


    for(int i=0; i<20; i++) {
      Face3D fnew = new Face3D(this, indices[i], tex[i%7], tc);
      fnew.uMode = new ClampMode();      // Modus der Texture
      fnew.vMode = fnew.uMode;
      
      add(fnew);
    }

    // durch Setzen der Einheitsmatrix als Transformationsmatrix, wird die
    // WC-Geometrie initialisiert
    setMC2WC(new Matrix4f());
   }

  /** 
   * Instanziiert einen Einheitswuerfel, der die MC-Geometrie von dem
   * uebergebenen Wuerfel uebernimmt.
   */
  public Ikosaeder(Ikosaeder src) {
    mc = src.mc;

    for(int i=0; i<20; i++) {
      Face3D face = src.faces[i];
      Point2f[] tc = new Point2f[face.count];

      for(int j=0; j<face.count; j++) {
        tc[j]=face.vertices[j].tc;
      }

      Face3D fnew = new Face3D(this, face.mcindex, face.tex, tc);
      fnew.uMode = face.uMode;            // Modus in u-
      fnew.vMode = face.vMode;            // und v-Richtungen

      add(fnew);
    }

    // durch Setzen der Einheitsmatrix als Transformationsmatrix, wird die 
    // WC-Geometrie initialisiert
    setMC2WC(new Matrix4f());
  }
    
  /**
   * Liefert einen neuen Ikosaeder zurueck, der sich die MC-Geometrie mit
   * diesem
   * teilt.
   */
  public Shape3D createMCSharingShape() {
    return new Ikosaeder(this);
  }
}