///////////////////////////////////////////////////////////////////////////////
/// @file deOccludeRaster.hpp
///
/// @brief software rasterizer for doing occlusion culling with
///
/// @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 May 2003
/// @author Assassin
/// @remarks Initial Creation
///
///////////////////////////////////////////////////////////////////////////////

#ifndef DEOCCLUDERASTER_HPP
#define DEOCCLUDERASTER_HPP

#include "deGlobalTypes.hpp"
#include "deMath.hpp"

#define OCCLUDE_16BIT		(1)	// faster when enabled
#define OCCLUDE_MINBUFFER	(0) // faster when disabled

class deOccludeRasterizer
{
public:
#if OCCLUDE_16BIT
	typedef u16 BufferType;
#else
	typedef u32 BufferType;
#endif

	deOccludeRasterizer();
	~deOccludeRasterizer();

	void SetBufferSize(short Width, short Height);
	void SetViewport(const deRect& ViewRect);
	void SetScissorRect(const deRect& ScissorRect);
	void SetGradientCutoff(deFloat Cutoff);
	void SetPixelCounting(deBoolean CountPixels);
	void SetWorldTransform(const deTransformInfo & World);
	void SetViewTransform(const deTransformInfo & View);
	void SetFOVClipping(float FOVY, float Aspect, float ClipNear, float ClipFar, deFloatRect* FSubRect = NULL);
	void SetOrthoClipping(float Width, float Height, float ClipNear, float ClipFar, deBoolean Invert, deFloatRect* FSubRect = NULL);

	void ClearBuffer();
	int RenderIndexedTriangles(deBoolean TestOnly, const deVertex * Vertices, long NumVertices, const WORD * Indices = NULL, long NumIndices = 0);

	const BufferType* GetBuffer(long level = -1, deBoolean MinNotMax = deFALSE) const;
	long GetBufferDepth() const;
	void GetBufferSize(short& Width, short& Height,long level = -1) const;
	void GetViewport(deRect & ViewRect) const;
	void GetScissorRect(deRect & ScissorRect) const;
	deFloat GetGradientCutoff() const;

private:
	void ConcatenateMatrices();
	void ResizeBuffer();
	void BuildHierarchy(deBoolean ForceTearDown = deFALSE);
	deBoolean TestScreenExtentsVisible(const deFloatRect& FullExtents, DWORD MinZ, int MaxLevel);

	struct BufferLevel_t
	{
		short Width, Height;
		BufferType* MaxBuffer;
#if OCCLUDE_MINBUFFER
		BufferType* MinBuffer;
#endif
	};

	deTransform m_WorldTransform;
	deTransform m_ViewPosTransform;
	deTransform m_ViewportTransform;
	deMatrix44 m_ProjectionTransform;
	//deTransform m_ConcatenatedTransform;
	deMatrix44 m_ConcatenatedTransform;
	deFloat m_LastProjectionColumn[4];
	deFloat m_NearClip, m_FarClip;
	deRect m_Viewport;
	deRect m_ScissorRect;
	deFloat m_GradientCutoff;
	BufferType* m_Buffer;
	BufferLevel_t* m_Hierarchy;
	short m_Width, m_Height;
	short m_HierarchyDepth;
	deBoolean m_TransformsChanged;
	deBoolean m_BufferSizeChanged;
	deBoolean m_DirtyBuffer;
	deBoolean m_CountPixels;
};

#endif // DEOCCLUDERASTER_HPP