#ifndef _3DMODEL_H_
#define _3DMODEL_H_

#include "ps2matrix4x4.h"
#include "texture.h"

class Model
{
public:
	//	Stucture used to define a mesh
	struct Mesh
	{
		int m_materialIndex;		// Material[m_materialIndex] is used for this mesh
		int m_numTriangles;			// Number of triangles in this mesh
		int * m_pTriangleIndices;	// m_pTriangleIndices[0->(m_numTriangles-1)] are the mesh triangles

		Mesh()
		{
			m_materialIndex = 0;
			m_numTriangles = 0;
			m_pTriangleIndices = 0;
		}
	};

	//	Material properties
	struct Material
	{
		float m_ambient[4]; 		// Property
		float m_diffuse[4];			// Property
		float m_specular[4];		// Property
		float m_emissive[4];		// Property
		float m_shininess;			// Property
		unsigned int m_texture;		// Not used
		char * m_pTextureFilename;	// Pointer to name of the texture file
		
		Material()
		{
			m_pTextureFilename = 0;
			m_texture = 0;
		}	
	};

	//	Triangle structure
	struct Triangle
	{
		float m_vertexNormals[3][3];	// Triangle normals
		float m_s[3], m_t[3];			// Texture coordinates
		int m_vertexIndices[3];			// Indices into vertex array
	};

	//	Vertex structure
	struct Vertex
	{
		char m_boneID;					// For skeletal animation
		float m_location[3];			// (x,y,z) position
	};

public:

	Model();
	virtual ~Model();

	virtual bool loadModelData( const char * filename, bool bTransparent = false, bool bWireFrame = false) = 0;
	
	virtual void Render(void) = 0;
	
	virtual void UploadTextures(void) = 0;

	void SetWorldMatrix(const Matrix4x4 & matWorld);

	void SetWVPMatrix(const Matrix4x4 & matWVP);

protected:

	virtual bool InitialiseDMA(bool bTransparent, bool bWireFrame) = 0;
	
	virtual	bool InitialiseTextures(void) = 0;

	//	No of Meshes used
	int m_numMeshes;
	Mesh * m_pMeshes;

	//	No of Materials used
	int m_numMaterials;
	Material * m_pMaterials;

	//	No of Triangles used
	int m_numTriangles;
	Triangle * m_pTriangles;

	//	No of Vertices Used
	int m_numVertices;
	Vertex * m_pVertices;
	
	//	No of Textures Used
	int m_numTextures;
	CTexture * m_pTextures;
	
	// The world and WorldViewProjection Matrices
	Matrix4x4 m_World, m_WVP;

	bool m_bWorldLoaded;
	
	// One of these needed for each mesh
	int * m_pStaticAddr;
};




class MilkshapeModel : public Model
{
public:
	MilkshapeModel();
	virtual ~MilkshapeModel();

	virtual bool loadModelData( const char * filename, bool bTransparent = false, bool bWireFrame = false);
	
	virtual void Render(void);
	
	virtual void UploadTextures(void);
	
protected:

	virtual bool InitialiseDMA(bool bTransparent, bool bWireFrame);
	
	virtual bool InitialiseTextures(void);
};

#endif // ndef _3DMODEL_H_
