/*****************************************************************************

File: VertexBuffer.h
Desc: The buffer that keeps the geometry data
		
Date: 2005/01/01

Author: Wim Lemkens

*****************************************************************************/

#ifndef VERTEXBUFFER_H
#define VERTEXBUFFER_H

#include "Vertex.h"
#include "Vector2i.h"
#include "ClipmapConfig.h"

#include <stdlib.h>
#include <vector>

namespace Ogre {

class VertexBuffer{
public:

	/**
	 * The constructor of the buffer with the depth of the geometry
	 * @param	int depth
	 * 			The depth of the real geometry (not synthesised)
	 */
	VertexBuffer(int depth);
	virtual ~VertexBuffer();
	
	/**
	 * Returns true if the given vertex is loaded in the buffer
	 */
	bool isInBuffer(int x, int y, int level) const;
	
	/**
	 * Returns a point to the given vertex
	 * @pre		The vertex has to be in the buffer
	 */
	Vertex* getVertex(int x, int y, int level) const;

	/**
	 * Puts a vertex in the buffer. Moves the buffer if needed
	 */
	void put(Vertex* vertex, int x, int y, int level);
	
	/**
	 * Return the width in vertices of the given level
	 */
	long getLevelSize(int level) const;
	
	/**
	 * Returns the depth of the vertex buffer
	 */
	int getDepth(){
		return depth;
	}
	
protected:

	/**
	 * The buffer of vertices. A list of vertices grouped by level
	 */
	std::vector<Vertex**> vertexTree;
	/**
	 * A bitmap with flags to mark which vertex is already in memory
	 */
	std::vector<bool*> vertexLoaded;
	/**
	 * The upper left coordinates of the first vertex in the buffer relative
	 * to the general level of detail
	 */
	std::vector<Vector2i> bufferPosition;
	/**
	 * The position in the buffer where the first vertex (the upper left) is
	 */
	std::vector<int> bufferStart;

	/**
	 * Expand the vertexBuffer until the given number of levels is reached
	 */
	void createLevel(int level, int x=0, int y=0);
	
	/**
	 * Returns true if the given vertex is in the borders of the buffer
	 */
	bool isInBufferBorders(int x, int y, int level) const;
	
	/**
	 * Converts the given lodcoordinates to coordinates in the buffer
	 */
	void convertToRelative(int &x, int &y, int &level) const;

	/**
	 * Moves the buffer so the given vertex is in its borders
	 */	
	void moveBufferFor(int x, int y, int level);
	
	/**
	 * Removes a vertex from the buffer
	 */
	void unloadVertex(int x, int y, int level);
	
	/**
	 * The number of levels in real geometry (not proceduraly generated) in the
	 * geometry
	 */
	int depth;
	
	/**
	 * Marks a vertex as being in the buffer
	 */
	void setVertexInMemory(int x, int y, int level);
	
	/**
	 * Marks a vertex as not being in the buffer
	 */
	void setVertexOutMemory(int x, int y, int level);

	/**
	 * Returns true if the vertex in the borders of its lod
	 */
	bool isInLevelBorders(int x, int y, int level) const;

	/**
	 * Returns the position in the buffer of the vertex given in coordinates 
	 * relative to the complete level of detail
	 */
	int getPositionInBuffer(int x, int y, int level) const;

	/**
	 * Returns the position in the buffer of the vertex given in coordinates 
	 * relative to the level of detail in the buffer
	 */
	int getRelativePositionInBuffer(int x, int y, int level) const;
	
};

#endif // VERTEXBUFFER_H

} // namespace Ogre
