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