#if !defined(FRUSTUM_H)
#define FRUSTUM_H

#include "Vec.h"
#include "Plane.h"
#include "Tile.h"
#include "Partikel.h"

/****************************************************************************/
/** \class Frustum
    \brief 
 Das Frustum ist der Sichtpyramide mit (normalerweise) vier Seiten, an deren 
 Spitze sich das Auge des Betrachters, bzw. die Camera befindet. 
 Die Frustumspitze ist fest verankert in 0,0,0. Wenn also die Camera, bzw. 
 der Spieler den Standort aendert, wird die Welt in das Frustum hineinbewegt.
 Das ist nicht optimal. Performanter waere es, das Frustum mit der Camera zu 
 bewegen. Auf der anderen Seite vereinfacht es einige Algorithmen, wenn der 
 Ursprung in 0,0,0 sitzt.
 
 Bem.: Das Frustum der Camera hat vier Seiten, weil es den Sichtbereich des
 Betrachters gegen den Bildschirm abgrenzt. Wenn aber der Betrachter durch ein
 Portal schaut, koennen mehr als vier Frustumseiten existieren, weil das 
 Portalfrustum voher gegen das Frustums des Betrachters geclipped wird.  
*****************************************************************************/
class Frustum  
{
private:
  int viewAngle;

public:
  int NearPlaneHeight;
  int NearPlaneWidth;
  int NearFarDist;
  int NearPlaneDist;
  int FarPlaneDist;

private:
  Vec vOrigin;

public:
  Vec vEnd;
  Vec Origin;

private:
  float OriginDist;

public:
  Vec OriginPlaneLR; // Eckpunkt Lower Right der NearPlane (rel. zur Camerapositon im Ursprung)
  Vec OriginPlaneUR; // Eckpunkt Upper Right der NearPlane (rel. zur Camerapositon im Ursprung)
  Vec OriginPlaneLL; // Eckpunkt Lower Left  der NearPlane (rel. zur Camerapositon im Ursprung)
  Vec OriginPlaneUL; // Eckpunkt Upper Left  der NearPlane (rel. zur Camerapositon im Ursprung)

  Vec PlaneDir;
  Vec NearPlaneLR; // Eckpunkt Lower Right der NearPlane (rel. zur Camerapositon im Ursprung)
  Vec NearPlaneUR; // Eckpunkt Upper Right der NearPlane (rel. zur Camerapositon im Ursprung)
  Vec NearPlaneLL; // Eckpunkt Lower Left  der NearPlane (rel. zur Camerapositon im Ursprung)
  Vec NearPlaneUL; // Eckpunkt Upper Left  der NearPlane (rel. zur Camerapositon im Ursprung)

  Vec FarPlaneLR; // Eckpunkt Lower Right der FarPlane (rel. zur Camerapositon im Ursprung)
  Vec FarPlaneUR; // Eckpunkt Upper Right der FarPlane (rel. zur Camerapositon im Ursprung)
  Vec FarPlaneLL; // Eckpunkt Lower Left  der FarPlane (rel. zur Camerapositon im Ursprung)
  Vec FarPlaneUL; // Eckpunkt Upper Left  der FarPlane (rel. zur Camerapositon im Ursprung)
  
private:
   // Achtung: Auch die Standard-Planes muessen im Uhrzeigersinn 
   // sortiert sein:
   enum PLANE_SIDE {PLANE_TOP=0, PLANE_RIGHT = 1, PLANE_BOTTOM = 2, PLANE_LEFT = 3}; 
  
   int m_usedSidePlanes;
   static int SIDE_PLANES; 
  
   Plane* m_sidePlanes; // TODO: 10 == SIDE_PLANES
  
   Plane OriginPlane;
   Plane NearPlane;
   Plane FarPlane;

public:
	Frustum();
   Frustum(int width, int height);
   void  init();
   void  set(Tile& tile);
   float getOriginDist();
   void  clip(Tile& tile);
   bool  inside(Tile& tile);
   bool  inside(Partikel& partikel);
   void  dump();

	virtual ~Frustum();

private:
   bool inside (Vec& v);
   bool intersects(Line& line);
};
#endif // !defined(FRUSTUM_H)
