goat3dgfx

view src/curveload.cc @ 3:eb75bff21824

added convenience header file which includes everything else
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 16 Nov 2013 21:09:16 +0200
parents
children 7bd5ebec3b6f
line source
1 #include <string>
2 #include <assert.h>
3 #include <stdint.h>
4 #include "curveload.h"
5 #include "3dschunks.h"
6 #include "logger.h"
8 static uint32_t read_counter;
10 struct ChunkHeader {
11 ChunkID id;
12 uint32_t size;
13 };
15 #define HEADER_SIZE 6
17 // local function prototypes
18 static uint8_t read_byte(FILE *file);
19 static uint16_t read_int16(FILE *file);
20 static uint32_t read_int32(FILE *file);
21 static float read_float(FILE *file);
22 static Vector3 read_vector(FILE *file, bool flip_yz = false);
23 static std::string read_string(FILE *file);
24 static ChunkHeader read_chunk_header(FILE *file);
25 static void skip_chunk(FILE *file, const ChunkHeader &chunk);
26 static Curve *read_curve(FILE *file, const ChunkHeader &ch);
28 static bool eof;
30 bool load_curves(Scene *scn, const char *fname)
31 {
32 FILE *file = fopen(fname, "rb");
33 if(!file) {
34 error_log("failed to open curves scene file: %s\n", fname);
35 return false;
36 }
37 eof = false;
39 ChunkHeader chunk;
41 chunk = read_chunk_header(file);
42 if(chunk.id != Chunk_3DSMain) {
43 fclose(file);
44 return false;
45 }
47 while(!eof) {
48 chunk = read_chunk_header(file);
50 Curve *curve;
52 switch(chunk.id) {
53 case Chunk_Main_3DEditor:
54 break; // dont skip
56 case Chunk_Edit_Object:
57 if((curve = read_curve(file, chunk))) {
58 scn->curves.push_back(curve);
59 }
60 break;
62 default:
63 skip_chunk(file, chunk);
64 }
65 }
67 fclose(file);
68 return true;
69 }
71 static uint8_t read_byte(FILE *fp) {
72 uint8_t v;
73 if(fread(&v, 1, 1, fp) <= 0) {
74 eof = true;
75 return 0;
76 }
77 read_counter++;
78 return v;
79 }
81 static uint16_t read_int16(FILE *fp) {
82 uint16_t v;
83 if(fread(&v, 2, 1, fp) <= 0) {
84 eof = true;
85 return 0;
86 }
87 read_counter += 2;
88 return v;
89 }
91 static uint32_t read_int32(FILE *fp) {
92 uint32_t v;
93 if(fread(&v, 4, 1, fp) <= 0) {
94 eof = true;
95 return 0;
96 }
97 read_counter += 4;
98 return v;
99 }
101 static float read_float(FILE *fp)
102 {
103 int32_t tmp = read_int32(fp);
104 return *((float*)&tmp);
105 }
107 static Vector3 read_vector(FILE *file, bool flip_yz)
108 {
109 Vector3 vector;
110 vector.x = read_float(file);
111 if(!flip_yz) vector.y = read_float(file);
112 vector.z = read_float(file);
113 if(flip_yz) vector.y = read_float(file);
114 return vector;
115 }
117 static std::string read_string(FILE *file)
118 {
119 std::string str;
120 char c;
121 while((c = (char)read_byte(file))) {
122 str.push_back(c);
123 }
124 read_counter++;
126 return str;
127 }
129 static ChunkHeader read_chunk_header(FILE *file)
130 {
131 ChunkHeader chunk;
132 chunk.id = (ChunkID)read_int16(file);
133 chunk.size = read_int32(file);
134 return chunk;
135 }
137 static void skip_chunk(FILE *file, const ChunkHeader &chunk)
138 {
139 if(eof) return;
140 fseek(file, chunk.size - HEADER_SIZE, SEEK_CUR);
141 read_counter += chunk.size - HEADER_SIZE;
142 }
144 static Curve *read_curve(FILE *file, const ChunkHeader &ch)
145 {
146 read_counter = HEADER_SIZE; // reset the global read counter
148 std::string name = read_string(file);
150 ChunkHeader chunk;
151 chunk = read_chunk_header(file);
152 if(chunk.id == Chunk_Obj_TriMesh) {
153 // object is a trimesh... load it
154 Vector3 *varray = 0;
155 uint32_t vertex_count = 0;
157 uint32_t obj_chunk_size = ch.size;
159 while(read_counter < obj_chunk_size) { // make sure we only read subchunks of this object chunk
160 chunk = read_chunk_header(file);
162 switch(chunk.id) {
163 case Chunk_TriMesh_VertexList:
164 vertex_count = (uint32_t)read_int16(file);
165 varray = new Vector3[vertex_count];
167 for(uint32_t i=0; i<vertex_count; i++) {
168 varray[i] = read_vector(file);
169 }
171 break;
173 case Chunk_TriMesh_FaceDesc:
174 // it is a real object not a curve since it has triangles
175 delete [] varray;
176 varray = 0;
177 break;
179 default:
180 skip_chunk(file, chunk);
181 }
182 }
184 if(varray) {
185 Curve *curve = new Curve;
186 curve->set_name(name.c_str());
187 for(uint32_t i=0; i<vertex_count; i++) {
188 curve->add_point(varray[i]);
189 }
190 return curve;
191 }
192 }
194 return 0;
195 }