#define MD2_MAX_TRIANGLES		4096
#define MD2_MAX_VERTICES		2048
#define MD2_MAX_TEXCOORDS		2048
#define MD2_MAX_FRAMES			512
#define MD2_MAX_SKINS			32
//(MD2_MAX_VERTICES * 4 + 128)
//2048*4+128=8320
#define MD2_MAX_FRAMESIZE		8320

struct md2_header_t
{
   int magic;
   int version;
   int skinWidth;
   int skinHeight;
   int frameSize;
   int numSkins;
   int numVertices;
   int numTexCoords;
   int numTriangles;
   int numGlCommands;
   int numFrames;
   int offsetSkins;
   int offsetTexCoords;
   int offsetTriangles;
   int offsetFrames;
   int offsetGlCommands;
   int offsetEnd;
};

struct  md2_alias_triangleVertex_t
{
   byte vertex[3];
   byte lightNormalIndex;
};

struct md2_triangleVertex_t
{
   float vertex[3];
   float normal[3];
};

struct md2_triangle_t
{
   short vertexIndices[3];   //short это 2 байта
   short textureIndices[3];
};

struct md2_textureCoordinate_t
{
   short s, t;
};

struct md2_alias_frame_t
{
   float scale[3];
   float translate[3];
   char name[16];
   md2_alias_triangleVertex_t alias_vertices[1];
};

struct md2_frame_t
{
   char   name[16];
   DWORD  vertices;      //md2_triangleVertex_t
};


struct md2_glCommandVertex_t
{
   float s, t;
   int vertexIndex;
};


struct skin_t
{
char md2_skin_t[64];
};


struct md2_model_t
{
	md2_header_t		header;
	DWORD	        	skins;          //skin_t
	DWORD           	texCoords;      //md2_textureCoordinate_t
	DWORD	  		triangles;      //md2_triangle_t
	DWORD		        frames;         //md2_frame_t
	int			glCommandBuffer;
};


struct animation_t
{
	char	nameAnimation[16];
	int		firstFrame;
	int		lastFrame;
};

struct md2_anim_t
{
	int	 count_anim;
	animation_t anim[MD2_MAX_FRAMES];

};



//===============================================================
//загрузка md2
md2_model_t md2_model;  //заголово md2


DWORD md2file=0;          //дескриптор файла
DWORD bytes_count=0;  //количество прочтенных байтов
DWORD i=0;
DWORD j=0;
DWORD LpUkazatel=0;
DWORD LpFrames=0;
DWORD LpFrame=0;
DWORD LpBufferFrame=0;
DWORD LpFrameName=0;
DWORD LpFramesVertices=0;

DWORD LpDestVertex0=0;
DWORD LpDestVertex1=0;
DWORD LpDestVertex2=0;

DWORD LpDestNormal0=0;
DWORD LpDestNormal1=0;
DWORD LpDestNormal2=0;

INT srcVertex0, srcVertex1, srcVertex2, srclightNormalIndex;
FLOAT srcScale0, srcScale1, srcScale2;
FLOAT srcTranslate0, srcTranslate1, srcTranslate2;
FLOAT resultat;
FLOAT minusOdin;
DWORD LpVertexByteSrc;

