goat3dgfx

view src/curveload.cc @ 13:25bf39105c82

lalal
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 27 Nov 2013 08:08:59 +0200
parents 1873dfd13f2d
children 7d6b667821cf
line source
1 #include <string>
2 #include <assert.h>
3 #include "curveload.h"
4 #include "3dschunks.h"
5 #include "logger.h"
7 #ifndef _MSC_VER
8 #include <stdint.h>
9 #else
10 typedef __int8 int8_t;
11 typedef __int16 int16_t;
12 typedef __int32 int32_t;
13 typedef unsigned __int8 uint8_t;
14 typedef unsigned __int16 uint16_t;
15 typedef unsigned __int32 uint32_t;
16 #endif
18 static uint32_t read_counter;
20 struct ChunkHeader {
21 ChunkID id;
22 uint32_t size;
23 };
25 #define HEADER_SIZE 6
27 // local function prototypes
28 static uint8_t read_byte(FILE *file);
29 static uint16_t read_int16(FILE *file);
30 static uint32_t read_int32(FILE *file);
31 static float read_float(FILE *file);
32 static Vector3 read_vector(FILE *file, bool flip_yz = false);
33 static std::string read_string(FILE *file);
34 static ChunkHeader read_chunk_header(FILE *file);
35 static void skip_chunk(FILE *file, const ChunkHeader &chunk);
36 static Curve *read_curve(FILE *file, const ChunkHeader &ch);
38 static bool eof;
40 bool load_curves(Scene *scn, const char *fname)
41 {
42 FILE *file = fopen(fname, "rb");
43 if(!file) {
44 error_log("failed to open curves scene file: %s\n", fname);
45 return false;
46 }
47 eof = false;
49 ChunkHeader chunk;
51 chunk = read_chunk_header(file);
52 if(chunk.id != Chunk_3DSMain) {
53 fclose(file);
54 return false;
55 }
57 while(!eof) {
58 chunk = read_chunk_header(file);
60 Curve *curve;
62 switch(chunk.id) {
63 case Chunk_Main_3DEditor:
64 break; // dont skip
66 case Chunk_Edit_Object:
67 if((curve = read_curve(file, chunk))) {
68 scn->curves.push_back(curve);
69 }
70 break;
72 default:
73 skip_chunk(file, chunk);
74 }
75 }
77 fclose(file);
78 return true;
79 }
81 static uint8_t read_byte(FILE *fp) {
82 uint8_t v;
83 if(fread(&v, 1, 1, fp) <= 0) {
84 eof = true;
85 return 0;
86 }
87 read_counter++;
88 return v;
89 }
91 static uint16_t read_int16(FILE *fp) {
92 uint16_t v;
93 if(fread(&v, 2, 1, fp) <= 0) {
94 eof = true;
95 return 0;
96 }
97 read_counter += 2;
98 return v;
99 }
101 static uint32_t read_int32(FILE *fp) {
102 uint32_t v;
103 if(fread(&v, 4, 1, fp) <= 0) {
104 eof = true;
105 return 0;
106 }
107 read_counter += 4;
108 return v;
109 }
111 static float read_float(FILE *fp)
112 {
113 int32_t tmp = read_int32(fp);
114 return *((float*)&tmp);
115 }
117 static Vector3 read_vector(FILE *file, bool flip_yz)
118 {
119 Vector3 vector;
120 vector.x = read_float(file);
121 if(!flip_yz) vector.y = read_float(file);
122 vector.z = read_float(file);
123 if(flip_yz) vector.y = read_float(file);
124 return vector;
125 }
127 static std::string read_string(FILE *file)
128 {
129 std::string str;
130 char c;
131 while((c = (char)read_byte(file))) {
132 str.push_back(c);
133 }
134 read_counter++;
136 return str;
137 }
139 static ChunkHeader read_chunk_header(FILE *file)
140 {
141 ChunkHeader chunk;
142 chunk.id = (ChunkID)read_int16(file);
143 chunk.size = read_int32(file);
144 return chunk;
145 }
147 static void skip_chunk(FILE *file, const ChunkHeader &chunk)
148 {
149 if(eof) return;
150 fseek(file, chunk.size - HEADER_SIZE, SEEK_CUR);
151 read_counter += chunk.size - HEADER_SIZE;
152 }
154 static Curve *read_curve(FILE *file, const ChunkHeader &ch)
155 {
156 read_counter = HEADER_SIZE; // reset the global read counter
158 std::string name = read_string(file);
160 ChunkHeader chunk;
161 chunk = read_chunk_header(file);
162 if(chunk.id == Chunk_Obj_TriMesh) {
163 // object is a trimesh... load it
164 Vector3 *varray = 0;
165 uint32_t vertex_count = 0;
167 uint32_t obj_chunk_size = ch.size;
169 while(read_counter < obj_chunk_size) { // make sure we only read subchunks of this object chunk
170 chunk = read_chunk_header(file);
172 switch(chunk.id) {
173 case Chunk_TriMesh_VertexList:
174 vertex_count = (uint32_t)read_int16(file);
175 varray = new Vector3[vertex_count];
177 for(uint32_t i=0; i<vertex_count; i++) {
178 varray[i] = read_vector(file);
179 }
181 break;
183 case Chunk_TriMesh_FaceDesc:
184 // it is a real object not a curve since it has triangles
185 delete [] varray;
186 varray = 0;
187 break;
189 default:
190 skip_chunk(file, chunk);
191 }
192 }
194 if(varray) {
195 Curve *curve = new Curve;
196 curve->set_name(name.c_str());
197 for(uint32_t i=0; i<vertex_count; i++) {
198 curve->add_point(varray[i]);
199 }
200 return curve;
201 }
202 }
204 return 0;
205 }