#include "loader3ds.h"

#include <wx/stream.h>
#include <wx/archive.h>

#include "object3d.h"
#include "mathTools.h"
#include "wxTools.h"
#include "texture.h"
//#include "tools/debug.h"

//#ifndef WX_PRECOMP
//  #include "wx/wx.h"
//#endif
//#define SEEK_START           1900
//#define SEEK_CURSOR          1901

// colors
#define COLOR_F             0x0010 //цвет задается как 3 x float
#define COLOR_24            0x0011 //цвет задается как 3 x unsigned char
#define LIN_COLOR_24        0x0012 //цвет задается как 4 x unsigned char
#define LIN_COLOR_F         0x0013 //цвет задается как 4 x float
// percentage
#define INT_PERCENTAGE      0x0030
#define FLOAT_PERCENTAGE    0x0031


#define MAIN3DS             0x4D4D //Main chunk, contains all the other chunks
	#define ID_VERSION          0x0002 //версия файла
	#define EDIT3DS             0x3D3D // this is the start of the editor config
		#define MESH_VERSION        0x3D3E
		// material entries
		#define MAT_ENTRY           0xAFFF //секция материалов
			#define MAT_NAME            0xA000
			#define MAT_AMBIENT         0xA010
			#define MAT_DIFFUSE         0xA020
			#define MAT_SPECULAR        0xA030
			#define MAT_SHININESS       0xA040
			#define MAT_SHIN2PCT        0xA041
			#define MAT_TRANSPARENCY    0xA050
			#define MAT_TRANSFALLOF     0xA052
			#define	MAT_REFLECTBLUR     0xA053
			#define	MAT_SELFILLUM       0xA084
			#define	MAT_TRANSFALLOFF    0xA08A
			#define MAT_SHADING         0xA100
			#define MAT_TWO_SIDE        0xA081
			#define MAT_ADDITIVE        0xA083
			#define MAT_WIRE            0xA085
			#define MAT_FACEMAP         0xA088
			#define MAT_WIRESIZE        0xA087 //always present, in case of forced wire rendering
			#define MAT_DECAL           0xA082
			#define MAT_TEXMAP          0xA200
				#define MAT_MAPNAME         0xA300 //названеи текстуры
				#define MAT_MAP_TILING      0xA351 //количество повторов текстуры по гориз. и вертик.
				#define MAT_MAP_TEXBLUR     0xA353 //Blur percent
				#define MAT_MAP_USCALE      0xA354
				#define MAT_MAP_VSCALE      0xA356
				#define MAT_MAP_UOFFSET     0xA358
				#define MAT_MAP_VOFFSET     0xA35A
				#define MAT_MAP_ANG         0xA35C
			#define MAT_TEX2MAP         0xA33A
			#define MAT_OPACMAP         0xA210
			#define MAT_BUMPMAP         0xA230
			#define MAT_SPECMAP         0xA204
			#define MAT_SHINMAP         0xA33C
			#define MAT_REFLMAP         0xA220
			#define MAT_ACUBIC          0xA310
		#define EDIT_CONFIG1        0x0100
		#define EDIT_OBJECT         0x4000
			#define OBJ_TRIMESH         0x4100
				#define TRI_VERTEXLIST      0x4110
				#define TRI_VERTEXOPTIONS   0x4111
				#define TRI_FACEMAPPING     0x4140
				#define TRI_FACELIST        0x4120 //Faces description
					#define TRI_MAT_GROUP       0x4130 //ASCII название материала
					#define TRI_SMOOTH_GROUP    0x4150 //Бит на n-ом месте указывает на вхождение грани в n-ую группу сглаживания (всего их понятно 32, столько сколько бит в целом без знака);
				#define TRI_LOCAL           0x4160 //Local coordinate system
				#define TRI_VISIBLE         0x4165 //Object color in editor
			#define OBJ_LIGHT           0x4600
			#define OBJ_CAMERA          0x4700
		#define EDIT_AMBIENT        0x2100// ambient light
	// keyframer chunk ids
	#define KFDATA              0xB000  // the keyframer section
		#define KFHDR               0xB00A //путь к файлу анимации или Viewport layout (Revision number SHORT)
		#define KFCURTIME           0xB009 //curframe
		#define FRAMES              0xB008 // Frames (Start and End)
		#define OBJECT_NODE_TAG     0xB002  //Mesh information block
			#define HIERARCHY           0xB030 // Hierarchy position
			#define NODE_HDR            0xB010 //Object name, parameters and hierarchy father
			#define PIVOT               0xB013 //Object pivot point
			#define POS_TRACK_TAG       0xB020 //Position track
			#define ROT_TRACK_TAG       0xB021 //Rotation track
			#define SCL_TRACK_TAG       0xB022 //Scale track



#define CAM_RANGES          0x4720

#define LIT_OFF             0x4620
#define LIT_SPOT            0x4610
#define LIT_INRANGE         0x4659
#define LIT_OUTRANGE        0x465A

#define SPOTLIGHT           0x4610

