// Ограничения реализации.

// Внутри описания материалов может быть только одна карта - либо диффузная,
// либо отражения. Поддерживаются три типа материалов: нетекстурированный -
// без карты, текстурированный - с диффузной картой, и хромовый - с картой
// отражения. При загрузке читается файл с текстурой (tga или bmp) b по полю
// MAP_AMOUNT создается альфа - канал. Готовая текстура сохраняется в
// файл "*.tga". Если у объекта нет поля MATERIAL_REF, (и есть поле 
// WIREFRAME_COLOR), то создается новый нетекстурированный материал.

#define DSMAX_MATERIAL_NAME     32
#define DSMAX_TEXTURE_NAME      32

#define	MAX_TMAP_NAME	32

/*
 * Note: we won't store image data in 'tmap' object. Instead,
 * vglLoadTMap() calls glGenTextures() and than downloads image
 * to OpenGL server. So, in vglReloadTMap() we need to load image
 * again and than call glTexSubimage2D() for existing texture object.
 */
typedef   struct tmap_s
{
	char	name[MAX_TMAP_NAME];
	struct	{
		char	name[MAX_TMAP_NAME];
		u32_t	width, height;
		vec_t	amount;					/* alpha channel: from 0 to 255 */
		GLuint	object;
	}	bitmap;
	struct	{
		vboolean identity;		/* == 1 if 'transform' is unit matrix */
		vec_t   uoffset, voffset;
		vec_t   angle;
		vec_t   uscale, vscale;	/* reciprocal to utile and vtile, respectively */
		GLfloat transform[4][4];
	}	wrap;
}	tmap_t, *tmap_p;


typedef   struct material_s
{
  char    *name;
  byte    ambient[4];
  byte    diffuse[4];
  byte    specular[4];
  vec_t   specular_power;
  vec_t   transparency;
  vec_t   selfillum;
  texture_map_t *diffuse_map;
  texture_map_t *reflection_map;
} material_t, *material_p;

typedef   struct triangle_s
{
  int     mtlid;
  int     vtx[3];
} triangle_t, *triangle_p;

typedef   struct mesh_vertices_s
{
  vec3_t  *vtx;
} mesh_vertices_t, *mesh_vertices_p;

typedef   struct mesh_faces_s
{
  triangle_t *tri;
} mesh_faces_t, *mesh_faces_p;

typedef   struct mesh_normals_s
{
  vec3_t *nrm;
} mesh_normals_t, *mesh_normals_p;

typedef   struct mesh_s
{
  int     numvertex;
  int     numfaces;
  int     numtvertex;
  int     numcvertex;
  int     numnormals;
  mesh_vertices_t *vlist;
  mesh_faces_t  *flist;
  mesh_vertices_t *tlist;
  mesh_vertices_t *clist;
  mesh_normals_t *facenormals;
  mesh_normals_t *vertexnormals;
} mesh_t, *mesh_p;

typedef  struct geomobject_s
{
  char *name;
  char *parent;
  mesh_p *mesh;
  uboolean inherit_pos, inherit_rot, inherit_scl;
  int tm_row[4];
  vec_t tm_pos, tm_rotaxis, tm_rotangle, tm_scale, tm_scaleaxis, tm_scaleaxisang;
} geomobject_t, *geomobject_p;

typedef enum
{
  DSMAX_INVALID_TOKEN = 0,
  DSMAX_ASCIIEXPORT,
  COMMENT,
  SCENE,
  SCENE_FILENAME,
  SCENE_FIRSTFRAME,
  SCENE_LASTFRAME,
  SCENE_FRAMESPEED,
  SCENE_TICKSPERFRAME,
  SCENE_BACKGROUND_STATIC,
  SCENE_AMBIENT_STATIC,

  MATERIAL_LIST,
  MATERIAL_COUNT,
  MATERIAL,
  MATERIAL_NAME,
  MATERIAL_CLASS,
  MATERIAL_AMBIENT,
  MATERIAL_DIFFUSE,
  MATERIAL_SPECULAR,
  MATERIAL_SHINE,
  MATERIAL_SHINESTRENGTH,
  MATERIAL_TRANSPARENCY,
  MATERIAL_WIRESIZE,
  MATERIAL_SHADING,
  MATERIAL_XP_FALLOFF,
  MATERIAL_SELFILLUM,
  MATERIAL_FALLOFF,
  MATERIAL_SOFTEN,
  MATERIAL_XP_TYPE,

  MAP_GENERIC,
  MAP_DIFFUSE,
  MAP_REFLECT,
  MAP_NAME,
  MAP_CLASS,
  MAP_SUBNO,
  MAP_AMOUNT,
  BITMAP,
  MAP_TYPE,
  UVW_U_OFFSET,
  UVW_V_OFFSET,
  UVW_U_TILING,
  UVW_V_TILING,
  UVW_ANGLE,
  
  GEOMOBJECT,
  NODE_NAME,
  
  NODE_TM,
  INHERIT_POS,
  INHERIT_ROT,
  INHERIT_SCL,
  TM_ROW0,
  TM_ROW1,
  TM_ROW2,
  TM_ROW3,
  TM_POS,
  TM_ROTAXIS,
  TM_ROTANGLE,
  TM_SCALE,
  TM_SCALEAXIS,
  TM_SCALEAXISANG,
  
  MESH,
  TIMEVALUE,
  MESH_NUMVERTEX,
  MESH_NUMFACES,
  MESH_VERTEX_LIST,
  MESH_VERTEX,
  MESH_FACE_LIST,
  MESH_FACE,
  MESH_SMOOTHING,
  MESH_MTLID,
  MESH_NUMTVERTEX,
  MESH_TVERTLIST,
  MESH_TVERT,
  MESH_NUMTVFACES,
  MESH_TFACELIST,
  MESH_TFACE,
  MESH_NUMCVERTEX,
  MESH_NORMALS,
  MESH_FACENORMAL,
  MESH_VERTEXNORMAL,
  
  PROP_MOTIONBLUR,
  PROP_CASTSHADOW,
  PROP_RECVSHADOW,
  WIREFRAME_COLOR,
  MATERIAL_REF,
  
  MAX_LAST_TOKEN
  
} dsmax_token_t;

