/* Universidade Federal Fluminense
 * Programa de Pós-Graduação em Computação
 *
 * Tópicos Avançados em Computação Visual e Interfaces II (Técnicas Avançadas de Rendering)
 * Professor: Leandro Augusto Frata Fernandes
 *
 * Version: 2012.05.16-001
 */

#ifndef _GEOMETRY_HEADER_
#define _GEOMETRY_HEADER_

// Include the Standard Template Library (STL).
#include <vector>

// Include some custom definitions.
#include "object.h"

// The vertex data structure.
struct VertexData {
	coord4f vertex;
	coord3f normal;
	texcoord2f texCoord0;
	coord3f tangent;
	coord3f bitangent;
};

// The superclass of some geometry.
class Geometry {
public:

	inline const std::vector<unsigned short>& getIndices() const { return m_indices; }
	inline const std::vector<VertexData>& getVertices() const { return m_vertices; }

protected:

	std::vector<unsigned short> m_indices;
	std::vector<VertexData> m_vertices;
};

// The geometry of a simple quad.
class QuadGeometry : public Geometry {
public:

	QuadGeometry();
};

// The geometry of a simple sphere.
class SphereGeometry : public Geometry {
public:

	SphereGeometry(const GLuint& nRings, const GLuint& nSegments);
};

// The superclass of some drawable geometry.
class DrawableGeometry {
public:

	DrawableGeometry(const Geometry* geometry);

public:

	virtual void initSpecial() = NULL;
	virtual void draw() const = NULL;
	virtual void freeSpecial() = NULL;

public:

	inline const Geometry& getGeometry() const { return *m_geometry; }
	
	inline const std::vector<unsigned short>& getIndices() const { return m_geometry->getIndices(); }
	inline const std::vector<VertexData>& getVertices() const { return m_geometry->getVertices(); }

private:

	const Geometry* m_geometry;
};

// Some drawable object.
class DrawableObject : public Object {
public:

	DrawableObject(DrawableGeometry* drawableGeometry);
	DrawableObject(const coord3f& location, const coord3f& forwardDirection, const coord3f& upDirection, DrawableGeometry* drawableGeometry);

public:

	inline const DrawableGeometry& getDrawableGeometry() const { return *m_drawableGeometry; }
	inline const Geometry& getGeometry() const { return m_drawableGeometry->getGeometry(); }

	inline const std::vector<unsigned short>& getIndices() const { return m_drawableGeometry->getIndices(); }
	inline const std::vector<VertexData>& getVertices() const { return m_drawableGeometry->getVertices(); }

	inline void initSpecial() { m_drawableGeometry->initSpecial(); }
	inline void draw() const { m_drawableGeometry->draw(); }
	inline void freeSpecial() { m_drawableGeometry->freeSpecial(); }

private:

	DrawableGeometry* m_drawableGeometry;
};

#endif // _GEOMETRY_HEADER_