//------------------------------------------------------------------------------
struct LChunk
{
    unsigned short id;
    unsigned int len;
    unsigned int sum;
};
//------------------------------------------------------------------------------
/*unsigned long read_material_section ( TTriangles * p_object, FILE * l_file )
{
    // variables
    LChunk chunk;
    LChunk child;
    char str[30];
    LMaterial mat;
    short sh;

    GotoChunk(parent);

    chunk = ReadChunk();
    while (chunk.end <= parent.end)
    {
        switch (chunk.id)
        {
        case MAT_NAME:
            ReadASCIIZ(str, 30);
            mat.SetName(str);
            break;
        case MAT_AMBIENT:
            child = ReadChunk();
            mat.SetAmbientColor(ReadColor(child));
            break;
        case MAT_DIFFUSE:
            child = ReadChunk();
            mat.SetDiffuseColor(ReadColor(child));
            break;
        case MAT_SPECULAR:
            child = ReadChunk();
            mat.SetSpecularColor(ReadColor(child));
            break;
        case MAT_SHININESS:
            child = ReadChunk();
            mat.SetShininess(ReadPercentage(child));
            break;
        case MAT_TRANSPARENCY:
            child = ReadChunk();
            mat.SetTransparency(ReadPercentage(child));
            break;
        case MAT_SHADING:
            sh = ReadShort();
            switch (sh)
            {
            case 0:
                mat.SetShadingType(sWireframe);
                break;
            case 1:
                mat.SetShadingType(sFlat);
                break;
            case 2:
                mat.SetShadingType(sGouraud);
                break;
            case 3:
                mat.SetShadingType(sPhong);
                break;
            case 4:
                mat.SetShadingType(sMetal);
                break;
            }
            break;
        case MAT_WIRE:
            mat.SetShadingType(sWireframe);
            break;
        case MAT_TEXMAP:
            ReadMap(chunk, mat.GetTextureMap1());
            break;
        case MAT_TEX2MAP:
            ReadMap(chunk, mat.GetTextureMap2());
            break;
        case MAT_OPACMAP:
            ReadMap(chunk, mat.GetOpacityMap());
            break;
        case MAT_BUMPMAP:
            ReadMap(chunk, mat.GetBumpMap());
            break;
        case MAT_SPECMAP:
            ReadMap(chunk, mat.GetSpecularMap());
            break;
        case MAT_REFLMAP:
            child = ReadChunk();
            mat.GetReflectionMap().strength = ReadPercentage(child);
            SkipChunk(child);
            child = ReadChunk();
            if (child.id != MAT_MAPNAME)
            {
                ErrorMsg("L3DS::ReadMaterial - error, expected chunk not found");
                return;
            }
            ReadASCIIZ(str, 30);
            if (strcmp(str, "") == 0)
                strcpy(mat.GetReflectionMap().mapName, "auto");
            break;
        }

        SkipChunk(chunk);
        chunk = ReadChunk();
    }
    m_materials.push_back(mat);
    m_materials[m_materials.size()-1].SetID(m_materials.size()-1);
  return 0;
}*/
//------------------------------------------------------------------------------
/*bool Load3DS( TTriangles * p_object, char * p_filename )
{
	int i; //Index variable
	FILE * l_file; //File pointer

	unsigned short l_chunk_id; //Chunk identifier
	unsigned int l_chunk_lenght; //Chunk lenght

	unsigned char l_char; //Char variable
	unsigned short l_qty; //Number of elements in each chunk

	unsigned short l_face_flags; //Flag that stores some face information

	if ( ( l_file = fopen( p_filename, "rb" ) ) == NULL ) return 0; //Open the file
  
	long flen=fileLength(p_filename);

	while ( ftell( l_file ) < flen ) //Loop to scan the whole file
	{
		//getche(); //Insert this command for debug (to wait for keypress for each chuck reading)

fread( & l_char, 1, 1, l_file ); //Read the chunk header
printf( "l_char: %d\n", l_char );
fread( & l_char, 1, 1, l_file ); //Read the chunk header
printf( "l_char: %d\n", l_char );
fread( & l_char, 1, 1, l_file ); //Read the chunk header
printf( "l_char: %d\n", l_char );
fread( & l_char, 1, 1, l_file ); //Read the chunk header
printf( "l_char: %d\n", l_char );
fread( & l_char, 1, 1, l_file ); //Read the chunk header
printf( "l_char: %d\n", l_char );
fread( & l_char, 1, 1, l_file ); //Read the chunk header
printf( "l_char: %d\n", l_char );
fread( & l_char, 1, 1, l_file ); //Read the chunk header
printf( "l_char: %d\n", l_char );
fread( & l_char, 1, 1, l_file ); //Read the chunk header
printf( "l_char: %d\n", l_char );
fread( & l_char, 1, 1, l_file ); //Read the chunk header
printf( "l_char: %d\n", l_char );
fread( & l_char, 1, 1, l_file ); //Read the chunk header
printf( "l_char: %d\n", l_char );

    fread( & l_chunk_id, 2, 1, l_file ); //Read the chunk header
    printf( "ChunkID: %d\n", l_chunk_id );
    fread( & l_chunk_lenght, 4, 1, l_file ); //Read the lenght of the chunk
    printf( "ChunkLenght: %d\n", l_chunk_lenght );

    switch ( l_chunk_id )
    {
      //----------------- MAIN3DS -----------------
      // Description: Main chunk, contains all the other chunks
      // Chunk ID: 4d4d
      // Chunk Lenght: 0 + sub chunks
      //-------------------------------------------
      case MAIN3DS:
      break;

        //----------------- EDIT3DS -----------------
        // Description: 3D Editor chunk, objects layout info
        // Chunk ID: 3d3d (hex)
        // Chunk Lenght: 0 + sub chunks
        //-------------------------------------------
      case EDIT3DS:
      break;

        //--------------- EDIT_OBJECT ---------------
        // Description: Object block, info for each object
        // Chunk ID: 4000 (hex)
        // Chunk Lenght: len(object name) + sub chunks
        //-------------------------------------------
      case EDIT_OBJECT:
        i = 0;
        do
        {
          fread( & l_char, 1, 1, l_file );
          p_object->name[i] = l_char;
          i++;
        }
        while ( l_char != '\0' && i < 20 );
      break;
      case MAT_ENTRY:
        read_material_section(p_object,l_file);
      break;
        //--------------- OBJ_TRIMESH ---------------
        // Description: Triangular mesh, contains chunks for 3d mesh info
        // Chunk ID: 4100 (hex)
        // Chunk Lenght: 0 + sub chunks
        //-------------------------------------------
      case OBJ_TRIMESH:
      break;

        //--------------- TRI_VERTEXL ---------------
        // Description: Vertices list
        // Chunk ID: 4110 (hex)
        // Chunk Lenght: 1 x unsigned short (number of vertices)
        //             + 3 x float (vertex coordinates) x (number of vertices)
        //             + sub chunks
        //-------------------------------------------
      case TRI_VERTEXLIST:
        fread( & l_qty, sizeof( unsigned short ), 1, l_file );
        p_object->VertexCount = l_qty;
        printf( "Number of vertices: %d\n", l_qty );

		for ( i = 0; i < l_qty; i++ )
        {
          fread( & p_object->Vertices[i].x, sizeof( float ), 1, l_file );
          printf( "Vertices list x: %f\n", p_object->Vertices[i].x );
          fread( & p_object->Vertices[i].y, sizeof( float ), 1, l_file );
          printf( "Vertices list y: %f\n", p_object->Vertices[i].y );
          fread( & p_object->Vertices[i].z, sizeof( float ), 1, l_file );
          printf( "Vertices list z: %f\n", p_object->Vertices[i].z );
        }
      break;

        //--------------- TRI_FACEL1 ----------------
        // Description: Polygons (faces) list
        // Chunk ID: 4120 (hex)
        // Chunk Lenght: 1 x unsigned short (number of polygons)
        //             + 3 x unsigned short (polygon points) x (number of polygons)
        //             + sub chunks
        //-------------------------------------------
      case TRI_FACELIST:
        fread( & l_qty, sizeof( unsigned short ), 1, l_file );
        p_object->FacesCount = l_qty;
        printf( "Number of polygons: %d\n", l_qty );

        //пїЅпїЅпїЅпїЅ пїЅпїЅпїЅ
        p_object->faces= new RsFacesABC[p_object->FacesCount];
        p_object->SmoothNormals= new RfPointXYZ[p_object->FacesCount];

        for ( i = 0; i < l_qty; i++ )
        {
          fread( & p_object->faces[i].a, sizeof( unsigned short ), 1, l_file );
          printf( "Polygon point a: %d\n", p_object->faces[i].a );
          fread( & p_object->faces[i].b, sizeof( unsigned short ), 1, l_file );
          printf( "Polygon point b: %d\n", p_object->faces[i].b );
          fread( & p_object->faces[i].c, sizeof( unsigned short ), 1, l_file );
          printf( "Polygon point c: %d\n", p_object->faces[i].c );
          fread( & l_face_flags, sizeof( unsigned short ), 1, l_file );
          printf( "Face flags: %x\n", l_face_flags );
          //пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ
          CalcNormals(  p_object->Vertices[ p_object->faces[i].a ].x,
                        p_object->Vertices[ p_object->faces[i].a ].y,
                        p_object->Vertices[ p_object->faces[i].a ].z,
                        p_object->Vertices[ p_object->faces[i].b ].x,
                        p_object->Vertices[ p_object->faces[i].b ].y,
                        p_object->Vertices[ p_object->faces[i].b ].z,
                        p_object->Vertices[ p_object->faces[i].c ].x,
                        p_object->Vertices[ p_object->faces[i].c ].y,
                        p_object->Vertices[ p_object->faces[i].c ].z,
                        p_object->SmoothNormals[i].x,p_object->SmoothNormals[i].y,p_object->SmoothNormals[i].z);
        }
      break;

        //------------- TRI_MAPPINGCOORS ------------
        // Description: Vertices list
        // Chunk ID: 4140 (hex)
        // Chunk Lenght: 1 x unsigned short (number of mapping points)
        //             + 2 x float (mapping coordinates) x (number of mapping points)
        //             + sub chunks
        //-------------------------------------------
      case TRI_FACEMAPPING:
        fread( & l_qty, sizeof( unsigned short ), 1, l_file );
        p_object->countMapPoint = l_qty;
        printf( "Number of MapPoint: %d\n", l_qty );
        p_object->TexVertices= new RfPointXY[p_object->countMapPoint];

        for ( i = 0; i < l_qty; i++ )
        {
          fread( & p_object->TexVertices[i].x, sizeof( float ), 1, l_file );
          printf( "Mapping list u: %f\n", p_object->TexVertices[i].x );
          fread( & p_object->TexVertices[i].y, sizeof( float ), 1, l_file );
          printf( "Mapping list v: %f\n", p_object->TexVertices[i].y );
        }
      break;

        //----------- Skip unknow chunks ------------
        //We need to skip all the chunks that currently we don't use
        //We use the chunk lenght information to set the file pointer
        //to the same level next chunk
        //-------------------------------------------
      default:
        fseek( l_file, l_chunk_lenght - 6, SEEK_CUR );
    }
  }
  fclose( l_file ); // Closes the file stream
  return ( 1 ); // Returns ok
}*/

