/*

  Hovertank's ROAM implementation:
  This code is taken and modified from the SimpleROAM implementation.

  The original copyright and info is included:

		//
		// ROAM Simplistic Implementation
		// All code copyright Bryan Turner (Jan, 2000)
		//                    brturn@bellsouth.net
		//
		// Based on the Tread Marks engine by Longbow Digital Arts
		//                               (www.LongbowDigitalArts.com)
		// Much help and hints provided by Seumas McNally, LDA.
		//

*/

#pragma once


#include <glh_extensions.h>
//#include <glh_glut.h>
#include <glh_array.h>
#include <glh_obs.h>
#include <glh_convenience.h>
// ...and nVidia's convenient png loader!
#include "nv_png.h"

// Add my own handy convenience function:
/*
namespace glh
{
	inline void glRotate(float angle, vec3f axis)
		{	glRotatef(angle, axis[0], axis[1], axis[2]);  }
};
*/

#include <vector>

using namespace std;
using namespace glh;

typedef glh::array2<unsigned char> gs_image_type;


// Depth of variance tree: should be near SQRT(PATCH_SIZE) + 1
#define VARIANCE_DEPTH (9)

// Predefines...
class Landscape;

//
// TriTreeNode Struct
// Store the triangle tree data, but no coordinates!
//
struct TriTreeNode
{
	TriTreeNode *LeftChild;
	TriTreeNode *RightChild;
	TriTreeNode *BaseNeighbor;
	TriTreeNode *LeftNeighbor;
	TriTreeNode *RightNeighbor;
};

//
// Patch Class
// Store information needed at the Patch level
//
class Patch
{
protected:
	gs_image_type* m_HeightMap;									// Pointer to height map to use
	glh::array2<glh::vec3f>* m_NormalMap;
	int m_WorldX, m_WorldY;										// World coordinate offset of this patch.

	unsigned char m_VarianceLeft[ 1<<(VARIANCE_DEPTH)];			// Left variance tree
	unsigned char m_VarianceRight[1<<(VARIANCE_DEPTH)];			// Right variance tree

	unsigned char *m_CurrentVariance;							// Which varience we are currently using. [Only valid during the Tessellate and ComputeVariance passes]

	TriTreeNode m_BaseLeft;										// Left base triangle tree node
	TriTreeNode m_BaseRight;									// Right base triangle tree node

public:
	bool          m_VarianceDirty;								// Does the Varience Tree need to be recalculated for this Patch?
	bool          m_isVisible;									// Is this patch visible in the current frame?

public:
	// Some encapsulation functions & extras
	TriTreeNode *GetBaseLeft()  { return &m_BaseLeft; }
	TriTreeNode *GetBaseRight() { return &m_BaseRight; }
	char isDirty()     { return m_VarianceDirty; }
	int  isVisibile( ) { return m_isVisible; }
	void SetVisibility( int eyeX, int eyeY, int leftX, int leftY, int rightX, int rightY );

	// The static half of the Patch Class
	void Init( int heightX, int heightY, int worldX, int worldY, gs_image_type* hMap, glh::array2<glh::vec3f>* nMap );
	void Reset();
	void Tessellate();
	void Render();
	void ComputeVariance();

	// The recursive half of the Patch Class
	void			Split( TriTreeNode *tri);
	void			RecursTessellate( TriTreeNode *tri, int leftX, int leftY, int rightX, int rightY, int apexX, int apexY, int node );
	void			RecursRender( TriTreeNode *tri, int leftX, int leftY, int rightX, int rightY, int apexX, int apexY );
	unsigned char	RecursComputeVariance(	int leftX,  int leftY,  unsigned char leftZ,
													int rightX, int rightY, unsigned char rightZ,
													int apexX,  int apexY,  unsigned char apexZ,
													int node);
};
