
#ifndef _JL_Frustum_H_
#define _JL_Frustum_H_


#include <stdlib.h>
#include <iostream.h>

#include "vec4.h"


class Camera;


// !_inclusize:
//
// Frustum includes pixels:	_x1 <= x < _x2
//							_y1 <= y < _y2
// (easy to subdivide for power-of-2-sized frustum)
//
//
// _inclusize:
//
// Frustum includes pixels:	_x1 <= x <= _x2
//							_y1 <= y <= _y2
// (easy to subdivide for power-of-2+1-sized frustum)


class Frustum {

	private:
		Camera	*_camera;
		int		_x1, _y1, _x2, _y2;
		Vec4	_N_in_left, _N_in_right, _N_in_bottom, _N_in_top;
		int		_inclusive;

	public: 
		Frustum();
		Frustum(Camera *C, int inclusive, int reset);
		Frustum(const Frustum &F) { CopyFrom(F); }
		virtual ~Frustum();

		void ReConstruct(Camera *C, int inclusive, int reset);

		Frustum& CopyFrom(const Frustum&);
		Frustum& operator=(const Frustum &F) { return CopyFrom(F); }

		friend ostream& operator<<(ostream&, const Frustum&);

		Camera* GetCamera() { return _camera; }
		int X_left() const { return _x1; }
		int Y_bottom() const{ return _y1; }
		int X_right() const{ return _x2; }
		int Y_top() const { return _y2; }
		int XSize() const { return _x2 - _x1 + _inclusive; }
		int YSize() const { return _y2 - _y1 + _inclusive; }

		Vec4& N_in_left() { return _N_in_left; }
		Vec4& N_in_right() { return _N_in_right; }
		Vec4& N_in_bottom() { return _N_in_bottom; }
		Vec4& N_in_top() { return _N_in_top; }

		void CalcTopLevelNormals();
		void CalcLowerLevelNormals();

		void Subdivide(Frustum &F00, Frustum &F10, Frustum &F01, Frustum &F11);

		void Reset();

		void CalcCorners(Vec4 &c00, Vec4 &c10, Vec4 &c01, Vec4 &c11);

		int TestPoint(const Vec4 &P);

		void Draw();
		void DrawNormals();
};

#endif