void f_MAT_ENTRY(TTrianglesList *MultyMesh,wxInputStream *is,TFileList *fl,unsigned int allLenght)
{
	LChunk chunk1,chunk2;

	unsigned int i;
	char l_char;
	float r,g,b,a,blur;
	unsigned char br, bg, bb, ba;
	unsigned short precent,tiling;

	TTriMat *Material=MultyMesh->AddMat(); //добавляем новую текстуру к списку всех текстур

	chunk1.sum=0;
	while(chunk1.sum<allLenght-6)
	{
		is->Read(&chunk1.id, sizeof(chunk1.id));
		is->Read(&chunk1.len, sizeof(chunk1.len));
		chunk1.sum+=chunk1.len;
		if(chunk1.sum>allLenght-6) return;//проверка на ошибки в алгоритме считывания
		switch(chunk1.id)
		{
			case MAT_NAME:
				//создаём новый материал с заданным здесь именем
				for(i=0;i<20;i++)
				{
					is->Read(&l_char, 1);
					Material->name[i] = l_char;
					if(l_char==0) break;
				}
			break;
			case MAT_AMBIENT:
				is->Read(&chunk2.id, sizeof(chunk2.id));
				is->Read(&chunk2.len, sizeof(chunk2.len));
				switch(chunk2.id)
				{
					case COLOR_F:
						is->Read(&r, sizeof(r));
						is->Read(&g, sizeof(g));
						is->Read(&b, sizeof(b));
					break;
					case COLOR_24:
						is->Read(&br, sizeof(br));
						is->Read(&bg, sizeof(bg));
						is->Read(&bb, sizeof(bb));
					break;
					case LIN_COLOR_24:
						is->Read(&br, sizeof(br));
						is->Read(&bg, sizeof(bg));
						is->Read(&bb, sizeof(bb));
						is->Read(&ba, sizeof(ba));
					break;
					case LIN_COLOR_F:
						is->Read(&r, sizeof(r));
						is->Read(&g, sizeof(g));
						is->Read(&b, sizeof(b));
						is->Read(&a, sizeof(a));
					break;
				}
				Material->ColorAmbientRGB.r=br/255.0f;
				Material->ColorAmbientRGB.g=bg/255.0f;
				Material->ColorAmbientRGB.b=bb/255.0f;
			break;
			case MAT_DIFFUSE:
				is->Read(&chunk2.id, sizeof(chunk2.id));
				is->Read(&chunk2.len, sizeof(chunk2.len));
				switch(chunk2.id)
				{
					case COLOR_F:
						is->Read(&r, sizeof(r));
						is->Read(&g, sizeof(g));
						is->Read(&b, sizeof(b));
					break;
					case COLOR_24:
						is->Read(&br, sizeof(br));
						is->Read(&bg, sizeof(bg));
						is->Read(&bb, sizeof(bb));
					break;
					case LIN_COLOR_24:
						is->Read(&br, sizeof(br));
						is->Read(&bg, sizeof(bg));
						is->Read(&bb, sizeof(bb));
						is->Read(&ba, sizeof(ba));
					break;
					case LIN_COLOR_F:
						is->Read(&r, sizeof(r));
						is->Read(&g, sizeof(g));
						is->Read(&b, sizeof(b));
						is->Read(&a, sizeof(a));
					break;
				}
				Material->ColorDiffuseRGB.r=br/255.0f;
				Material->ColorDiffuseRGB.g=bg/255.0f;
				Material->ColorDiffuseRGB.b=bb/255.0f;
			break;
			case MAT_SPECULAR:
				is->Read(&chunk2.id, sizeof(chunk2.id));
				is->Read(&chunk2.len, sizeof(chunk2.len));
				switch(chunk2.id)
				{
					case COLOR_F:
						is->Read(&r, sizeof(r));
						is->Read(&g, sizeof(g));
						is->Read(&b, sizeof(b));
					break;
					case COLOR_24:
						is->Read(&br, sizeof(br));
						is->Read(&bg, sizeof(bg));
						is->Read(&bb, sizeof(bb));
					break;
					case LIN_COLOR_24:
						is->Read(&br, sizeof(br));
						is->Read(&bg, sizeof(bg));
						is->Read(&bb, sizeof(bb));
						is->Read(&ba, sizeof(ba));
					break;
					case LIN_COLOR_F:
						is->Read(&r, sizeof(r));
						is->Read(&g, sizeof(g));
						is->Read(&b, sizeof(b));
						is->Read(&a, sizeof(a));
					break;
				}
				Material->ColorSpecularRGB.r=br/255.0f;
				Material->ColorSpecularRGB.g=bg/255.0f;
				Material->ColorSpecularRGB.b=bb/255.0f;
			break;
			case MAT_SHININESS:
				for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1);
			break;
			case MAT_SHIN2PCT:
				for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1);
			break;
			case MAT_TRANSPARENCY:
				for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1);
			break;
			case MAT_TRANSFALLOF:
				for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1);
			break;
			case MAT_REFLECTBLUR:
				for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1);
			break;
			case MAT_SHADING:
				for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1);
			break;
			case MAT_SELFILLUM:
				for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1);
			break;
			case MAT_TRANSFALLOFF:
				for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1);
			break;
			case MAT_WIRESIZE:
				for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1);
			break;
