/* 3dsloader.c : a small library to load a subset of the 3DS model format */ /* This software is PUBLIC DOMAIN as of January 2006. No copyright is claimed. * - Jon Mayo */ #include #include #include #include #include "fileio.h" #include "model.h" #include "logger.h" enum chunk_id { CHUNK_M3DMAGIC=0x4d4d, CHUNK_M3D_VERSION=0x0002, CHUNK_MDATA=0x3d3d, CHUNK_COLOR_F=0x0010, CHUNK_COLOR_24=0x0011, CHUNK_MAT_ENTRY=0xafff, CHUNK_MAT_NAME=0xa000, CHUNK_MAT_AMBIENT=0xa010, CHUNK_MAT_DIFFUSE=0xa020, CHUNK_MAT_SPECULAR=0xa030, CHUNK_MAT_SHININESS=0xa040, CHUNK_MAT_SNIN2PCT=0xa041, CHUNK_MAT_TRANSPARENCY=0xa050, CHUNK_MAT_XPFALL=0xa052, CHUNK_MAT_USE_XPFALL=0xa240, CHUNK_MAT_REFBLUR=0xa053, CHUNK_MAT_SHADING=0xa100, CHUNK_MAT_WIRESIZE=0xa087, CHUNK_MESH_VERSION=0x3d3e, CHUNK_NAMED_OBJECT=0x4000, CHUNK_N_TRI_OBJECT=0x4100, CHUNK_POINT_ARRAY=0x4110, CHUNK_FACE_ARRAY=0x4120, CHUNK_TEX_VERTS=0x4140, CHUNK_MESH_MATRIX=0x4160, CHUNK_MASTER_SCALE=0x0100, CHUNK_INT_PERCENTAGE=0x0030, CHUNK_KFDATA=0xb000, /* Keyframe data */ }; struct state_3ds { long file_size; struct model *model; struct object *current_object; }; static void free_state(struct state_3ds *m) { model_free(m->model); m->model=0; } static int swallow(FILE *f, long bytes) { if(fseek(f, bytes, SEEK_CUR)!=0) { LOG_DEBUG("%s:%d:", __FILE__, __LINE__); perror("fseek()"); return 0; } return 1; } static int read3ds_chunk_header(FILE *f, const char *filename, enum chunk_id *chunk_id, size_t *chunk_len) { uint16_t chunk_id_data; uint32_t chunk_len_data; if( read_u2le(f, filename, 1, &chunk_id_data) && read_u4le(f, filename, &chunk_len_data)) { *chunk_id=chunk_id_data; *chunk_len=chunk_len_data-6; if(chunk_len_data<6) { LOG_INFO("%s:short chunk\n", filename); return 0; } return 1; } LOG_DEBUG("%s:%d:", __FILE__, __LINE__); perror(filename); return 0; } static int read_point_array(struct state_3ds *m, FILE *f, const char *filename, long len) { float point[3]; uint16_t count; unsigned i; if(!read_u2le(f, filename, 1, &count)) { return 0; } if(len!=count*4*3+2) { LOG_INFO("%s: corrupt POINT_ARRAY chunk\n", filename); return 0; } for(i=0;icurrent_object, point[0], point[1], point[2]); } return 1; } static int read_face_array(struct state_3ds *m, FILE *f, const char *filename, long len) { enum chunk_id chunk_id; size_t chunk_len; long start; uint16_t nr_face; int i; start=ftell(f); LOG_INFO("%s:FACE_ARRAY start\n", filename); if(!read_u2le(f, filename, 1, &nr_face)) { return 0; } LOG_INFO("%s:FACE_ARRAY nr_face=%d\n", filename, (int)nr_face); for(i=0;icurrent_object, face[0], face[1], face[2]); } while((ftell(f)-start)current_object=model_object_create(m->model, name, 0); while((ftell(f)-start)current_object=0; return 1; } static int read_mat_entry(struct state_3ds *m, FILE *f, const char *filename, long len) { enum chunk_id chunk_id; size_t chunk_len; long start; start=ftell(f); LOG_INFO("%s:MAT_ENTRY start\n", filename); while((ftell(f)-start)