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