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