BOOLEAN q2_loadmodel()
{


//открываем файл
md2file=CreateFile(#model_name,GENERIC_READ,0,0,OPEN_EXISTING,0,0);
//в eax возвращается дескриптор открытого файла
IF (md2file==INVALID_HANDLE_VALUE) return FALSE;


//Читаем заголовок файла
ZeroMemory(#md2_model,sizeof(md2_model));    //обнуляем на самый случай структуру заголовка
ReadFile(md2file,#md2_model.header,sizeof(md2_model.header),#bytes_count,0);  //Читаем заголовок md2


//проверяем версию заголовка
IF (md2_model.header.magic!=0x32504449) return FALSE;   //"IDP2"=0x32504449
IF (md2_model.header.version != 8) return FALSE;

//		fseek(md2file, mdl->header.offsetSkins, SEEK_SET);


//ЧТЕНИЕ СКИНОВ========================================
//установка указателя чтения на , блоки Skins
//узнали смещение от начала файла в .md2 файле, где лежат нужные блоки
//устанавливаем указатель файла
SetFilePointer(md2file,md2_model.header.offsetSkins,0,FILE_BEGIN);
IF(EAX==INVALID_HANDLE_VALUE) return FALSE;
//Если все нормально то возвращеается новая позиция указателя файла

//		mdl->skins = (md2_skin_t *) malloc(sizeof(md2_skin_t) * mdl->header.numSkins);

EAX=sizeof(skin_t);
EBX=md2_model.header.numSkins;
EAX=EAX*EBX;
IF (EBX!=0) md2_model.skins=LocalAlloc(LPTR,EAX);


//------------
LpUkazatel=md2_model.skins;
FOR (i=0; i<md2_model.header.numSkins; i++)
      {
ReadFile(md2file,LpUkazatel,sizeof(skin_t),#bytes_count,0);
LpUkazatel+=sizeof(skin_t);
      }
//------------
//=КОНЕЦ ЧТЕНИЕ СКИНОВ================================================


//Чтение КООРДИНАТ ТЕКСТУРЫ===========================================
//		fseek(md2file, mdl->header.offsetTexCoords, SEEK_SET);
SetFilePointer(md2file,md2_model.header.offsetTexCoords,0,FILE_BEGIN);
IF(EAX==INVALID_HANDLE_VALUE) return FALSE;

//		mdl->texCoords = (md2_textureCoordinate_t *) malloc(sizeof(md2_textureCoordinate_t) * mdl->header.numTexCoords);
EAX=sizeof(md2_textureCoordinate_t);
EBX=md2_model.header.numTexCoords;
EAX=EAX*EBX;
IF (EBX!=0) md2_model.texCoords=LocalAlloc(LPTR,EAX);

//Загружаем координаты текстуры
//		for (i=0; i<mdl->header.numTexCoords; i++)
//			fread(&mdl->texCoords[i], sizeof(md2_textureCoordinate_t), 1, md2file);
LpUkazatel=md2_model.texCoords;
FOR (i=0; i<md2_model.header.numTexCoords; i++)
{
ReadFile(md2file,LpUkazatel,sizeof(md2_textureCoordinate_t),#bytes_count,0);
LpUkazatel+=sizeof(md2_textureCoordinate_t);
}
//=КОНЕЦ чтения КООРДИНАТ ТЕКСТУР=====================================



//ЧТЕНИЕ ИНДЕКСОВ ТРЕУГОЛЬНИКОВ =================================================
//		fseek(md2file, mdl->header.offsetTriangles, SEEK_SET);
SetFilePointer(md2file,md2_model.header.offsetTriangles,0,FILE_BEGIN);
IF(EAX==INVALID_HANDLE_VALUE) return FALSE;

//Выделяем память для FACES, индексы к треугольникам и текстурам
//		mdl->triangles = (md2_triangle_t *) malloc(sizeof(md2_triangle_t) * mdl->header.numTriangles);
EAX=sizeof(md2_triangle_t);
EBX=md2_model.header.numTriangles;
EAX=EAX*EBX;
IF (EBX!=0) md2_model.triangles=LocalAlloc(LPTR,EAX);

//подгружаем треугольники
//		for (i=0; i<mdl->header.numTriangles; i++)
//			fread(&mdl->triangles[i], sizeof(md2_triangle_t), 1, md2file);
LpUkazatel=md2_model.triangles;
FOR (i=0; i<md2_model.header.numTriangles; i++)
{
ReadFile(md2file,LpUkazatel,sizeof(md2_triangle_t),#bytes_count,0);
LpUkazatel+=sizeof(md2_triangle_t);
}
//КОНЕЦ ЧТЕНИЯ ИНДЕКСОВ ТРЕУГОЛЬНИКОВ ===========================================


//ЧТЕНИЕ КАДРОВ =========================================================
//		fseek(md2file, mdl->header.offsetFrames, SEEK_SET);
SetFilePointer(md2file,md2_model.header.offsetFrames,0,FILE_BEGIN);
IF(EAX==INVALID_HANDLE_VALUE) return FALSE;

//		mdl->frames = (md2_frame_t *) malloc(sizeof(md2_frame_t) * mdl->header.numFrames);
EAX=sizeof(md2_frame_t);
EBX=md2_model.header.numFrames;
EAX=EAX*EBX;
IF (EBX!=0) md2_model.frames=LocalAlloc(LPTR,EAX);
LpFrames=md2_model.frames;   //Текущий фрейм


//отводим место для данных одного фрейма
EAX=md2_model.header.frameSize;
LpBufferFrame=LocalAlloc(LPTR,EAX);

//ставим указатель на имя фрейма
LpFrameName=md2_model.frames;

for (i=1; i<md2_model.header.numFrames; i++)
	{
//md2_alias_frame_t *frame = (md2_alias_frame_t *) buffer;
//mdl->frames[i].vertices = (md2_triangleVertex_t *)
//malloc(sizeof(md2_triangleVertex_t) * mdl->header.numVertices);



EAX=sizeof(md2_triangleVertex_t);
EBX=md2_model.header.numVertices;
EAX=EAX*EBX;
//запоминаем указатель к текущему фрейму

IF (EBX!=0) LpFrame=LocalAlloc(LPTR,EAX);

EDX=LpFrames+#md2_frame_t.vertices;
#EDX=LpFrame;




//EAX=md2_model.header.frameSize; 7E8h=2024/44=46
//EAX=sizeof(frame);   2ch=44


//			fread(frame, 1, mdl->header.frameSize, md2file);
ReadFile(md2file,LpBufferFrame,md2_model.header.frameSize,#bytes_count,0);
//			strcpy(mdl->frames[i].name, frame->name);
EAX=LpBufferFrame+#md2_alias_frame_t.name;
strcpy(LpFrameName,EAX);
//               <- направление копирования


EDX=LpFrames+#md2_frame_t.vertices;
LpFramesVertices=#EDX;


//поставим указатель на первый байт исходной вершины
LpVertexByteSrc=LpBufferFrame+#md2_alias_frame_t.alias_vertices.vertex;


//srcScale0=DSDWORD[LpBufferFrame+#md2_alias_frame_t.scale];
srcScale0=DSFLOAT[LpBufferFrame+#md2_alias_frame_t.scale];
srcScale1=DSFLOAT[LpBufferFrame+#md2_alias_frame_t.scale+4];
srcScale2=DSFLOAT[LpBufferFrame+#md2_alias_frame_t.scale+4+4];

srcTranslate0=DSFLOAT[LpBufferFrame+#md2_alias_frame_t.translate];
srcTranslate1=DSFLOAT[LpBufferFrame+#md2_alias_frame_t.translate+4];
srcTranslate2=DSFLOAT[LpBufferFrame+#md2_alias_frame_t.translate+4+4];

			for (j=0; j<md2_model.header.numVertices; j++)

			{



//	mdl->frames[i].vertices[j].vertex[0] =
//(float) ((int) frame->alias_vertices[j].vertex[0]) *
//frame->scale[0] + frame->translate[0];

//LpFramesVertices=LpFrames+#md2_frame_t.vertices;

//адреса вершин
LpDestVertex0=LpFramesVertices+#md2_triangleVertex_t.vertex;
LpDestVertex1=LpDestVertex0+4;
LpDestVertex2=LpDestVertex1+4;
//адреса нормалей
LpDestNormal0=LpDestVertex2+4;
LpDestNormal1=LpDestNormal0+4;
LpDestNormal2=LpDestNormal1+4;


LpFramesVertices+=sizeof(md2_triangleVertex_t);

/*
struct md2_triangleVertex_t
{
   float vertex[3];
   float normal[3];
};
*/

/*
struct md2_alias_frame_t
{
   float scale[3];
   float translate[3];
   char name[16];
   md2_alias_triangleVertex_t alias_vertices[1];
};

struct  md2_alias_triangleVertex_t
{
   byte vertex[3];
   byte lightNormalIndex;
};

*/



srcVertex0=DSBYTE[LpVertexByteSrc];
$ INC LpVertexByteSrc;
srcVertex1=DSBYTE[LpVertexByteSrc];
$ INC LpVertexByteSrc;
srcVertex2=DSBYTE[LpVertexByteSrc];
$ INC LpVertexByteSrc;


srclightNormalIndex=DSBYTE[LpVertexByteSrc];
// провернуть еще на один байт lightNormalIndex
$ INC LpVertexByteSrc;


                        //получение реальных координат вершин
                        //resultat=srcVertex0*srcScale0+srcTranslate0;
			asm{
				fild srcVertex0
				fld  srcScale0
				fmul ST,ST(1)
				fld  srcTranslate0
				fadd ST,ST(1)
				fstp resultat
                                fstp ST(0)             //очистка стека
                                fstp ST(0)
				fwait
			}
                                DSFLOAT[LpDestVertex0]=resultat;

                        //resultat=-1 * (srcVertex1*srcScale1+srcTranslate1);
                        minusOdin=-1.0f;
			asm{
				fild srcVertex1
				fld  srcScale1
				fmul ST,ST(1)
				fld  srcTranslate1
				fadd ST,ST(1)
				fld  minusOdin
				fmul ST,ST(1)
				fstp resultat
                                fstp ST(0)             //очистка стека
                                fstp ST(0)
                                fstp ST(0)
				fwait
			}
                                DSFLOAT[LpDestVertex2]=resultat;

                        //resultat=srcVertex2*srcScale2+srcTranslate2;
			asm{
				fild srcVertex2
				fld  srcScale2
				fmul ST,ST(1)
				fld  srcTranslate2
				fadd ST,ST(1)
				fstp resultat
                                fstp ST(0)             //очистка стека
                                fstp ST(0)
				wait
			}
                                DSFLOAT[LpDestVertex1]=resultat;


//74.000000000000000000*0.1103776618838310272=8.167946979403+(-10.430895805358886912)=-2.262948825955
//DSDWORD [#background];
//EBX;
//EAX=float

//переходим на другую структуру md2_alias_frame_t
//LpBufferFrameChange+=sizeof(md2_alias_frame_t);


/*

				mdl->frames[i].vertices[j].normal[0] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][0];
				mdl->frames[i].vertices[j].normal[1] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][1];
				mdl->frames[i].vertices[j].normal[2] = avertexnormals[frame->alias_vertices[j].lightNormalIndex][2];
*/

//srclightNormalIndex*3+0
//srclightNormalIndex*3+1
//srclightNormalIndex*3+2

//EAX=#avertexnormals;      //базовый адрес  массива
//EAX=srclightNormalIndex;

resultat=DSFLOAT[srclightNormalIndex*12+#avertexnormals];
DSFLOAT[LpDestNormal0]=resultat;

resultat=DSFLOAT[srclightNormalIndex*12+4+#avertexnormals];
DSFLOAT[LpDestNormal1]=resultat;

resultat=DSFLOAT[srclightNormalIndex*12+4+4+#avertexnormals];
DSFLOAT[LpDestNormal2]=resultat;

// MATRIX[tileY * tilesX + tileX]=empty;
//DSDWORD[LpDestNormal0]=resultat;


			}


LpFrameName+=sizeof(md2_frame_t);
LpFrames+=sizeof(md2_frame_t);   //Переход к другому фрейму

	}


//КОНЕЦ ЧТЕНИЯ КАДРОВ ====================================================



//md2
//mdl=LocalAlloc(LPTR,sizeof(md2_model));  //Взяли память под заголовок md2
//LocalFree(mdl); //Освободили память от заголовок md2

CloseHandle(md2file);   //закрываем md2 файл

RETURN TRUE;
}
//=================================================================

