/*****************************************************************************
 * $Id: mod_pony_terrain.hh,v 1.1 2006/11/24 21:56:58 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	Terrain and associated classes.
 *//*
 * LEGAL:	COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/

#if COMPILING_MODULE_PONY
#ifndef MOD_PONY_TERRAIN_HH
#define MOD_PONY_TERRAIN_HH 1

enum
{
	eTerrainParmMountains_NORMAL,
	eTerrainParmMountains_HUGE,
	eTerrainParmMountains_ROLLING_HILLS,
};

class Water;

////////////////////////////////////////////////////////////////////////////////
/// @brief Terrain class.
class Terrain : public Omni
{
private:
	PREVENT_COPYING(Terrain)
	typedef Omni Parent;

public:
						Terrain( QuadrantPtrConst q, SafePtr<Water> water );
						~Terrain();
	fp					GetDistance( void );
	void				FinalConstruction( void ) { }
	bool				Reproducible( void ) { return true; }
	void				Draw( void );
	const string		GetName( void ) { return string("Terrain"); }

protected:
	// Support for drawing Omnis only once per frame (TODO per-view).
	uint			GetFrameDrawn( void ) { return msFrameDrawn; }
	void			SetFrameDrawn( uint frame ) { msFrameDrawn = frame; }
	static uint		msFrameDrawn;

private:
	void				InitStatics( void );
	void				DrawFlatLand( void );
	void				MakeRollingHills( QuadrantPtrConst q, SafePtr<Water> water );
	void				MakeTrees( QuadrantPtrConst q, SafePtr<Water> water );
	static bool			mInit;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief RollingHill class.
class RollingHill : public ObjectVisExt<FixedPolymorph>
{
private:
	PREVENT_COPYING(RollingHill)
	typedef ObjectVisExt<FixedPolymorph> Parent;

public:
						RollingHill( QuadrantPtrConst q, const Position& pos, int width1, int width2 );
						~RollingHill();
	void				FinalConstruction( void );
	void				Draw( void );
	const string		GetName( void ) { return string("RollingHill"); }

	uint				GetVertexCnt( void ) { return mMesh[GetLodObj()].mVertexCnt; } // per mesh
	const WorldVertex*	GetWorldVertexs( void );										 // per mesh

    const WorldVertex*  GetHilltopVertex( const WorldVertex* vw )
						{
							int vertexCntSqrt = mMesh[GetLodObj()].mVertexCntSqrt;
							return &vw[ vertexCntSqrt/2*vertexCntSqrt + vertexCntSqrt/2 ];
						}
	bool				IfHugeMountain( const WorldVertex* v );
	bool				IfHillTop( int vi );

	void SetVertexCnt( uint vcnt ) { }				// OBJECT NOP
	void SetWorldVertexs( WorldVertex* wv ) { }		// OBJECT NOP

private:
	void				MakeMesh( void );
	PolygonList*		MakePolygonList( eLodObj lod, const int vertexCntSqrt, const int vertexCnt );
    void                MakeTrees( void );
    void                DrawTrees( void );

	// Has a mesh for each LOD.
	struct RollingHillMesh
	{
		int				mDeg1inc;
		int				mDeg2inc;
		int				mVertexCntSqrt;
		int				mVertexCnt;
		PolygonList*	mPolygonList;		// instances will use PolygonList() copy constructor
	};
	static RollingHillMesh	mMesh[eLodObj_LEVELS];
	static bool				mMadeMesh;
	int						mWidth1;
	int						mWidth2;
	uint8					mJaggedPeak;
    Dlist<Object>           mTreeDlist;
};

////////////////////////////////////////////////////////////////////////////////
/// @brief Tree class.
class Tree : public FixedData
{
private:
	PREVENT_COPYING(Tree)
	typedef FixedData Parent;
	enum				{ TREE_VERTEX_CNT = 8, TREE_SPECIES_MAX = 50 };

public:
						Tree( QuadrantPtrConst q, const Position& pos, const string& speciesName = "" );
						~Tree();
	void				FinalConstruction( void );
	void				Draw( void );
	const string		GetName( void ) { return string("Tree"); }
	uint				GetVertexCnt( void ) { return TREE_VERTEX_CNT; }
	const WorldVertex*	GetWorldVertexs( void );

	void SetVertexCnt( uint vcnt ) { }				// OBJECT NOP
	void SetWorldVertexs( WorldVertex* wv ) { }		// OBJECT NOP
	uint GetPolygonCnt( void ) { return 0; }		// OBJECT NOP

private:
	// A tree is drawn using two intersecting texture quads (TexBiquad).
	struct TreeSpecies
	{
		TexBiquad	mTexBiquad;
		fp			mWidth, mHeight, mWidthHalf, mHeightHalf;
	};
	// mSpecies[] is a C array: a STL vector can't be used
	// since TexBiquad lacks a copy constructor.
	static TreeSpecies	mSpecies[TREE_SPECIES_MAX];		///< defines different tree species (textures, geoms)
	static uint			mSpeciesCnt;
	static std::map<string,uint> mSpeciesName;			///< maps species name to mWhich index
	static WorldVertex	mWorldVertexs[TREE_VERTEX_CNT];	///< recomputed to save memory
	uint8				mWhich;							///< which tree species (mSpecies[] index)
};

////////////////////////////////////////////////////////////////////////////////
// Pacify the tree huggers ;-)
class TreeUnreproducible : public Tree
{
	PREVENT_COPYING(TreeUnreproducible)
public:
   	TreeUnreproducible( QuadrantPtrConst q, const Position& pos, const string& speciesName = "" ) : Tree(q,pos,speciesName) { }
	bool Reproducible( void ) { return false; }
};

#endif // MOD_PONY_TERRAIN_HH
#endif // COMPILING_MODULE_PONY