typedef struct
{
  dsmax_token_t id;
  char *value;
} dsmax_token_pair;

// Этот массив должен быть отсортирован так, чтобы наиболее часто 
// встречающиеся ключевые слова шли первыми

static dsmax_token_pair dsmax_tokens[] =
{
	{MESH_FACE,							"*MESH_FACE"},
    {MESH_SMOOTHING,					"*MESH_SMOOTHING"},
    {MESH_MTLID,						"*MESH_MTLID"},
    {MESH_TFACE,						"*MESH_TFACE"},
    {MESH_VERTEX,						"*MESH_VERTEX"},
    {MESH_TVERT,						"*MESH_TVERT"},
    {MESH_VERTEXNORMAL,					"*MESH_VERTEXNORMAL"},
    {MESH_FACENORMAL,					"*MESH_FACENORMAL"},
  
    {MATERIAL_NAME,						"*MATERIAL_NAME"},
    {MATERIAL_CLASS,					"*MATERIAL_CLASS"},
    {MATERIAL_AMBIENT,					"*MATERIAL_AMBIENT"},
    {MATERIAL_DIFFUSE,					"*MATERIAL_DIFFUSE"},
    {MATERIAL_SPECULAR,					"*MATERIAL_SPECULAR"},
	{MATERIAL_SHINE,					"*MATERIAL_SHINE"},
	{MATERIAL_SHINESTRENGTH,			"*MATERIAL_SHINESTRENGTH"},
    {MATERIAL_TRANSPARENCY,				"*MATERIAL_TRANSPARENCY"},
    {MATERIAL_WIRESIZE,					"*MATERIAL_WIRESIZE"},
    {MATERIAL_SHADING,					"*MATERIAL_SHADING"},
    {MATERIAL_XP_FALLOFF,				"*MATERIAL_XP_FALLOFF"},
    {MATERIAL_SELFILLUM,				"*MATERIAL_SELFILLUM"},
    {MATERIAL_FALLOFF,					"*MATERIAL_FALLOFF"},
    {MATERIAL_SOFTEN,					"*MATERIAL_SOFTEN"},
    {MATERIAL_XP_TYPE,					"*MATERIAL_XP_TYPE"},
    {NODE_NAME,							"*NODE_NAME"},
    {NODE_TM,							"*NODE_TM"},
    {INHERIT_POS,						"*INHERIT_POS"},
    {INHERIT_ROT,						"*INHERIT_ROT"},
    {INHERIT_SCL,						"*INHERIT_SCL"},
    {TM_ROW0,							"*TM_ROW0"},
    {TM_ROW1,							"*TM_ROW1"},
    {TM_ROW2,							"*TM_ROW2"},
    {TM_ROW3,							"*TM_ROW3"},
    {TM_POS,							"*TM_POS"},
    {TM_ROTAXIS,						"*TM_ROTAXIS"},
    {TM_ROTANGLE,						"*TM_ROTANGLE"},
    {TM_SCALE,							"*TM_SCALE"},
    {TM_SCALEAXIS,						"*TM_SCALEAXIS"},
    {TM_SCALEAXISANG,					"*TM_SCALEAXISANG"},
    {MAP_NAME,							"*MAP_NAME"},
    {MAP_CLASS,							"*MAP_CLASS"},
    {MAP_SUBNO,							"*MAP_SUBNO"},
    {MAP_AMOUNT,						"*MAP_AMOUNT"},
    {BITMAP,							"*BITMAP"},
    {MAP_TYPE,							"*MAP_TYPE"},
    {UVW_U_OFFSET,						"*UVW_U_OFFSET"},
    {UVW_V_OFFSET,						"*UVW_V_OFFSET"},
    {UVW_U_TILING,						"*UVW_U_TILING"},
    {UVW_V_TILING,						"*UVW_V_TILING"},
    {UVW_ANGLE,							"*UVW_ANGLE"},
    {GEOMOBJECT,						"*GEOMOBJECT"},
    {MATERIAL_LIST,						"*MATERIAL_LIST"},
    {MATERIAL_COUNT,					"*MATERIAL_COUNT"},
    {MATERIAL,							"*MATERIAL"},
    {MAP_GENERIC,						"*MAP_GENERIC"},
    {MAP_DIFFUSE,						"*MAP_DIFFUSE"},
    {MAP_REFLECT,						"*MAP_REFLECT"},
    {MESH,								"*MESH"},
    {TIMEVALUE,							"*TIMEVALUE"},
    {MESH_NUMVERTEX,					"*MESH_NUMVERTEX"},
    {MESH_NUMFACES,						"*MESH_NUMFACES"},
    {MESH_VERTEX_LIST,					"*MESH_VERTEX_LIST"},
    {MESH_FACE_LIST,					"*MESH_FACE_LIST"},
    {MESH_NUMTVERTEX,					"*MESH_NUMTVERTEX"},
    {MESH_TVERTLIST,					"*MESH_TVERTLIST"},
    {MESH_NUMTVFACES,					"*MESH_NUMTVFACES"},
    {MESH_TFACELIST,					"*MESH_TFACELIST"},
    {MESH_NUMCVERTEX,					"*MESH_NUMCVERTEX"},
    {MESH_NORMALS,						"*MESH_NORMALS"},
    {PROP_MOTIONBLUR,					"*PROP_MOTIONBLUR"},
    {PROP_CASTSHADOW,					"*PROP_CASTSHADOW"},
    {PROP_RECVSHADOW,					"*PROP_RECVSHADOW"},
    {WIREFRAME_COLOR,					"*WIREFRAME_COLOR"},
    {MATERIAL_REF,						"*MATERIAL_REF"},
    {SCENE_FILENAME,					"*SCENE_FILENAME"},
    {SCENE_FIRSTFRAME,					"*SCENE_FIRSTFRAME"},
    {SCENE_LASTFRAME,					"*SCENE_LASTFRAME"},
    {SCENE_FRAMESPEED,					"*SCENE_FRAMESPEED"},
    {SCENE_TICKSPERFRAME,				"*SCENE_TICKSPERFRAME"},
    {SCENE_BACKGROUND_STATIC,			"*SCENE_BACKGROUND_STATIC"},
    {SCENE_AMBIENT_STATIC,				"*SCENE_AMBIENT_STATIC"},
    {MAX_ASCIIEXPORT,					"*3DSMAX_ASCIIEXPORT"},
    {COMMENT,							"*COMMENT"},
    {SCENE,								"*SCENE"},
  
    {DSMAX_LAST_TOKEN,""}
};