//			case MAT_TRANSPARENCY:
//			break;
//			case MAT_TEXMAP:
//				ProcessNextMaterialChunk(NewChunk);
//			break;
			case MAT_TEXMAP:
				chunk2.sum=0;
				while(chunk2.sum<chunk1.len-6)
				{ 
					is->Read(&chunk2.id, sizeof(chunk2.id));
					is->Read(&chunk2.len, sizeof(chunk2.len));
					chunk2.sum+=chunk2.len;
					switch(chunk2.id)
					{
						case INT_PERCENTAGE:
							is->Read(&precent, sizeof(precent));
						break;
						case MAT_MAPNAME: //файл текстуры
						{
							for(i=0;i<20;i++)
							{
								is->Read(&l_char, 1);
								Material->imgpath[i] = l_char;
								if(l_char==0) break;
							}
							//находим текстуру в архиве и загружаем
							wxInputStream *imgStream = fl->get(wxString::FromAscii(Material->imgpath));
							if(imgStream!=NULL)
							{
								wxString ext=getAfterLast(wxString::FromAscii(Material->imgpath),'.');
								Material->textureid=glLoadBitmap0(2,*imgStream,ext);
							}
						}
						break;
						case MAT_MAP_TILING:
							is->Read(&tiling, sizeof(tiling));
						break;
						case MAT_MAP_TEXBLUR:
							is->Read(&blur, sizeof(blur));
						break;
						case MAT_MAP_USCALE:
							is->Read(&Material->USCALE, sizeof(Material->USCALE));
						break;
						case MAT_MAP_VSCALE:
							is->Read(&Material->VSCALE, sizeof(Material->VSCALE));
						break;
						case MAT_MAP_UOFFSET:
							for(i=0;i<chunk2.len-6;i++) is->Read(&l_char,1);
						break;
						case MAT_MAP_VOFFSET:
							for(i=0;i<chunk2.len-6;i++) is->Read(&l_char,1);
						break;
						default: for(i=0;i<chunk2.len-6;i++) is->Read(&l_char,1); //непрочитанные блоки пропускаем
					}
				}
			break;
			default: for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1); //непрочитанные блоки пропускаем
		}
	}
	//result=allLenght;
}
//------------------------------------------------------------------------------
bool LoadMain3DS(TTrianglesList *MultyMesh,wxInputStream *is,TFileList *fl)
{
	LChunk chunk1,chunk2,chunk3,chunk4,chunk5;
	
	//unsigned short bufus;
	unsigned short wpos=0;
	unsigned short l_qty,l_face_flags;
	unsigned int Version,i;
	unsigned char l_char;
	RfPointXYZ xPoint1,yPoint2,zPoint3;
	TTriangles *p_object;
	unsigned int size=(unsigned int)is->GetSize();
	chunk1.sum=0;
	while(chunk1.sum<size-6)
	{	
		is->Read(&chunk1.id, 2);
		is->Read(&chunk1.len, 4);
		chunk1.sum+=chunk1.len;
		if(chunk1.sum>size-6) return false;//проверка на ошибки в алгоритме считывания
		switch(chunk1.id)
		{
			case ID_VERSION:
				is->Read(&Version, 4);
				if(Version>3) return false;
			break;
			//----------------- EDIT3DS -----------------
			// Description: 3D Editor chunk, objects layout info
			// Chunk ID: 3d3d (hex)
			// Chunk Lenght: 0 + sub chunks
			//-------------------------------------------
			case EDIT3DS:
				chunk2.sum=0;
				while(chunk2.sum<chunk1.len-6)
				{
					is->Read(&chunk2.id, sizeof(chunk2.id));
					is->Read(&chunk2.len, sizeof(chunk2.len));
					chunk2.sum+=chunk2.len;
					if(chunk2.sum>chunk1.len-6) return false;//проверка на ошибки в алгоритме считывания
					switch(chunk2.id)
					{
						//по правильному надо поместить всё что ниже сюда
						case MESH_VERSION:
							is->Read(&Version, 4);
							if(Version>3) return false;
						break;
						case MAT_ENTRY:
							f_MAT_ENTRY(MultyMesh,is,fl,chunk2.len);
						break;
						case EDIT_CONFIG1:
							for(i=0;i<chunk2.len-6;i++) is->Read(&l_char,1);
						break;
						//--------------- EDIT_OBJECT ---------------
						// Description: Object block, info for each object
						// Chunk ID: 4000 (hex)
						// Chunk Lenght: len(object name) + sub chunks
						//-------------------------------------------
						case EDIT_OBJECT:
							p_object=MultyMesh->Add();
							wpos=0; //позиция загружаемой текстуры
							char cnt=0;
							for(i=0;i<20;i++) //считываем название обьекта
							{
								is->Read(&l_char, 1);
								p_object->name[i] = l_char;
								cnt++;
								if(l_char==0) break;
							}
							chunk3.sum=0;
							while(chunk3.sum<chunk2.len-6-cnt)
							{
								is->Read(&chunk3.id, sizeof(chunk3.id));
								is->Read(&chunk3.len, sizeof(chunk3.len));
								chunk3.sum+=chunk3.len;
								if(chunk3.sum>chunk2.len-6-cnt) return false;//проверка на ошибки в алгоритме считывания
								switch(chunk3.id)
								{
									//--------------- OBJ_TRIMESH ---------------
									// Description: Triangular mesh, contains chunks for 3d mesh info
									// Chunk ID: 4100 (hex)
									// Chunk Lenght: 0 + sub chunks
									//-------------------------------------------
									case OBJ_TRIMESH:
										chunk4.sum=0;
										while(chunk4.sum<chunk3.len-6)
										{
											is->Read(&chunk4.id, sizeof(chunk4.id));
											is->Read(&chunk4.len, sizeof(chunk4.len));
											chunk4.sum+=chunk4.len;
											if(chunk4.sum>chunk3.len-6) return false;//проверка на ошибки в алгоритме считывания
											switch(chunk4.id)
											{
												//--------------- TRI_VERTEXL ---------------
												// Description: Vertices list
												// Chunk ID: 4110 (hex)
												// Chunk Lenght: 1 x unsigned short (number of vertices)
												//             + 3 x float (vertex coordinates) x (number of vertices)
												//             + sub chunks
												//-------------------------------------------
												case TRI_VERTEXLIST:
													is->Read(&l_qty,2);
													p_object->CountVertex = l_qty;
													p_object->Vertices=new RfPointXYZ[p_object->CountVertex]; //память под точки
													for(i=0;i<l_qty;i++)
													{
														is->Read(&p_object->Vertices[i].x, 4);
														is->Read(&p_object->Vertices[i].y, 4);
														is->Read(&p_object->Vertices[i].z, 4);
													}
													//p_object->CalcMinMaxPoint();
												break;
												//--------------- TRI_FACEL1 ----------------
												// Description: Polygons (faces) list
												// Chunk ID: 4120 (hex)
												// Chunk Lenght: 1 x unsigned short (number of polygons)
												//             + 3 x unsigned short (polygon points) x (number of polygons)
												//             + sub chunks
												//-------------------------------------------
												case TRI_FACELIST:
													is->Read(&l_qty, 2);
													p_object->CountFaces = l_qty;
													p_object->faces=new RsFacesABC[p_object->CountFaces]; //пока сюда не записываем только в буфер потом из буфера в соответствии с текстурой (точки на которые указывает поверхность с другой текстурой надо скопировать (также и с нормалями) )
													//bufFaces=new RsFacesABC[p_object->FacesCount];
													chunk5.sum=2; //подсчитываем прочитанное
													for(i=0;i<l_qty;i++)
													{
														is->Read(&p_object->faces[i].a, 2);
														is->Read(&p_object->faces[i].b, 2);
														is->Read(&p_object->faces[i].c, 2);
														is->Read(&l_face_flags,2); //word Face flag * bit 0 : CA visible * bit 1 : BC visible * bit 2 : AB visible
														chunk5.sum+=8; //подсчитываем прочитанное
													}
													while(chunk5.sum<chunk4.len-6)
													{
														//считываем группы сглаживания для фейсов и материал для фейсов
														is->Read(&chunk5.id, sizeof(chunk5.id));
														is->Read(&chunk5.len, sizeof(chunk5.len));
														chunk5.sum+=chunk5.len;
														if(chunk5.sum>chunk4.len-6) return false;//проверка на ошибки в алгоритме считывания
														switch(chunk5.id)
														{
															case TRI_MAT_GROUP: //16688 0x4130 материал для фейсов данного объекта
															{	char *name=new char[20];
																for(i=0;i<20;i++)//название материала
																{
																	is->Read(&l_char, 1);
																	name[i] = l_char;
																	if(l_char==0) break;
																}
																unsigned short wnum;
																is->Read(&wnum,sizeof(wnum));
																unsigned short *faces=new unsigned short[wnum];
																for(i=0;i<wnum;i++) is->Read(&faces[i],2); //список фейсов с данным материалом name
																p_object->AddMaterial(name,wnum,faces); //фиксируем материал для текущего обьекта на нужной позиции pos
															}
															break;
															case TRI_SMOOTH_GROUP: //0x4150 группа сглаживания для каждого фейса
																p_object->SmoothG=new unsigned int[p_object->CountFaces];
																for(i=0;i<p_object->CountFaces;i++)
																{
																	is->Read(&p_object->SmoothG[i],4);
																}
															break;
															default:
																for(i=0;i<chunk5.len-6;i++) is->Read(&l_char,1);
														}
													}
												break;
												//------------- TRI_MAPPINGCOORS ------------
												// Description: Vertices list
												// Chunk ID: 4140 (hex)
												// Chunk Lenght: 1 x unsigned short (number of mapping points)
												//             + 2 x float (mapping coordinates) x (number of mapping points)
												//             + sub chunks
												//-------------------------------------------
												case TRI_FACEMAPPING: //координаты материала
													is->Read(&l_qty, 2); //количество матерных точек == кол-ву точек
													p_object->TexVertices=new RfPointXY[l_qty];
													for(i=0;i<l_qty;i++)
													{
														is->Read(&p_object->TexVertices[i].x,sizeof(p_object->TexVertices[i].x));
														is->Read(&p_object->TexVertices[i].y,sizeof(p_object->TexVertices[i].y));
													}
												break;
												case TRI_LOCAL: //Local coordinate system
													//Max сохраняет в 3ds уже с конвертированное а всё в этом чанке только для информации
													is->Read(&xPoint1.x,sizeof(xPoint1.x)); //Scale X "Absolute: Local"
													is->Read(&xPoint1.y,sizeof(xPoint1.z));
													is->Read(&xPoint1.z,sizeof(xPoint1.y));

													is->Read(&yPoint2.x,sizeof(yPoint2.x));
													is->Read(&yPoint2.y,sizeof(yPoint2.y)); //Scale Y "Absolute: Local"
													is->Read(&yPoint2.z,sizeof(yPoint2.z));

													is->Read(&zPoint3.x,sizeof(zPoint3.x));
													is->Read(&zPoint3.y,sizeof(zPoint3.y));
													is->Read(&zPoint3.z,sizeof(zPoint3.z)); //Scale Z "Absolute: Local"

													is->Read(&p_object->PointXYZCenter.x,sizeof(p_object->PointXYZCenter.x)); //позизия пивота в абсолютных координатах (надо найти разницу)
													is->Read(&p_object->PointXYZCenter.y,sizeof(p_object->PointXYZCenter.y));
													is->Read(&p_object->PointXYZCenter.z,sizeof(p_object->PointXYZCenter.z));
												break;
												default:
													for(i=0;i<chunk4.len-6;i++) is->Read(&l_char,1);
											}//end of switch(l_chunk_id4)
										}//end of while(sumLenght4<l_chunk_lenght-6)
									break;
									case OBJ_LIGHT:
										for(i=0;i<chunk3.len-6;i++) is->Read(&l_char,1);
									break;
									case OBJ_CAMERA:
										for(i=0;i<chunk3.len-6;i++) is->Read(&l_char,1);
									break;
									default:
										for(i=0;i<chunk3.len-6;i++) is->Read(&l_char,1);
								}//end of switch(l_chunk_id3)
							}//end of while(sumLenght3<l_chunk_lenght2-6-cnt)
						break;
						for(i=0;i<chunk2.len-6;i++) is->Read(&l_char,1);
					}
				}//end of while(sumLenght2<l_chunk_lenght-6)
			break;			
			case KFDATA: //0xB000 ключи анимации
				for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1);
/*				sumLenght2=0;
				while(sumLenght2<l_chunk_lenght-6)
				{
					is->Read(&l_chunk_id2, sizeof(l_chunk_id2));
					is->Read(&l_chunk_lenght2, sizeof(l_chunk_lenght2));
					sumLenght2=sumLenght2 + l_chunk_lenght2;
					if(sumLenght2>l_chunk_lenght-6) return false;//проверка на ошибки в алгоритме считывания
					switch(l_chunk_id2)
					{
						case KFHDR: // путь к файлу анимации или Viewport layout (Revision number SHORT)
						{
							is->Read(&bufus, sizeof(bufus)); //Revision number (версия файла)
							for(i=0;i<20;i++)
							{
								is->Read(&l_char, 1);
								name[i] = l_char;
								if(l_char=='\n') break;
							}
							is->Read(&bufus, sizeof(bufus)); //Animation length
							is->Read(&bufus, sizeof(bufus)); //старт ???
						}
						case FRAMES: //Object name, parameters and hierarchy father
						{
							is->Read(&fstart, sizeof(fstart));
							is->Read(&fend, sizeof(fend));
						}
						case KFCURTIME:
						{
							is->Read(&bufus, sizeof(bufus));
							is->Read(&bufus, sizeof(bufus));
						}
						case OBJECT_NODE_TAG:
						{
							sumLenght3=0;
							while(sumLenght3<l_chunk_lenght2-6)
							{
								is->Read(&l_chunk_id3, sizeof(l_chunk_id3));
								is->Read(&l_chunk_lenght3, sizeof(l_chunk_lenght3));
								sumLenght3=sumLenght3 + l_chunk_lenght3;
								if(sumLenght3>l_chunk_lenght2-6) return false;//проверка на ошибки в алгоритме считывания
								switch(l_chunk_id3)
								{
									case HIERARCHY: //45104 : Hierarchy position
									{
										//is->seek( l_chunk_lenght3 - 6, soCurrent );
										for(i=0;i<l_chunk_lenght3-6;i++) is->Read(&l_char,1);
									}
									case NODE_HDR: //Object name, parameters and hierarchy father
									{
										for(i=0;i<20;i++)
										{
											is->Read(&l_char, 1);
											name[i] = l_char;
											if(l_char=='\n') break;
										}
										p_object=MultyMesh->FindObjectOnName(name);
										is->Read(&wnum, sizeof(wnum)); //* Bit 11 : Hidden
										is->Read(&wnum, sizeof(wnum)); //* Bit 0 : Show path * Bit 1 : Animate smoothing * Bit 4 : Object motion blur * Bit 6 : Morph MultyMesh->
										is->Read(&wnum, sizeof(wnum)); // Hierarchy father, link to the parent object (-1 for none)
									}
									case PIVOT:
									{
										//Считываем на сколько был сдвинут пивот по XYZ от первоначального значения (в 3d Максе )
										is->Read(&PivotPoint.x, sizeof(PivotPoint.x));
										is->Read(&PivotPoint.y, sizeof(PivotPoint.y));
										is->Read(&PivotPoint.z, sizeof(PivotPoint.z));
										//при сохранении в 3ds координаты преобразовываються относительно Пивота (поэтому надо их сдвинуть на место)
										for(i=0;i<p_object->VertexCount;i++)
										{
											p_object->Vertices[i].x=p_object->Vertices[i].x-PivotPoint.x;
											p_object->Vertices[i].y=p_object->Vertices[i].y-PivotPoint.y;
											p_object->Vertices[i].z=p_object->Vertices[i].z-PivotPoint.z;
										}
									}
									case POS_TRACK_TAG: //Position track
									{
										is->Read(&wnum, sizeof(wnum));
										is->Read(&wnum, sizeof(wnum)); is->Read(&wnum, sizeof(wnum));
										is->Read(&lwcount, sizeof(lwcount)); //Number of keys in this track
										is->Read(&lwcn, sizeof(lwcn)); //Key number (position in track)
										is->Read(&wnum, sizeof(wnum)); //Acceleration data present (flag)
										is->Read(&CenterPoint.x, sizeof(CenterPoint.x));
										is->Read(&CenterPoint.y, sizeof(CenterPoint.x));
										is->Read(&CenterPoint.z, sizeof(CenterPoint.y));
										is->Read(&CenterPoint.z, sizeof(CenterPoint.z));
									}
									case ROT_TRACK_TAG: //Rotation track 36 bytes
									{
										is->Read(&wnum, sizeof(wnum));
										is->Read(&wnum, sizeof(wnum)); is->Read(wnum, sizeof(wnum));
										is->Read(&wnum, sizeof(wnum)); //Number of keys in this track
										is->Read(&wnum, sizeof(wnum)); //Key number (position in track)

										is->Read(&wnum, sizeof(wnum)); //Acceleration data present (flag)
										is->Read(&lwcn, sizeof(lwcn)); //long unknown;

										is->Read(&angle, sizeof(angle)); //long unknown;
										is->Read(&angle, sizeof(angle)); //наверно угол в плоскости X Y пивота
										//надо подробно разобрать первое предположение что это тоже углы но зачем хватило бы 2
										is->Read(&CenterPoint.y, sizeof(CenterPoint.x));
										is->Read(&CenterPoint.z, sizeof(CenterPoint.z));
										is->Read(&CenterPoint.x, sizeof(CenterPoint.y));
									}
									case SCL_TRACK_TAG: //Scale track
									{
										is->Read(&wnum, sizeof(wnum)); //word
										is->Read(&wnum, sizeof(wnum)); is->Read(wnum, sizeof(wnum));
										is->Read(&lwcount, sizeof(lwcount)); //Number of keys in this track
										is->Read(&lwcn, sizeof(lwcn)); //Key number (position in track)
										is->Read(&wnum, sizeof(wnum)); //Acceleration data present (flag)
										is->Read(&CenterPoint.x, sizeof(CenterPoint.x));

										is->Read(&CenterPoint.x, sizeof(CenterPoint.x)); //зум по осям 0..1..
										is->Read(&CenterPoint.y, sizeof(CenterPoint.y));
										is->Read(&CenterPoint.z, sizeof(CenterPoint.z));
									}
									default: 
										//is->seek( l_chunk_lenght3 - 6, soCurrent );
										for(i=0;i<l_chunk_lenght3-6;i++) is->Read(&l_char,1);
								}
							}
						}
						default: is->seek( l_chunk_lenght2 - 6, soCurrent );
					} //switch
				} //while*/
			break;
			default:
				//is->SeekI( l_chunk_lenght - 6, wxFromCurrent ); //непрочитанные блоки пропускаем
				for(i=0;i<chunk1.len-6;i++) is->Read(&l_char,1);
		} //switch
	} //while

	return true;
}
//------------------------------------------------------------------------------
//загрузить 3ds файл в объект отображения
bool Load3DS2(TTrianglesList *MultyMesh,wxInputStream *is,TFileList *fl)
{
	bool result=true;
	unsigned short l_chunk_id;
	unsigned int l_chunk_lenght;
	unsigned int sumLenght=0;
	unsigned char l_char;

	unsigned int size=(unsigned int)is->GetSize();
	while(sumLenght<size)
	{	
		is->Read(&l_chunk_id, 2);
		is->Read(&l_chunk_lenght, 4);
		sumLenght+=l_chunk_lenght;
		if(sumLenght>size) return false;//проверка на ошибки в алгоритме считывания
		switch(l_chunk_id)
		{
			case MAIN3DS:
				LoadMain3DS(MultyMesh,is,fl);
			break;
			default:
				for(unsigned int i=0;i<l_chunk_lenght-6;i++) is->Read(&l_char,1);
		}
	}
	return result;
}
//------------------------------------------------------------------------------
//Загрузить модели из списка именованных потоков
// fl - список из "название файла -> поток"
// Triangles - Список 3d объектов
bool Load3DSFromZIP(TTrianglesList * Triangles,TFileList *fl)
{
	//перебираем и загружаем 3ds файлы
	for(unsigned int i=0;i<fl->getCount();i++)
	{
		wxString name=fl->item(i)->name;
		if(name.AfterLast(_T('.')).Lower()==_T("3ds"))
			Load3DS2(Triangles,fl->item(i)->is,fl);
	}
	return true;
}
//------------------------------------------------------------------------------