goat3dgfx

view src/curveload.cc @ 34:3eb6c8f89fe1

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