goat3dgfx
diff src/curveload.cc @ 0:1873dfd13f2d
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 14 Nov 2013 05:27:09 +0200 |
parents | |
children | 7bd5ebec3b6f |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/curveload.cc Thu Nov 14 05:27:09 2013 +0200 1.3 @@ -0,0 +1,195 @@ 1.4 +#include <string> 1.5 +#include <assert.h> 1.6 +#include <stdint.h> 1.7 +#include "curveload.h" 1.8 +#include "3dschunks.h" 1.9 +#include "logger.h" 1.10 + 1.11 +static uint32_t read_counter; 1.12 + 1.13 +struct ChunkHeader { 1.14 + ChunkID id; 1.15 + uint32_t size; 1.16 +}; 1.17 + 1.18 +#define HEADER_SIZE 6 1.19 + 1.20 +// local function prototypes 1.21 +static uint8_t read_byte(FILE *file); 1.22 +static uint16_t read_int16(FILE *file); 1.23 +static uint32_t read_int32(FILE *file); 1.24 +static float read_float(FILE *file); 1.25 +static Vector3 read_vector(FILE *file, bool flip_yz = false); 1.26 +static std::string read_string(FILE *file); 1.27 +static ChunkHeader read_chunk_header(FILE *file); 1.28 +static void skip_chunk(FILE *file, const ChunkHeader &chunk); 1.29 +static Curve *read_curve(FILE *file, const ChunkHeader &ch); 1.30 + 1.31 +static bool eof; 1.32 + 1.33 +bool load_curves(Scene *scn, const char *fname) 1.34 +{ 1.35 + FILE *file = fopen(fname, "rb"); 1.36 + if(!file) { 1.37 + error_log("failed to open curves scene file: %s\n", fname); 1.38 + return false; 1.39 + } 1.40 + eof = false; 1.41 + 1.42 + ChunkHeader chunk; 1.43 + 1.44 + chunk = read_chunk_header(file); 1.45 + if(chunk.id != Chunk_3DSMain) { 1.46 + fclose(file); 1.47 + return false; 1.48 + } 1.49 + 1.50 + while(!eof) { 1.51 + chunk = read_chunk_header(file); 1.52 + 1.53 + Curve *curve; 1.54 + 1.55 + switch(chunk.id) { 1.56 + case Chunk_Main_3DEditor: 1.57 + break; // dont skip 1.58 + 1.59 + case Chunk_Edit_Object: 1.60 + if((curve = read_curve(file, chunk))) { 1.61 + scn->curves.push_back(curve); 1.62 + } 1.63 + break; 1.64 + 1.65 + default: 1.66 + skip_chunk(file, chunk); 1.67 + } 1.68 + } 1.69 + 1.70 + fclose(file); 1.71 + return true; 1.72 +} 1.73 + 1.74 +static uint8_t read_byte(FILE *fp) { 1.75 + uint8_t v; 1.76 + if(fread(&v, 1, 1, fp) <= 0) { 1.77 + eof = true; 1.78 + return 0; 1.79 + } 1.80 + read_counter++; 1.81 + return v; 1.82 +} 1.83 + 1.84 +static uint16_t read_int16(FILE *fp) { 1.85 + uint16_t v; 1.86 + if(fread(&v, 2, 1, fp) <= 0) { 1.87 + eof = true; 1.88 + return 0; 1.89 + } 1.90 + read_counter += 2; 1.91 + return v; 1.92 +} 1.93 + 1.94 +static uint32_t read_int32(FILE *fp) { 1.95 + uint32_t v; 1.96 + if(fread(&v, 4, 1, fp) <= 0) { 1.97 + eof = true; 1.98 + return 0; 1.99 + } 1.100 + read_counter += 4; 1.101 + return v; 1.102 +} 1.103 + 1.104 +static float read_float(FILE *fp) 1.105 +{ 1.106 + int32_t tmp = read_int32(fp); 1.107 + return *((float*)&tmp); 1.108 +} 1.109 + 1.110 +static Vector3 read_vector(FILE *file, bool flip_yz) 1.111 +{ 1.112 + Vector3 vector; 1.113 + vector.x = read_float(file); 1.114 + if(!flip_yz) vector.y = read_float(file); 1.115 + vector.z = read_float(file); 1.116 + if(flip_yz) vector.y = read_float(file); 1.117 + return vector; 1.118 +} 1.119 + 1.120 +static std::string read_string(FILE *file) 1.121 +{ 1.122 + std::string str; 1.123 + char c; 1.124 + while((c = (char)read_byte(file))) { 1.125 + str.push_back(c); 1.126 + } 1.127 + read_counter++; 1.128 + 1.129 + return str; 1.130 +} 1.131 + 1.132 +static ChunkHeader read_chunk_header(FILE *file) 1.133 +{ 1.134 + ChunkHeader chunk; 1.135 + chunk.id = (ChunkID)read_int16(file); 1.136 + chunk.size = read_int32(file); 1.137 + return chunk; 1.138 +} 1.139 + 1.140 +static void skip_chunk(FILE *file, const ChunkHeader &chunk) 1.141 +{ 1.142 + if(eof) return; 1.143 + fseek(file, chunk.size - HEADER_SIZE, SEEK_CUR); 1.144 + read_counter += chunk.size - HEADER_SIZE; 1.145 +} 1.146 + 1.147 +static Curve *read_curve(FILE *file, const ChunkHeader &ch) 1.148 +{ 1.149 + read_counter = HEADER_SIZE; // reset the global read counter 1.150 + 1.151 + std::string name = read_string(file); 1.152 + 1.153 + ChunkHeader chunk; 1.154 + chunk = read_chunk_header(file); 1.155 + if(chunk.id == Chunk_Obj_TriMesh) { 1.156 + // object is a trimesh... load it 1.157 + Vector3 *varray = 0; 1.158 + uint32_t vertex_count = 0; 1.159 + 1.160 + uint32_t obj_chunk_size = ch.size; 1.161 + 1.162 + while(read_counter < obj_chunk_size) { // make sure we only read subchunks of this object chunk 1.163 + chunk = read_chunk_header(file); 1.164 + 1.165 + switch(chunk.id) { 1.166 + case Chunk_TriMesh_VertexList: 1.167 + vertex_count = (uint32_t)read_int16(file); 1.168 + varray = new Vector3[vertex_count]; 1.169 + 1.170 + for(uint32_t i=0; i<vertex_count; i++) { 1.171 + varray[i] = read_vector(file); 1.172 + } 1.173 + 1.174 + break; 1.175 + 1.176 + case Chunk_TriMesh_FaceDesc: 1.177 + // it is a real object not a curve since it has triangles 1.178 + delete [] varray; 1.179 + varray = 0; 1.180 + break; 1.181 + 1.182 + default: 1.183 + skip_chunk(file, chunk); 1.184 + } 1.185 + } 1.186 + 1.187 + if(varray) { 1.188 + Curve *curve = new Curve; 1.189 + curve->set_name(name.c_str()); 1.190 + for(uint32_t i=0; i<vertex_count; i++) { 1.191 + curve->add_point(varray[i]); 1.192 + } 1.193 + return curve; 1.194 + } 1.195 + } 1.196 + 1.197 + return 0; 1.198 +}