aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_q3o/imp_q3o.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_q3o/imp_q3o.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_q3o/imp_q3o.c586
1 files changed, 586 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_q3o/imp_q3o.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_q3o/imp_q3o.c
new file mode 100644
index 0000000..b8d83a4
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_q3o/imp_q3o.c
@@ -0,0 +1,586 @@
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 <stdio.h>
24#include <string.h>
25
26#include <g3d/types.h>
27#include <g3d/context.h>
28#include <g3d/material.h>
29#include <g3d/stream.h>
30
31/*
32 * format description:
33 * http://www.quick3d.com/guide/guidec.html
34 */
35
36static void q3o_update_face_textures(G3DModel *model, G3DContext *context);
37static gboolean q3o_read_mesh(G3DStream *stream, G3DModel *model,
38 guint32 n_textures, G3DContext *context);
39static gboolean q3o_read_material(G3DStream *stream, G3DModel *model,
40 guint32 index, guint32 n_textures);
41static gboolean q3o_read_texture(G3DStream *stream, G3DModel *model,
42 guint32 *idx);
43static gboolean q3o_read_scene(G3DStream *stream, G3DContext *context);
44static gboolean q3o_read_eof(G3DStream *stream);
45
46EAPI
47gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream,
48 G3DModel *model, gpointer user_data)
49{
50 gchar signature[8], ver_min, ver_maj, id;
51 guint32 nmeshes, nmats, ntexs, i, tex_index = 0;
52
53 g3d_stream_read(stream, signature, 8);
54 if(strncmp(signature, "quick3Ds", 8) && strncmp(signature, "quick3Do", 8))
55 {
56 g_warning("file '%s' is not a Quick3D file", stream->uri);
57 return FALSE;
58 }
59
60 ver_maj = g3d_stream_read_int8(stream);
61 ver_min = g3d_stream_read_int8(stream);
62#if DEBUG > 0
63 g_debug("Q3O: version %c.%c", ver_maj, ver_min);
64#endif
65
66 nmeshes = g3d_stream_read_int32_le(stream);
67 nmats = g3d_stream_read_int32_le(stream);
68 ntexs = g3d_stream_read_int32_le(stream);
69#if DEBUG > 0
70 g_debug("Q3O: %d meshes, %d materials, %d textures",
71 nmeshes, nmats, ntexs);
72#endif
73
74 /* generate (emtpy) materials */
75 for(i = 0; i < nmats; i ++) {
76 G3DMaterial *material = g3d_material_new();
77 model->materials = g_slist_append(model->materials, material);
78 }
79
80 while((id = g3d_stream_read_int8(stream)) != 0) {
81#if DEBUG > 0
82 g_debug("Q3O: chunk type 0x%02x @ 0x%08x", id,
83 (guint32)g3d_stream_tell(stream) - 1);
84#endif
85 switch(id) {
86 case 'm': /* mesh */
87 for(i = 0; i < nmeshes; i ++)
88 q3o_read_mesh(stream, model, ntexs, context);
89 break;
90
91 case 'c': /* material */
92 for(i = 0; i < nmats; i ++)
93 q3o_read_material(stream, model, i, ntexs);
94 break;
95
96 case 't': /* texture */
97 for(i = 0; i < ntexs; i ++)
98 q3o_read_texture(stream, model, &tex_index);
99 break;
100
101 case 's': /* scene */
102 q3o_read_scene(stream, context);
103 break;
104
105 case 'q': /* EOF signature? */
106 q3o_read_eof(stream);
107 break;
108
109 default:
110 g_warning("Q3O: unknown chunk type 0x%02x\n", id);
111 return TRUE;
112 break;
113 }
114 }
115
116 /* update texture images */
117 q3o_update_face_textures(model, context);
118
119 return TRUE;
120}
121
122EAPI
123gchar *plugin_description(void)
124{
125 return g_strdup("Quick3D models.");
126}
127
128EAPI
129gchar **plugin_extensions(void)
130{
131 return g_strsplit("q3o:q3s", ":", 0);
132}
133
134/*
135 * Q3O specific stuff
136 */
137
138static void q3o_update_face_textures(G3DModel *model, G3DContext *context)
139{
140 GSList *oitem, *fitem;
141 G3DObject *object;
142 G3DFace *face;
143
144 oitem = model->objects;
145 while(oitem)
146 {
147 object = (G3DObject *)oitem->data;
148 fitem = object->faces;
149 while(fitem)
150 {
151 face = (G3DFace *)fitem->data;
152 face->tex_image = face->material->tex_image;
153 if(face->tex_image && face->tex_image->width)
154 face->flags |= G3D_FLAG_FAC_TEXMAP;
155 else
156 {
157 face->tex_vertex_count = 0;
158 if(face->tex_vertex_data)
159 g_free(face->tex_vertex_data);
160 }
161 fitem = fitem->next;
162 }
163
164 g3d_context_update_interface(context);
165 oitem = oitem->next;
166 }
167}
168
169static G3DImage *q3o_get_texture_nth(G3DModel *model, guint32 n)
170{
171 gchar number[32];
172 G3DImage *image;
173
174 if(model->tex_images == NULL)
175 model->tex_images = g_hash_table_new(g_str_hash, g_str_equal);
176
177#if DEBUG > 5
178 g_debug("Q3O: texture #%d wanted", n);
179#endif
180
181 sprintf(number, "%d", n);
182 image = g_hash_table_lookup(model->tex_images, number);
183 if(image) {
184#if DEBUG > 5
185 g_debug("Q3O: texture #%d from hash table", n);
186#endif
187 return image;
188 }
189
190#if DEBUG > 5
191 g_debug("Q3O: texture #%d created", n);
192#endif
193
194 image = g_new0(G3DImage, 1);
195 image->tex_scale_u = 1.0;
196 image->tex_scale_v = 1.0;
197 image->name = g_strdup_printf("would be %d", n + 1);
198
199 g_hash_table_insert(model->tex_images, g_strdup(number), image);
200
201 return image;
202}
203
204static gboolean q3o_read_mesh(G3DStream *stream, G3DModel *model,
205 guint32 n_textures, G3DContext *context)
206{
207 guint32 i, j, nfaces, mat, nnormals, ntexco, index, nfaceverts = 0;
208 guint16 *faceshapes;
209 G3DFloat *normals;
210 GSList *fitem;
211 G3DObject *object;
212 G3DFace *face;
213 G3DMaterial *material;
214
215 object = g_new0(G3DObject, 1);
216 object->name = g_strdup("Q3O mesh");
217 model->objects = g_slist_append(model->objects, object);
218
219 material = g3d_material_new();
220 material->name = g_strdup("fallback material");
221 object->materials = g_slist_append(object->materials, material);
222
223 /* vertices */
224 object->vertex_count = g3d_stream_read_int32_le(stream);
225#if DEBUG > 3
226 g_debug("Q3O: number of vertices: %d", object->vertex_count);
227#endif
228 object->vertex_data = g_new0(G3DFloat,object->vertex_count * 3);
229 for(i = 0; i < object->vertex_count; i ++)
230 {
231 object->vertex_data[i*3+0] = g3d_stream_read_float_le(stream);
232 object->vertex_data[i*3+1] = g3d_stream_read_float_le(stream);
233 object->vertex_data[i*3+2] = g3d_stream_read_float_le(stream);
234
235 g3d_context_update_interface(context);
236 }
237
238 /* faces */
239 nfaces = g3d_stream_read_int32_le(stream);
240#if DEBUG > 3
241 g_debug("Q3O: number of faces: %d", nfaces);
242#endif
243 faceshapes = g_new0(guint16, nfaces);
244 for(i = 0; i < nfaces; i ++)
245 {
246 faceshapes[i] = g3d_stream_read_int16_le(stream);
247 nfaceverts += faceshapes[i];
248
249 g3d_context_update_interface(context);
250 }
251
252 for(i = 0; i < nfaces; i ++)
253 {
254 face = g_new0(G3DFace, 1);
255 face->vertex_count = faceshapes[i];
256 face->vertex_indices = g_new0(guint32, face->vertex_count);
257 for(j = 0; j < face->vertex_count; j ++)
258 {
259 face->vertex_indices[j] = g3d_stream_read_int32_le(stream);
260 if(face->vertex_indices[j] >= object->vertex_count)
261 {
262 g_warning("Q3O: vertex_indices >= vertex_count");
263 }
264
265 g3d_context_update_interface(context);
266 }
267 /* fallback material */
268 face->material = (G3DMaterial *)g_slist_nth_data(object->materials, 0);
269 g_assert(face->material);
270
271 object->faces = g_slist_append(object->faces, face);
272
273 g3d_context_update_interface(context);
274 }
275
276 /* material indices */
277 fitem = object->faces;
278 for(i = 0; i < nfaces; i ++)
279 {
280 face = (G3DFace *)fitem->data;
281 g_assert(face != NULL);
282 mat = g3d_stream_read_int32_le(stream);
283 face->material = (G3DMaterial*)g_slist_nth_data(model->materials, mat);
284 if(face->material == NULL)
285 {
286 if(mat != -1) g_warning("Q3O: material is NULL (index %d)", mat);
287 face->material = g_slist_nth_data(object->materials, 0);
288 }
289
290 g3d_context_update_interface(context);
291 fitem = fitem->next;
292 }
293
294 /* normals */
295 nnormals = g3d_stream_read_int32_le(stream);
296 normals = g_new0(G3DFloat, nnormals * 3);
297#if DEBUG > 3
298 g_debug("Q3O: number of normals: %d", nnormals);
299#endif
300 for(i = 0; i < nnormals; i ++) {
301 normals[i * 3 + 0] = g3d_stream_read_float_le(stream);
302 normals[i * 3 + 1] = g3d_stream_read_float_le(stream);
303 normals[i * 3 + 2] = g3d_stream_read_float_le(stream);
304
305 g3d_context_update_interface(context);
306 }
307
308 /* update faces */
309 if(object->vertex_count == nnormals) {
310 fitem = object->faces;
311 for(i = 0; i < nfaces; i ++) {
312 face = (G3DFace *)fitem->data;
313 face->normals = g_new0(G3DFloat, faceshapes[i] * 3);
314 face->flags |= G3D_FLAG_FAC_NORMALS;
315 for(j = 0; j < faceshapes[i]; j ++)
316 {
317 face->normals[j * 3 + 0] =
318 normals[face->vertex_indices[j] * 3 + 0];
319 face->normals[j * 3 + 1] =
320 normals[face->vertex_indices[j] * 3 + 1];
321 face->normals[j * 3 + 2] =
322 normals[face->vertex_indices[j] * 3 + 2];
323 }
324
325 g3d_context_update_interface(context);
326 fitem = fitem->next;
327 }
328
329 }
330
331 /* texture stuff */
332 ntexco = g3d_stream_read_int32_le(stream);
333#if DEBUG > 3
334 g_debug("Q3O: number of texture coordinates: %d", ntexco);
335#endif
336 if(n_textures > 0)
337 {
338 object->tex_vertex_count = ntexco;
339 object->tex_vertex_data = g_new0(G3DFloat, 2 * ntexco);
340
341 for(i = 0; i < ntexco; i ++)
342 {
343 object->tex_vertex_data[i * 2 + 0] = g3d_stream_read_float_le(stream);
344 object->tex_vertex_data[i * 2 + 1] = g3d_stream_read_float_le(stream);
345 }
346
347 fitem = object->faces;
348 for(i = 0; i < nfaces; i ++)
349 {
350 face = (G3DFace *)fitem->data;
351 face->tex_vertex_count = faceshapes[i];
352 face->tex_vertex_data = g_new0(G3DFloat, faceshapes[i] * 2);
353 for(j = 0; j < faceshapes[i]; j ++)
354 {
355 index = g3d_stream_read_int32_le(stream);
356 face->tex_vertex_data[j * 2 + 0] =
357 object->tex_vertex_data[face->vertex_indices[j] * 2 + 0];
358 face->tex_vertex_data[j * 2 + 1] =
359 object->tex_vertex_data[face->vertex_indices[j] * 2 + 1];
360 }
361
362 g3d_context_update_interface(context);
363 fitem = fitem->next;
364 }
365 }
366
367 /* centerOfMass */
368 g3d_stream_read_float_le(stream);
369 g3d_stream_read_float_le(stream);
370 g3d_stream_read_float_le(stream);
371
372 /* boundingBox */
373 g3d_stream_read_float_le(stream);
374 g3d_stream_read_float_le(stream);
375 g3d_stream_read_float_le(stream);
376
377 g3d_stream_read_float_le(stream);
378 g3d_stream_read_float_le(stream);
379 g3d_stream_read_float_le(stream);
380
381 /* clean up */
382 g_free(faceshapes);
383 if(object->tex_vertex_data)
384 {
385 /* should be in faces */
386 g_free(object->tex_vertex_data);
387 object->tex_vertex_data = NULL;
388 }
389 if(normals)
390 g_free(normals);
391
392 g3d_context_update_interface(context);
393
394 return TRUE;
395}
396
397static gboolean q3o_read_material(G3DStream *stream, G3DModel *model,
398 guint32 index, guint32 n_textures)
399{
400 gchar buffer[2048], *bufp;
401 G3DMaterial *material;
402 gint32 num;
403
404 material = g_slist_nth_data(model->materials, index);
405 memset(buffer, 0, 2048);
406 bufp = buffer;
407 while((*bufp = g3d_stream_read_int8(stream)) != '\0') bufp ++;
408 material->name = g_strdup(buffer);
409#if DEBUG > 0
410 g_debug("Q3O: material name: '%s'", buffer);
411#endif
412
413 /* ambientColor */
414 material->r = g3d_stream_read_float_le(stream);
415 material->g = g3d_stream_read_float_le(stream);
416 material->b = g3d_stream_read_float_le(stream);
417
418 /* diffuseColor */
419 material->r = g3d_stream_read_float_le(stream);
420 material->g = g3d_stream_read_float_le(stream);
421 material->b = g3d_stream_read_float_le(stream);
422
423 /* specularColor */
424 material->specular[0] = g3d_stream_read_float_le(stream);
425 material->specular[1] = g3d_stream_read_float_le(stream);
426 material->specular[2] = g3d_stream_read_float_le(stream);
427
428 /* transparency */
429 material->a = g3d_stream_read_float_le(stream);
430 if(material->a == 0.0) material->a = 1.0;
431 if(material->a < 0.1) material->a = 0.1;
432
433 /* texture */
434 num = g3d_stream_read_int32_le(stream);
435#if DEBUG > 4
436 g_debug("Q3O: material unknown uint32: %d", num);
437#endif
438 if((num != -1) && (num < n_textures))
439 material->tex_image = q3o_get_texture_nth(model, num);
440
441 return TRUE;
442}
443
444static gboolean q3o_read_texture(G3DStream *stream, G3DModel *model,
445 guint32 *idx)
446{
447 G3DImage *image;
448 gchar buffer[2048], *bufp;
449#if DEBUG > 2
450 gchar *ppmname;
451#endif
452 guint32 width, height, y, x;
453
454 memset(buffer, 0, 2048);
455 bufp = buffer;
456 while((*bufp = g3d_stream_read_int8(stream)) != '\0')
457 bufp ++;
458
459 width = g3d_stream_read_int32_le(stream);
460 height = g3d_stream_read_int32_le(stream);
461#if DEBUG > 0
462 g_debug("Q3O: texture #%d '%s': %dx%d", *idx, buffer, width, height);
463#endif
464
465 image = q3o_get_texture_nth(model, *idx);
466 (*idx) ++;
467
468 image->name = g_strdup(buffer);
469 image->width = width;
470 image->height = height;
471 image->depth = 32;
472 image->pixeldata = g_new0(guint8, width * height * 4);
473 image->tex_id = *idx;
474
475 for(y = 0; y < height; y ++)
476 for(x = 0; x < width; x ++) {
477 image->pixeldata[(y * width + x) * 4 + 0] =
478 g3d_stream_read_int8(stream);
479 image->pixeldata[(y * width + x) * 4 + 1] =
480 g3d_stream_read_int8(stream);
481 image->pixeldata[(y * width + x) * 4 + 2] =
482 g3d_stream_read_int8(stream);
483 image->pixeldata[(y * width + x) * 4 + 3] = 0xFF;
484 }
485
486#if DEBUG > 2
487 ppmname = g_strdup_printf("/tmp/%s.ppm", image->name);
488 g3d_image_dump_ppm(image, ppmname);
489 g_free(ppmname);
490#endif
491 return TRUE;
492}
493
494static gboolean q3o_read_scene(G3DStream *stream, G3DContext *context)
495{
496 gchar buffer[2048], *bufp;
497 guint32 bgw, bgh;
498 /* position: 3 x float */
499
500 g3d_stream_skip(stream, 12);
501
502 /* transformation: matrix */
503 g3d_stream_skip(stream, 64);
504
505 /* axis: 3 x float */
506 g3d_stream_skip(stream, 12);
507
508 /* angle: float */
509 g3d_stream_skip(stream, 4);
510
511 /* eyePosition: 3 x float */
512 g3d_stream_skip(stream, 12);
513
514 /* eyeRotation: 3 x float */
515 g3d_stream_skip(stream, 12);
516
517 /* foregroundColor: color */
518 g3d_stream_skip(stream, 12);
519
520 /* backgroundColor: color */
521 g3d_context_set_bgcolor(context,
522 g3d_stream_read_float_le(stream),
523 g3d_stream_read_float_le(stream),
524 g3d_stream_read_float_le(stream),
525 1.0);
526
527 /* usingEyeFilter: bool */
528 g3d_stream_read_int8(stream);
529
530 /* eyeFilterColor: color */
531 g3d_stream_skip(stream, 12);
532
533 /* eyeFilterAmount: float */
534 g3d_stream_read_float_le(stream);
535
536 /* lightColor: color */
537 g3d_stream_skip(stream, 12);
538
539 /* backgroundImageWidth: int */
540 bgw = g3d_stream_read_int32_le(stream);
541
542 /* backgroundImageHeight: int */
543 bgh = g3d_stream_read_int32_le(stream);
544
545 if(bgw * bgh) {
546
547 /* backgroundFilename */
548 memset(buffer, 0, 2048);
549 bufp = buffer;
550 while((*bufp = g3d_stream_read_int8(stream)) != '\0')
551 bufp ++;
552
553#if DEBUG > 0
554 g_debug("Q3O: scene: background image '%s' (%dx%d)",
555 buffer, bgw, bgh);
556#endif
557
558 /* backgroundImage: pixel[] */
559 g3d_stream_skip(stream, bgw * bgh * 3);
560 }
561
562 /* depthCuing: float */
563 g3d_stream_read_float_le(stream);
564
565 /* depthCueColor: color */
566 g3d_stream_skip(stream, 12);
567
568 /* gamma: float */
569 g3d_stream_read_float_le(stream);
570
571 return FALSE;
572}
573
574static gboolean q3o_read_eof(G3DStream *stream)
575{
576 gchar buffer[7];
577
578 if(g3d_stream_read(stream, buffer, 7) == 7) {
579 if(strncmp(buffer, "uick3Ds", 7) == 0) return TRUE;
580 g_warning("Q3O: did not get expected EOF marker");
581 } else {
582 g_warning("Q3O: premature end of file\n");
583 }
584 return FALSE;
585}
586