Files
Tools_CPP/lib/loader3ds.cpp
2024-11-01 12:23:13 +05:00

1021 lines
39 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}
//------------------------------------------------------------------------------