///////////////////////////////////////////////////////////////////////////////
/// @file deCamera_priv.hpp
///
/// @brief Viewport & Rendering Data, private header
///
/// @author Assassin
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Jan 2002
/// @author Assassin
/// @remarks Creation
///
///////////////////////////////////////////////////////////////////////////////

#ifndef DECAMERA_PRIV_HPP
#define DECAMERA_PRIV_HPP

#include "deCamera.hpp"
#include "deArray.hpp"

// this class is essentially a storage class to interface deRender & deScene
class deCamera : public IdeCamera
{
public:
	deCamera(void);
	deCamera(const deCamera &ref);
	~deCamera(void);
	long Release();
	
	void SetWindow(HWND window);
	void SetRect(deRect rect);
	void SetFOV(deDouble Degrees);
	void SetScreenAspect(long PixelWidth, long PixelHeight, deDouble AspectRatio);
	void SetClip(deDouble Near, deDouble Far);
	void FogEnable(deBoolean Enable);
	void SetFog(deFloat Near, deFloat Far, deARGB Color, deBoolean RangeFog);
	void SetOrthoWidth(deDouble Width);
	void EnableOrtho(deBoolean OrthoEnable);
//	void BuildRootFrustum(deFrustum &f);
	deBoolean BuildRootFrustum(IdePlaneFrustum * pFrustum);
	// returns a unit vector from the current camera translation
	// that extends along the ray corresponding to screen coord (x,y)
	deVec3d ScreenPointToWorldVec(int x, int y, deVec3d *StartPosition);
	// transforms a 3D world position into an (x,y) pair on the screen
	deBoolean WorldPosToScreenPos(const deVec3d &pos, int &x, int &y);
//	deBoolean FrustumRect(const deFrustum & f, deRect & r);
	deBoolean FrustumRect(const IdePlaneFrustum* f, deRect & r);
	
	HWND GetWindow();
	deRect GetRect();
	deDouble GetFOV();
	deDouble GetFOVy(deDouble &Aspect);
	deDouble GetNearClip();
	deDouble GetFarClip();
	deDouble GetOrthoWidth();
	deBoolean IsOrtho();
	deBoolean GetFog(deFloat& Near, deFloat& Far, deARGB& Color, deBoolean& RangeFog);
	
	void LockAspect(deDouble Aspect);
	
	deTransformInfo&	Position();
	
private:
	HWND		m_hWnd;
	deBoolean	m_IsOrtho;
	deBoolean	m_FogEnable;
	deBoolean	m_RangeFog;
	deBoolean	m_AspectLocked;
	deARGB		m_FogColor;
	deFloat		m_NearFog, m_FarFog;
	deDouble	m_OrthoWidth;
	deDouble	m_NearClip, m_FarClip;
	deDouble	m_FOV, m_FOVy;
	deDouble	m_LastAspect;
	deDouble	m_PixelAspect;
	deRect		m_Viewport;
	deTransform	m_Position;
};

class dePlaneFrustum : public IdePlaneFrustum
{
private:
	deTArray <dePlane> m_Planes;
	deVec3d m_InVec, m_PosVec;
	deDouble m_Min, m_Max;
	deBoolean m_Ortho;
public:
	dePlaneFrustum();
	~dePlaneFrustum();

	long Release();

	deBoolean CreateFromPolygon(const deVec3d * PointArray, long NumPoints, const deVec3d & Position);
	deBoolean CopyFromFrustum(const IdePlaneFrustum* Ref);
	
	deBoolean Optimize();
	
	deBoolean IsOrtho() const;
	void SetOrtho(deBoolean Ortho);
	
	u32  GetNumPlanes() const;
	void SetNumPlanes(u32 NumPlanes);
	
	void AddPlane(const dePlane & plane);

	void GetPlane(u32 index, dePlane & plane) const;
	void SetPlane(u32 index, const dePlane & plane);
	
	void SetInVec(const deVec3d & InVec);
	void SetPosVec(const deVec3d & PosVec);
	void SetDists(const deDouble & Min, const deDouble & Max);
	deDouble GetMinDist() const;
	deDouble GetMaxDist() const;

	deBoolean TestSphereInside(const deBoundSphere& Sphere, const deVec3d& WorldPos, deBoolean & AllInside) const;
	deBoolean TestAABBInside(const deAABB& BBox, const deVec3d& WorldPos, deBoolean & AllInside) const;
};

#endif
