diff options
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ar/imp_ar_dof.c')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ar/imp_ar_dof.c | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ar/imp_ar_dof.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ar/imp_ar_dof.c new file mode 100644 index 0000000..6b2eff6 --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ar/imp_ar_dof.c | |||
@@ -0,0 +1,446 @@ | |||
1 | /* $Id$ */ | ||
2 | |||
3 | /* | ||
4 | libg3d - 3D object loading library | ||
5 | |||
6 | Copyright (C) 2005-2009 Markus Dahms <mad@automagically.de> | ||
7 | |||
8 | This library is free software; you can redistribute it and/or | ||
9 | modify it under the terms of the GNU Lesser General Public | ||
10 | License as published by the Free Software Foundation; either | ||
11 | version 2.1 of the License, or (at your option) any later version. | ||
12 | |||
13 | This library is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | Lesser General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU Lesser General Public | ||
19 | License along with this library; if not, write to the Free Software | ||
20 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | #include <g3d/types.h> | ||
24 | #include <g3d/stream.h> | ||
25 | #include <g3d/texture.h> | ||
26 | #include <g3d/material.h> | ||
27 | #include <g3d/iff.h> | ||
28 | |||
29 | gchar *ar_dof_read_string(G3DStream *stream, gint32 *dlen) | ||
30 | { | ||
31 | gint32 len; | ||
32 | gchar *text; | ||
33 | |||
34 | len = g3d_stream_read_int16_le(stream); | ||
35 | *dlen -= 2; | ||
36 | |||
37 | text = g_new0(gchar, len + 1); | ||
38 | g3d_stream_read(stream, text, len); | ||
39 | *dlen -= len; | ||
40 | |||
41 | return text; | ||
42 | } | ||
43 | |||
44 | G3DMaterial *ar_dof_load_mat(G3DContext *context, G3DModel *model, | ||
45 | G3DStream *stream) | ||
46 | { | ||
47 | G3DMaterial *material; | ||
48 | gint32 id, len = 0, dlen, i, ntex, trans = 0, blend = 0; | ||
49 | gchar *tmp; | ||
50 | |||
51 | id = g3d_stream_read_int32_be(stream); | ||
52 | if(id != G3D_IFF_MKID('M','A','T','0')) | ||
53 | return NULL; | ||
54 | |||
55 | material = g3d_material_new(); | ||
56 | |||
57 | dlen = g3d_stream_read_int32_le(stream); | ||
58 | do { | ||
59 | id = g3d_stream_read_int32_be(stream); | ||
60 | if(id != G3D_IFF_MKID('M','E','N','D')) | ||
61 | len = g3d_stream_read_int32_le(stream); | ||
62 | |||
63 | switch(id) { | ||
64 | case G3D_IFF_MKID('M','E','N','D'): | ||
65 | break; | ||
66 | |||
67 | case G3D_IFF_MKID('M','H','D','R'): | ||
68 | material->name = ar_dof_read_string(stream, &dlen); | ||
69 | tmp = ar_dof_read_string(stream, &dlen); | ||
70 | g_free(tmp); | ||
71 | break; | ||
72 | |||
73 | case G3D_IFF_MKID('M','C','O','L'): | ||
74 | /* ambient */ | ||
75 | material->r = g3d_stream_read_float_le(stream); | ||
76 | material->g = g3d_stream_read_float_le(stream); | ||
77 | material->b = g3d_stream_read_float_le(stream); | ||
78 | material->a = g3d_stream_read_float_le(stream); | ||
79 | dlen -= 16; | ||
80 | /* diffuse */ | ||
81 | g3d_stream_skip(stream, 16); | ||
82 | dlen -= 16; | ||
83 | /* specular */ | ||
84 | material->specular[0] = g3d_stream_read_float_le(stream); | ||
85 | material->specular[1] = g3d_stream_read_float_le(stream); | ||
86 | material->specular[2] = g3d_stream_read_float_le(stream); | ||
87 | material->specular[3] = g3d_stream_read_float_le(stream); | ||
88 | dlen -= 16; | ||
89 | /* emission */ | ||
90 | g3d_stream_skip(stream, 16); | ||
91 | dlen -= 16; | ||
92 | /* shininess */ | ||
93 | material->shininess = g3d_stream_read_float_le(stream); | ||
94 | dlen -= 4; | ||
95 | break; | ||
96 | |||
97 | case G3D_IFF_MKID('M','T','E','X'): | ||
98 | ntex = g3d_stream_read_int32_le(stream); | ||
99 | dlen -= 4; | ||
100 | for(i = 0; i < ntex; i ++) { | ||
101 | tmp = ar_dof_read_string(stream, &dlen); | ||
102 | if(i == 0) { | ||
103 | material->tex_image = | ||
104 | g3d_texture_load_cached(context, model, tmp); | ||
105 | if(material->tex_image) | ||
106 | material->tex_image->tex_id = g_str_hash(tmp); | ||
107 | } | ||
108 | g_free(tmp); | ||
109 | } | ||
110 | break; | ||
111 | |||
112 | case G3D_IFF_MKID('M','T','R','A'): | ||
113 | /* transparency */ | ||
114 | trans = g3d_stream_read_int32_le(stream); | ||
115 | /* blend mode */ | ||
116 | blend = g3d_stream_read_int32_le(stream); | ||
117 | |||
118 | printf("D: MTRA: %s: trans: 0x%04x, blend: 0x%04x\n", | ||
119 | (material->name ? material->name : "unnamed"), | ||
120 | trans, blend); | ||
121 | |||
122 | dlen -= 8; | ||
123 | break; | ||
124 | |||
125 | case G3D_IFF_MKID('M','C','F','L'): | ||
126 | /* creation flags */ | ||
127 | g3d_stream_read_int32_le(stream); | ||
128 | dlen -= 4; | ||
129 | break; | ||
130 | |||
131 | case G3D_IFF_MKID('M','U','V','W'): | ||
132 | /* u offset */ | ||
133 | g3d_stream_read_int32_le(stream); | ||
134 | /* v offset */ | ||
135 | g3d_stream_read_int32_le(stream); | ||
136 | dlen -= 8; | ||
137 | |||
138 | /* u tiling */ | ||
139 | g3d_stream_read_int32_le(stream); | ||
140 | /* v tiling */ | ||
141 | g3d_stream_read_int32_le(stream); | ||
142 | dlen -= 8; | ||
143 | |||
144 | /* angle */ | ||
145 | g3d_stream_read_float_le(stream); | ||
146 | /* blur */ | ||
147 | g3d_stream_read_float_le(stream); | ||
148 | /* blur offset */ | ||
149 | g3d_stream_read_int32_le(stream); | ||
150 | dlen -= 12; | ||
151 | break; | ||
152 | |||
153 | default: | ||
154 | g3d_stream_skip(stream, len); | ||
155 | dlen -= len; | ||
156 | break; | ||
157 | } | ||
158 | } | ||
159 | while((dlen > 0) && (id != G3D_IFF_MKID('M','E','N','D'))); | ||
160 | |||
161 | if(material->tex_image != NULL) { | ||
162 | if(blend == 1) | ||
163 | material->tex_image->tex_env = G3D_TEXENV_BLEND; | ||
164 | else | ||
165 | material->tex_image->tex_env = G3D_TEXENV_DECAL; | ||
166 | } | ||
167 | |||
168 | return material; | ||
169 | } | ||
170 | |||
171 | G3DObject *ar_dof_load_obj(G3DContext *context, G3DModel *model, | ||
172 | G3DStream *stream) | ||
173 | { | ||
174 | G3DObject *object, *pobj; | ||
175 | G3DFace *face; | ||
176 | G3DMaterial *material; | ||
177 | GSList *item; | ||
178 | gint32 id, len = 0, dlen, nverts, ntver, nnorm, nind, i, j, index; | ||
179 | G3DFloat *tex_vertices = NULL, *normals = NULL; | ||
180 | |||
181 | id = g3d_stream_read_int32_be(stream); | ||
182 | dlen = g3d_stream_read_int32_le(stream); | ||
183 | |||
184 | if(id != G3D_IFF_MKID('G','O','B','1')) { | ||
185 | g3d_stream_skip(stream, dlen); | ||
186 | return NULL; | ||
187 | } | ||
188 | |||
189 | object = g_new0(G3DObject, 1); | ||
190 | object->name = g_strdup_printf("object @ 0x%08x", | ||
191 | (guint32)g3d_stream_tell(stream)); | ||
192 | |||
193 | /* parent object for material references */ | ||
194 | pobj = (G3DObject *)g_slist_nth_data(model->objects, 0); | ||
195 | |||
196 | /* default material */ | ||
197 | material = (G3DMaterial *)g_slist_nth_data(model->materials, 0); | ||
198 | |||
199 | do { | ||
200 | id = g3d_stream_read_int32_be(stream); | ||
201 | if(id != G3D_IFF_MKID('G','E','N','D')) | ||
202 | len = g3d_stream_read_int32_le(stream); | ||
203 | |||
204 | switch(id) { | ||
205 | case G3D_IFF_MKID('G','E','N','D'): | ||
206 | /* end of object */ | ||
207 | break; | ||
208 | |||
209 | case G3D_IFF_MKID('G','H','D','R'): | ||
210 | /* object header */ | ||
211 | /* flags */ | ||
212 | i = g3d_stream_read_int32_le(stream); | ||
213 | printf("D: GHDR: flags = 0x%04X\n", i); | ||
214 | /* paint flags */ | ||
215 | i = g3d_stream_read_int32_le(stream); | ||
216 | printf("D: GHDR: paint flags = 0x%04X\n", i); | ||
217 | |||
218 | /* material ref */ | ||
219 | i = g3d_stream_read_int32_le(stream); | ||
220 | material = g_slist_nth_data(pobj->materials, i); | ||
221 | if(material == NULL) | ||
222 | material = (G3DMaterial *)g_slist_nth_data( | ||
223 | model->materials, 0); | ||
224 | |||
225 | dlen -= 12; | ||
226 | break; | ||
227 | |||
228 | case G3D_IFF_MKID('V','E','R','T'): | ||
229 | /* vertices */ | ||
230 | nverts = g3d_stream_read_int32_le(stream); | ||
231 | |||
232 | #if DEBUG > 2 | ||
233 | printf("D: %d vertices\n", nverts); | ||
234 | #endif | ||
235 | |||
236 | dlen -= 4; | ||
237 | if(nverts > 0) { | ||
238 | object->vertex_count = nverts; | ||
239 | object->vertex_data = g_new0(G3DFloat, nverts * 3); | ||
240 | for(i = 0; i < nverts; i ++) { | ||
241 | for(j = 0; j < 3; j ++) | ||
242 | object->vertex_data[i * 3 + j] = | ||
243 | g3d_stream_read_float_le(stream); | ||
244 | dlen -= 12; | ||
245 | } | ||
246 | } | ||
247 | break; | ||
248 | |||
249 | case G3D_IFF_MKID('N', 'O','R','M'): | ||
250 | /* normals */ | ||
251 | nnorm = g3d_stream_read_int32_le(stream); | ||
252 | normals = g_new0(G3DFloat, nnorm * 3); | ||
253 | dlen -= 4; | ||
254 | for(i = 0; i < nnorm; i ++) { | ||
255 | for(j = 0; j < 3; j ++) | ||
256 | normals[i * 3 + j] = g3d_stream_read_float_le(stream); | ||
257 | dlen -= 12; | ||
258 | } | ||
259 | break; | ||
260 | |||
261 | case G3D_IFF_MKID('T', 'V','E','R'): | ||
262 | /* texture vertices */ | ||
263 | ntver = g3d_stream_read_int32_le(stream); | ||
264 | tex_vertices = g_new0(G3DFloat, ntver * 2); | ||
265 | dlen -= 4; | ||
266 | |||
267 | #if DEBUG > 2 | ||
268 | printf("D: %d texture vertices @ 0x%08x\n", ntver, | ||
269 | (guint32)g3d_stream_tell(stream) - 12); | ||
270 | #endif | ||
271 | |||
272 | for(i = 0; (i < ntver) && (len > 0); i ++) { | ||
273 | tex_vertices[i * 2 + 0] = g3d_stream_read_float_le(stream); | ||
274 | tex_vertices[i * 2 + 1] = | ||
275 | 1.0 - g3d_stream_read_float_le(stream); | ||
276 | dlen -= 8; | ||
277 | } | ||
278 | break; | ||
279 | |||
280 | case G3D_IFF_MKID('B','R','S','T'): | ||
281 | /* bursts */ | ||
282 | i = g3d_stream_read_int32_le(stream); | ||
283 | dlen -= 4; | ||
284 | g3d_stream_skip(stream, i * 4); /* burstStart */ | ||
285 | g3d_stream_skip(stream, i * 4); /* burstCount */ | ||
286 | g3d_stream_skip(stream, i * 4); /* burstMtlID */ | ||
287 | g3d_stream_skip(stream, i * 4); /* burstVperP */ | ||
288 | dlen -= (4 * 4 * i); | ||
289 | break; | ||
290 | |||
291 | case G3D_IFF_MKID('V','C','O','L'): | ||
292 | /* vertex colors */ | ||
293 | i = g3d_stream_read_int32_le(stream); | ||
294 | dlen -= 4; | ||
295 | g3d_stream_skip(stream, i * 4 * 3); | ||
296 | dlen -= (i * 4 * 3); | ||
297 | break; | ||
298 | |||
299 | case G3D_IFF_MKID('I','N','D','I'): | ||
300 | /* indices */ | ||
301 | nind = g3d_stream_read_int32_le(stream); | ||
302 | dlen -= 4; | ||
303 | len -= 4; | ||
304 | |||
305 | #if DEBUG > 2 | ||
306 | printf("D: %d indices in %d bytes\n", nind, len); | ||
307 | #endif | ||
308 | |||
309 | for(i = 0; i < nind; i += 3) { | ||
310 | face = g_new0(G3DFace, 1); | ||
311 | face->material = material; | ||
312 | face->vertex_count = 3; | ||
313 | face->vertex_indices = g_new0(guint32, 3); | ||
314 | |||
315 | for(j = 0; j < 3; j ++) | ||
316 | face->vertex_indices[j] = | ||
317 | g3d_stream_read_int16_le(stream); | ||
318 | dlen -= 6; | ||
319 | len -= 6; | ||
320 | |||
321 | object->faces = g_slist_append(object->faces, face); | ||
322 | } | ||
323 | break; | ||
324 | |||
325 | default: | ||
326 | #if DEBUG > 0 | ||
327 | printf("D: skipping tag '%c%c%c%c @ 0x%08x'\n", | ||
328 | (id << 24) & 0xFF, (id << 16) & 0xFF, | ||
329 | (id << 8) & 0xFF, id & 0xFF, | ||
330 | (guint32)g3d_stream_tell(stream)); | ||
331 | #endif | ||
332 | g3d_stream_skip(stream, len); | ||
333 | dlen -= len; | ||
334 | break; | ||
335 | } | ||
336 | } while((dlen > 0) && (id != G3D_IFF_MKID('G','E','N','D'))); | ||
337 | |||
338 | /* fix faces with normals and texture vertices */ | ||
339 | for(item = object->faces; item != NULL; item = item->next) { | ||
340 | face = (G3DFace *)item->data; | ||
341 | |||
342 | if(tex_vertices != NULL) { | ||
343 | face->tex_image = material->tex_image; | ||
344 | face->tex_vertex_count = 3; | ||
345 | face->tex_vertex_data = g_new0(G3DFloat, 3 * 2); | ||
346 | for(j = 0; j < 3; j ++) { | ||
347 | index = face->vertex_indices[j]; | ||
348 | face->tex_vertex_data[j * 2 + 0] = tex_vertices[index * 2 + 0]; | ||
349 | face->tex_vertex_data[j * 2 + 1] = tex_vertices[index * 2 + 1]; | ||
350 | } | ||
351 | if(face->tex_image != NULL) | ||
352 | face->flags |= G3D_FLAG_FAC_TEXMAP; | ||
353 | } | ||
354 | |||
355 | if(normals != NULL) { | ||
356 | face->normals = g_new0(G3DFloat, 3 * 3); | ||
357 | for(j = 0; j < 3; j ++) { | ||
358 | index = face->vertex_indices[j]; | ||
359 | face->normals[j * 3 + 0] = normals[index * 3 + 0]; | ||
360 | face->normals[j * 3 + 1] = normals[index * 3 + 1]; | ||
361 | face->normals[j * 3 + 2] = normals[index * 3 + 2]; | ||
362 | } | ||
363 | face->flags |= G3D_FLAG_FAC_NORMALS; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | /* cleanup */ | ||
368 | if(tex_vertices != NULL) | ||
369 | g_free(tex_vertices); | ||
370 | |||
371 | if(normals != NULL) | ||
372 | g_free(normals); | ||
373 | |||
374 | return object; | ||
375 | } | ||
376 | |||
377 | G3DObject *ar_dof_load(G3DContext *context, G3DModel *model, | ||
378 | G3DStream *stream) | ||
379 | { | ||
380 | gint32 id, dlen, len = 0, nmat, nobj, i; | ||
381 | G3DObject *object, *cobj; | ||
382 | G3DMaterial *material; | ||
383 | |||
384 | /* file is little-endian, but read IDs as big-endian to use | ||
385 | * G3D_IFF_MKID to compare */ | ||
386 | |||
387 | id = g3d_stream_read_int32_be(stream); | ||
388 | if(id != G3D_IFF_MKID('D','O','F','1')) { | ||
389 | g_warning("%s is not a DOF1 file\n", stream->uri); | ||
390 | return NULL; | ||
391 | } | ||
392 | dlen = g3d_stream_read_int32_le(stream); | ||
393 | |||
394 | object = g_new0(G3DObject, 1); | ||
395 | object->name = g_strdup(stream->uri); | ||
396 | model->objects = g_slist_append(model->objects, object); | ||
397 | |||
398 | do { | ||
399 | id = g3d_stream_read_int32_be(stream); | ||
400 | if(id != G3D_IFF_MKID('E','D','O','F')) | ||
401 | len = g3d_stream_read_int32_le(stream); | ||
402 | dlen -= 8; | ||
403 | |||
404 | switch(id) { | ||
405 | case G3D_IFF_MKID('E','D','O','F'): | ||
406 | /* end of DOF */ | ||
407 | break; | ||
408 | |||
409 | case G3D_IFF_MKID('M','A','T','S'): | ||
410 | nmat = g3d_stream_read_int32_le(stream); | ||
411 | for(i = 0; i < nmat; i ++) { | ||
412 | material = ar_dof_load_mat(context, model, stream); | ||
413 | if(material) | ||
414 | object->materials = g_slist_append(object->materials, | ||
415 | material); | ||
416 | } | ||
417 | dlen -= len; | ||
418 | break; | ||
419 | |||
420 | case G3D_IFF_MKID('G','E','O','B'): | ||
421 | nobj = g3d_stream_read_int32_le(stream); | ||
422 | for(i = 0; i < nobj; i ++) { | ||
423 | cobj = ar_dof_load_obj(context, model, stream); | ||
424 | if(cobj) | ||
425 | object->objects = | ||
426 | g_slist_append(object->objects, cobj); | ||
427 | } | ||
428 | dlen -= len; | ||
429 | break; | ||
430 | |||
431 | default: | ||
432 | g_warning("DOF: unknown ID '%c%c%c%c' @ 0x%08x", | ||
433 | (id >> 24) & 0xFF, (id >> 16) & 0xFF, | ||
434 | (id >> 8) & 0xFF, id & 0xFF, | ||
435 | (guint32)g3d_stream_tell(stream) - 8); | ||
436 | g3d_stream_skip(stream, len); | ||
437 | dlen -= len; | ||
438 | break; | ||
439 | } | ||
440 | } while((dlen > 0) && | ||
441 | (id != G3D_IFF_MKID('E','D','O','F')) && | ||
442 | (!g3d_stream_eof(stream))); | ||
443 | |||
444 | return object; | ||
445 | } | ||
446 | |||