
// TexturedPlanes.java
// Andrew Davison, April 2005, ad@fivedots.coe.psu.ac.th

/* Třída TexturesPlanes obsahuje mnoho čtyřúhelníků, z nichž každý
   spadá do jistého výškového pásma. Všem je tedy přiřazena stejná
   textura.

   Pro realizaci účinků osvětlení musíme nejdříve vypočítat normálové
   vektory (a smíchat texturu s materiálem). Dále je kvůli výkonu
   vhodné geometrii převést na pásy trojúhelníků (stripifikace).

   Třída je velmi podobná svému protějšku v adresáři /Maze3D, ovšem
   zde se normálové vektory počítají pomocí tříd GeometryInfo a 
   NormalGenerator.

   Technika vybírání je zapnutá, takže metoda getLandHeight() ze třídy
   Landscape může v kterémkoliv bodě získat výšku povrchu.
*/

import java.util.ArrayList;

import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.image.*;
import com.sun.j3d.utils.picking.PickTool;


public class TexturedPlanes extends Shape3D 
{

  public TexturedPlanes(ArrayList coords, String fnm) 
  {
    System.out.println(fnm + "; numPoints: " + coords.size());
    createGeometry(coords);
    createAppearance(fnm);

	// nastav bity oprávnění pro techniku vybírání tak,
    // aby bylo možné extrahovat souřadnice vybraného tvaru
	PickTool.setCapabilities(this, PickTool.INTERSECT_COORD);
  } // konec metody: Texturedmlanes()


  private void createGeometry(ArrayList coords)
  {
    int numPoints = coords.size();
    QuadArray plane = new QuadArray(numPoints, 
						GeometryArray.COORDINATES | 
						GeometryArray.TEXTURE_COORDINATE_2 |
						GeometryArray.NORMALS );

    // nastav souřadnice
    Point3d[] points = new Point3d[numPoints];
    coords.toArray( points );

    // každému čtyřúhelníku přiřaď souřadnice textury
    // proti směru hodinových ručiček počínaje spodním levým rohem
    TexCoord2f[] tcoords = new TexCoord2f[numPoints];
    for(int i=0; i < numPoints; i=i+4) {
      tcoords[i] = new TexCoord2f(0.0f, 0.0f);   // pro 1 bod
      tcoords[i+1] = new TexCoord2f(1.0f, 0.0f);
      tcoords[i+2] = new TexCoord2f(1.0f, 1.0f);
      tcoords[i+3] = new TexCoord2f(0.0f, 1.0f);
    }

    // vytvoř objekt typu GeometryInfo
    GeometryInfo gi = new GeometryInfo(GeometryInfo.QUAD_ARRAY);
    gi.setCoordinates(points);
    gi.setTextureCoordinateParams(1, 2); // jedna sada 2D texetů
    gi.setTextureCoordinates(0, tcoords);

    // vypočítej normálové vektory s velmi jemnými okraji
    NormalGenerator ng = new NormalGenerator();
    ng.setCreaseAngle( (float) Math.toRadians(150));   // výchozí je 44
    ng.generateNormals(gi);

    // pro použití trojúhelníkových pásů
    Stripifier st = new Stripifier();
    st.stripify(gi);

    // extrahuj a použij objekt typu GeometryArray
    setGeometry( gi.getGeometryArray() );
  }  // konec metody: createGeometry()




  private void createAppearance(String fnm)
  // zkombinuje texturu s bílým osvětleným povrchem
  {
    Appearance app = new Appearance();

    // smíchej barvu textury a materiálu
    TextureAttributes ta = new TextureAttributes();
    ta.setTextureMode(TextureAttributes.MODULATE);
    app.setTextureAttributes(ta);

    // načti a nastav texturu, vygeneruj pro ni mipmapy
    TextureLoader loader = new TextureLoader(fnm, TextureLoader.GENERATE_MIPMAP, null);

    Texture2D texture = (Texture2D) loader.getTexture();
    texture.setMinFilter(Texture2D.MULTI_LEVEL_LINEAR);  // nejhezčí

    app.setTexture(texture);      // nastav texturu

    // nastav výchozí bílý materiál
    Material mat = new Material();
    mat.setLightingEnable(true);    // osvětlení je zapnuté
    app.setMaterial(mat);

    setAppearance(app);
  }  // konec metody: createAppearance()


} // konec třídy: Texturedmlanes
