/*    

	Wavefront OBJ model reader


	This reader is based on:

	  -----------------------------------------------------------------
      Wavefront OBJ model file format reader/writer/manipulator.

      glm.c
      Nate Robins, 1997, 2000
      nate@pobox.com, http://www.pobox.com/~nate
 	  -----------------------------------------------------------------

	Modifications by Carsten Dachsbacher:

	- clean ups, optimizations
	- Direct3D 9 Rendering
	- Reads now non-100%-standard OBJs

*/
#ifndef __OBJ__H
#define __OBJ__H

#include <d3dx9.h>
#include "vertex3dop.h"

// none or material or color:	--- / --- / diffuse
// none or flat or smooth:		--- / nrml / nrml
// none or texture:				--- / tex
#define RENDER_MATERIAL			0x01
#define RENDER_DIFFUSE_COLOR	0x02

#define RENDER_FLAT_SHADED		0x04
#define RENDER_SMOOTH_SHADED	0x08

#define RENDER_TEXTURE_COORDS	0x10

#define RENDER_TANGENT_SPACE_UV	0x20

// OBJMaterial: structure that defines a material in a model. 
typedef struct _OBJmaterial
{
	char			*name;
	D3DMATERIAL9	data;
} OBJMaterial;

// OBJtriangle: structure that defines a triangle in a model.
typedef struct _OBJtriangle 
{
	DWORD idxV[3];		// vertex indices
	DWORD idxN[3];      // normal indices
	DWORD idxT[3];      // tex coord indices
	DWORD idxFN;        // index of face normal
	float area;			// size of triangle
} OBJtriangle;

typedef struct _OBJgroup 
{
	char		*name;				// name
	DWORD		nTriangles;			// #triangles in this group
	DWORD		*pTriangleList;     // ptr to triangle list
	DWORD		material;			// index to material for group
	struct _OBJgroup* next;         // ptr to next group in model
} OBJgroup;

//
// class OBJmodel: reads and renders OBJ models
//
class OBJmodel
{
	private:
	protected:
		char			*pathname;			// path of file
		char			*mtllibname;        // name of material library
		
		DWORD			nVertices;			// #vertices
		VERTEX3D		*pVertexList;       // ptr vertex list
		
		DWORD			nNormals;           // #normals
		VERTEX3D		*pNormalList;       // ptr normal list

		DWORD			nSpaces;            // #spaces
		VERTEX3D		*pTangentList;
		VERTEX3D		*pBinormalList;
		
		DWORD			nTexCoords;         // #texcoords
		float			*pTexCoordList;     // ptr texcoord list
		
		DWORD			nFaceNormals;       // #facenormals
		VERTEX3D		*pFaceNormalList;   // ptr to face normal list
		
		DWORD			nTriangles;			// #triangles
		OBJtriangle		*pTriangleList;     // ptr to triangle list
		
		DWORD			nMaterials;			// #materials
		OBJMaterial		*pMaterialList;     // ptr to material list
		
		DWORD			nGroups;			// #groups
		OBJgroup		*pGroupList;        // linked list of groups
		
		// Direct3D 9 Stuff
		LPDIRECT3DVERTEXBUFFER9	pMeshVB;
		DWORD			fvfMeshVertex;
		DWORD			sizePerVertex;
		DWORD			currentMode;

		// protected methods
		OBJgroup		*objFindGroup( char *name );
		OBJgroup		*objAddGroup( char *name );
		DWORD			objFindMaterial( char *name );
		void			objReadMTL( char *name );
		void			objFirstPass( FILE *file );
		void			objSecondPass( FILE *file );
	public:
		OBJmodel();
		~OBJmodel();

		// read OBJ file
		int				readOBJ( char *filename );

		// calculate face normals
		void			calcFaceNormals();

		// calculate vertex normals
		void			calcVertexNormals();

		// scale to unit size
		void			scaleIsotropic();

		// build D3D9 vertex buffer for model
		void			buildVertexBuffer( LPDIRECT3DDEVICE9 pD3DDevice, int mode );

		// render model with D3D9
		void			drawModel( LPDIRECT3DDEVICE9 pD3DDevice );

		int				getNVertices() { return nVertices; };
		int				getNTriangles() { return nTriangles; };
};


#endif