nuclear@0: #include nuclear@0: #include nuclear@0: #include "curveload.h" nuclear@0: #include "3dschunks.h" nuclear@0: #include "logger.h" nuclear@0: nuclear@15: using namespace goatgfx; nuclear@15: nuclear@2: #ifndef _MSC_VER nuclear@2: #include nuclear@2: #else nuclear@2: typedef __int8 int8_t; nuclear@2: typedef __int16 int16_t; nuclear@2: typedef __int32 int32_t; nuclear@2: typedef unsigned __int8 uint8_t; nuclear@2: typedef unsigned __int16 uint16_t; nuclear@2: typedef unsigned __int32 uint32_t; nuclear@2: #endif nuclear@2: nuclear@0: static uint32_t read_counter; nuclear@0: nuclear@0: struct ChunkHeader { nuclear@0: ChunkID id; nuclear@0: uint32_t size; nuclear@0: }; nuclear@0: nuclear@0: #define HEADER_SIZE 6 nuclear@0: nuclear@0: // local function prototypes nuclear@0: static uint8_t read_byte(FILE *file); nuclear@0: static uint16_t read_int16(FILE *file); nuclear@0: static uint32_t read_int32(FILE *file); nuclear@0: static float read_float(FILE *file); nuclear@0: static Vector3 read_vector(FILE *file, bool flip_yz = false); nuclear@0: static std::string read_string(FILE *file); nuclear@0: static ChunkHeader read_chunk_header(FILE *file); nuclear@0: static void skip_chunk(FILE *file, const ChunkHeader &chunk); nuclear@0: static Curve *read_curve(FILE *file, const ChunkHeader &ch); nuclear@0: nuclear@0: static bool eof; nuclear@0: nuclear@0: bool load_curves(Scene *scn, const char *fname) nuclear@0: { nuclear@0: FILE *file = fopen(fname, "rb"); nuclear@0: if(!file) { nuclear@0: error_log("failed to open curves scene file: %s\n", fname); nuclear@0: return false; nuclear@0: } nuclear@0: eof = false; nuclear@0: nuclear@0: ChunkHeader chunk; nuclear@0: nuclear@0: chunk = read_chunk_header(file); nuclear@0: if(chunk.id != Chunk_3DSMain) { nuclear@0: fclose(file); nuclear@0: return false; nuclear@0: } nuclear@0: nuclear@0: while(!eof) { nuclear@0: chunk = read_chunk_header(file); nuclear@0: nuclear@0: Curve *curve; nuclear@0: nuclear@0: switch(chunk.id) { nuclear@0: case Chunk_Main_3DEditor: nuclear@0: break; // dont skip nuclear@0: nuclear@0: case Chunk_Edit_Object: nuclear@0: if((curve = read_curve(file, chunk))) { nuclear@0: scn->curves.push_back(curve); nuclear@0: } nuclear@0: break; nuclear@0: nuclear@0: default: nuclear@0: skip_chunk(file, chunk); nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: fclose(file); nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: static uint8_t read_byte(FILE *fp) { nuclear@0: uint8_t v; nuclear@0: if(fread(&v, 1, 1, fp) <= 0) { nuclear@0: eof = true; nuclear@0: return 0; nuclear@0: } nuclear@0: read_counter++; nuclear@0: return v; nuclear@0: } nuclear@0: nuclear@0: static uint16_t read_int16(FILE *fp) { nuclear@0: uint16_t v; nuclear@0: if(fread(&v, 2, 1, fp) <= 0) { nuclear@0: eof = true; nuclear@0: return 0; nuclear@0: } nuclear@0: read_counter += 2; nuclear@0: return v; nuclear@0: } nuclear@0: nuclear@0: static uint32_t read_int32(FILE *fp) { nuclear@0: uint32_t v; nuclear@0: if(fread(&v, 4, 1, fp) <= 0) { nuclear@0: eof = true; nuclear@0: return 0; nuclear@0: } nuclear@0: read_counter += 4; nuclear@0: return v; nuclear@0: } nuclear@0: nuclear@0: static float read_float(FILE *fp) nuclear@0: { nuclear@0: int32_t tmp = read_int32(fp); nuclear@0: return *((float*)&tmp); nuclear@0: } nuclear@0: nuclear@0: static Vector3 read_vector(FILE *file, bool flip_yz) nuclear@0: { nuclear@0: Vector3 vector; nuclear@0: vector.x = read_float(file); nuclear@0: if(!flip_yz) vector.y = read_float(file); nuclear@0: vector.z = read_float(file); nuclear@0: if(flip_yz) vector.y = read_float(file); nuclear@0: return vector; nuclear@0: } nuclear@0: nuclear@0: static std::string read_string(FILE *file) nuclear@0: { nuclear@0: std::string str; nuclear@0: char c; nuclear@0: while((c = (char)read_byte(file))) { nuclear@0: str.push_back(c); nuclear@0: } nuclear@0: read_counter++; nuclear@0: nuclear@0: return str; nuclear@0: } nuclear@0: nuclear@0: static ChunkHeader read_chunk_header(FILE *file) nuclear@0: { nuclear@0: ChunkHeader chunk; nuclear@0: chunk.id = (ChunkID)read_int16(file); nuclear@0: chunk.size = read_int32(file); nuclear@0: return chunk; nuclear@0: } nuclear@0: nuclear@0: static void skip_chunk(FILE *file, const ChunkHeader &chunk) nuclear@0: { nuclear@0: if(eof) return; nuclear@0: fseek(file, chunk.size - HEADER_SIZE, SEEK_CUR); nuclear@0: read_counter += chunk.size - HEADER_SIZE; nuclear@0: } nuclear@0: nuclear@0: static Curve *read_curve(FILE *file, const ChunkHeader &ch) nuclear@0: { nuclear@0: read_counter = HEADER_SIZE; // reset the global read counter nuclear@0: nuclear@0: std::string name = read_string(file); nuclear@0: nuclear@0: ChunkHeader chunk; nuclear@0: chunk = read_chunk_header(file); nuclear@0: if(chunk.id == Chunk_Obj_TriMesh) { nuclear@0: // object is a trimesh... load it nuclear@0: Vector3 *varray = 0; nuclear@0: uint32_t vertex_count = 0; nuclear@0: nuclear@0: uint32_t obj_chunk_size = ch.size; nuclear@0: nuclear@0: while(read_counter < obj_chunk_size) { // make sure we only read subchunks of this object chunk nuclear@0: chunk = read_chunk_header(file); nuclear@0: nuclear@0: switch(chunk.id) { nuclear@0: case Chunk_TriMesh_VertexList: nuclear@0: vertex_count = (uint32_t)read_int16(file); nuclear@0: varray = new Vector3[vertex_count]; nuclear@0: nuclear@0: for(uint32_t i=0; iset_name(name.c_str()); nuclear@0: for(uint32_t i=0; iadd_point(varray[i]); nuclear@0: } nuclear@0: return curve; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: return 0; nuclear@0: }