#include <stdio.h>
#include <string.h>

dsmax_token_t dsmaxFindToken(char *token)
{
	int i=0;
	while(dsmax_tokens[i].id != DSMAX_LAST_TOKEN)
		if(!strcmp(dsmax_tokens[i].value,token)) 
			return dsmax_tokens[i].id;
	return DSMAX_INVALID_TOKEN;
}

typedef struct
{
	int a,b,c;        // vertex indices
	int mtl_id;       // material identifier
}	dsmax_face_t;

static dsmax_face_t *AllocFaces(int num)
{
  return (dsmax_face_t*)malloc(num*sizeof(dsmax_face_t));
}

vboolean V_LOCAL dsmaxLoadMap();
vboolean V_LOCAL dsmaxLoadMaterial();
vboolean V_LOCAL dsmaxLoadMaterialList();
vboolean V_LOCAL dsmaxLoadNodeTM();

vboolean V_LOCAL dsmaxLoadVertexList(vec3_t *dest,int n,tokenizer_t *src);
vboolean V_LOCAL dsmaxLoadFaceList(dsmax_face_t *dest,int n,tokenizer_t *src);

vboolean V_LOCAL dsmaxLoadTextureVertexList();
vboolean V_LOCAL dsmaxLoadTextureFaceList();
vboolean V_LOCAL dsmaxLoadNormals();
vboolean V_LOCAL dsmaxLoadMesh();
vboolean V_LOCAL dsmaxLoadGeomObject();
vboolean V_LOCAL dsmaxLoadScene();
