aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_flt/imp_flt_callbacks.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_flt/imp_flt_callbacks.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_flt/imp_flt_callbacks.c999
1 files changed, 999 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_flt/imp_flt_callbacks.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_flt/imp_flt_callbacks.c
new file mode 100644
index 0000000..44fd8f6
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_flt/imp_flt_callbacks.c
@@ -0,0 +1,999 @@
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 <string.h>
24#include <math.h>
25
26#include <g3d/stream.h>
27#include <g3d/material.h>
28#include <g3d/texture.h>
29#include <g3d/model.h>
30
31#include "imp_flt.h"
32#include "imp_flt_callbacks.h"
33
34/* header */
35gboolean flt_cb_0001(FltGlobalData *gd, FltLocalData *ld)
36{
37 gchar id[8];
38
39 g3d_stream_read(gd->stream, id, 8);
40 id[7] = '\0';
41 ld->nb -= 8;
42 gd->fversion = g3d_stream_read_int32_be(gd->stream);
43 ld->nb -= 4;
44
45 g_debug("FLT: header: '%s' revision %u", id, gd->fversion);
46
47 return TRUE;
48}
49
50/* group */
51gboolean flt_cb_0002(FltGlobalData *gd, FltLocalData *ld)
52{
53 G3DObject *object, *pobj;
54 gchar namebuf[8];
55
56 object = g_new0(G3DObject, 1);
57 pobj = (G3DObject *)g_queue_peek_head(gd->oqueue);
58 if(pobj != NULL)
59 pobj->objects = g_slist_append(pobj->objects, object);
60 else
61 gd->model->objects = g_slist_append(gd->model->objects, object);
62 ld->g3dobj = object;
63
64 /* group ID */
65 g3d_stream_read(gd->stream, namebuf, 8);
66 ld->nb -= 8;
67 namebuf[7] = '\0';
68 object->name = g_strdup_printf("group '%s'", namebuf);
69
70 return TRUE;
71}
72
73/* object */
74gboolean flt_cb_0004(FltGlobalData *gd, FltLocalData *ld)
75{
76 G3DObject *object, *pobj;
77 G3DMaterial *material;
78 gchar namebuf[8];
79
80 object = g_new0(G3DObject, 1);
81 pobj = (G3DObject *)g_queue_peek_head(gd->oqueue);
82 if(pobj != NULL)
83 pobj->objects = g_slist_append(pobj->objects, object);
84 else
85 gd->model->objects = g_slist_append(gd->model->objects, object);
86 ld->g3dobj = object;
87
88 material = g3d_material_new();
89 material->name = g_strdup("fallback material");
90 object->materials = g_slist_append(object->materials, material);
91
92 /* object ID */
93 g3d_stream_read(gd->stream, namebuf, 8);
94 ld->nb -= 8;
95 namebuf[7] = '\0';
96 object->name = g_strdup_printf("object '%s'", namebuf);
97
98 /* flags */
99 g3d_stream_read_int32_be(gd->stream);
100 ld->nb -= 4;
101
102 /* relative priority */
103 g3d_stream_read_int16_be(gd->stream);
104 ld->nb -= 2;
105
106 /* transparency */
107 g3d_stream_read_int16_be(gd->stream);
108 ld->nb -= 2;
109
110 /* special effect ID 1 */
111 g3d_stream_read_int16_be(gd->stream);
112 ld->nb -= 2;
113
114 /* special effect ID 2 */
115 g3d_stream_read_int16_be(gd->stream);
116 ld->nb -= 2;
117
118 /* significance */
119 g3d_stream_read_int16_be(gd->stream);
120 ld->nb -= 2;
121
122 /* reserved */
123 g3d_stream_read_int16_be(gd->stream);
124 ld->nb -= 2;
125
126 return TRUE;
127}
128
129/* face */
130gboolean flt_cb_0005(FltGlobalData *gd, FltLocalData *ld)
131{
132 G3DObject *object = ld->g3dobj;
133 G3DMaterial *material;
134 G3DFace *face;
135 gint16 index;
136 guint32 flags;
137 G3DFloat r, g, b;
138
139 g_return_val_if_fail(object != NULL, FALSE);
140
141 if(object->materials == NULL) {
142 material = g3d_material_new();
143 material->name = g_strdup("(default material)");
144 object->materials = g_slist_append(object->materials, material);
145 }
146
147 face = g_new0(G3DFace, 1);
148 face->material = g_slist_nth_data(object->materials, 0);
149 object->faces = g_slist_append(object->faces, face);
150 ld->level_object = face;
151
152 if(object->vertex_count == 0) {
153 if(gd->vertex_palette) {
154 /* copy vertex palette to object */
155 object->vertex_count = gd->vertex_palette->n_entries;
156 object->vertex_data = g_new0(G3DFloat, object->vertex_count * 3);
157 memcpy(object->vertex_data, gd->vertex_palette->vertex_data,
158 object->vertex_count * 3 * sizeof(G3DFloat));
159 }
160 }
161
162 /* id */
163 g3d_stream_skip(gd->stream, 8);
164 ld->nb -= 8;
165 /* IR color code */
166 g3d_stream_read_int32_be(gd->stream);
167 ld->nb -= 4;
168 /* relative priority */
169 g3d_stream_read_int16_be(gd->stream);
170 ld->nb -= 2;
171 /* draw type */
172 g3d_stream_read_int8(gd->stream);
173 ld->nb --;
174 /* texture white */
175 g3d_stream_read_int8(gd->stream);
176 ld->nb --;
177 /* color name index */
178 g3d_stream_read_int16_be(gd->stream);
179 ld->nb -= 2;
180 /* alternate color name index */
181 g3d_stream_read_int16_be(gd->stream);
182 ld->nb -= 2;
183 /* reserved */
184 g3d_stream_read_int8(gd->stream);
185 ld->nb --;
186 /* template (billboard) */
187 g3d_stream_read_int8(gd->stream);
188 ld->nb --;
189 /* detail texture pattern */
190 index = g3d_stream_read_int16_be(gd->stream);
191 ld->nb -= 2;
192 if(index != -1)
193 if(gd->texture_palette && (index < gd->texture_palette->size))
194 face->tex_image = gd->texture_palette->textures[index];
195 /* texture pattern */
196 index = g3d_stream_read_int16_be(gd->stream);
197 ld->nb -= 2;
198 if((face->tex_image == NULL) && (index != -1))
199 if(gd->texture_palette && (index < gd->texture_palette->size))
200 face->tex_image = gd->texture_palette->textures[index];
201
202 if(face->tex_image)
203 face->tex_image->tex_env = G3D_TEXENV_REPLACE;
204
205 /* material index */
206 index = g3d_stream_read_int16_be(gd->stream);
207 ld->nb -= 2;
208 if(index != -1) {
209 material = g_slist_nth_data(gd->model->materials, index);
210 if(material)
211 face->material = material;
212 }
213 /* surface material code */
214 g3d_stream_read_int16_be(gd->stream);
215 ld->nb -= 2;
216 /* feature ID */
217 g3d_stream_read_int16_be(gd->stream);
218 ld->nb -= 2;
219 /* IR material code */
220 g3d_stream_read_int32_be(gd->stream);
221 ld->nb -= 4;
222 /* transparency */
223 g3d_stream_read_int16_be(gd->stream);
224 ld->nb -= 2;
225 /* LOD generation control */
226 g3d_stream_read_int8(gd->stream);
227 ld->nb --;
228 /* line style index */
229 g3d_stream_read_int8(gd->stream);
230 ld->nb --;
231 /* flags */
232 flags = g3d_stream_read_int32_be(gd->stream);
233 ld->nb -= 4;
234 /* light mode */
235 g3d_stream_read_int8(gd->stream);
236 ld->nb --;
237 /* reserved */
238 g3d_stream_skip(gd->stream, 7);
239 ld->nb -= 7;
240 /* packed color, primary */
241 if((flags & (1 << 1)) /* no color */ ||
242 !(flags & (1 << 3))) /* packed color */
243 g3d_stream_read_int32_be(gd->stream);
244 else {
245 g3d_stream_read_int8(gd->stream); /* alpha, unused */
246 b = (G3DFloat)g3d_stream_read_int8(gd->stream) / 255.0;
247 g = (G3DFloat)g3d_stream_read_int8(gd->stream) / 255.0;
248 r = (G3DFloat)g3d_stream_read_int8(gd->stream) / 255.0;
249 material = g3d_material_new();
250 material->r = r;
251 material->g = g;
252 material->b = b;
253 material->a = 1.0;
254 face->material = material;
255 }
256 ld->nb -= 4;
257 /* packed color, alternate */
258 g3d_stream_read_int32_be(gd->stream);
259 ld->nb -= 4;
260 /* texture mapping index */
261 index = g3d_stream_read_int16_be(gd->stream);
262 ld->nb -= 2;
263
264 return TRUE;
265}
266
267/* push level */
268gboolean flt_cb_0010(FltGlobalData *gd, FltLocalData *ld)
269{
270 g_queue_push_head(gd->oqueue, ld->g3dobj);
271
272 gd->level ++;
273 return TRUE;
274}
275
276/* pop level */
277gboolean flt_cb_0011(FltGlobalData *gd, FltLocalData *ld)
278{
279 ld->g3dobj = g_queue_pop_head(gd->oqueue);
280 ld->level_object = NULL;
281
282 if(gd->level > 0)
283 gd->level --;
284 return TRUE;
285}
286
287/* color palette */
288gboolean flt_cb_0032(FltGlobalData *gd, FltLocalData *ld)
289{
290 G3DMaterial *material;
291 G3DObject *cobj;
292 gint32 i;
293
294 cobj = g_new0(G3DObject, 1);
295 cobj->name = g_strdup("color palette");
296 gd->model->objects = g_slist_append(gd->model->objects, cobj);
297
298 /* skip reserved bytes */
299 g3d_stream_skip(gd->stream, 128);
300 ld->nb -= 128;
301
302 /* get colors */
303 for(i = 0; i < 1024; i ++) {
304 material = g3d_material_new();
305 material->name = g_strdup_printf("color %d", i);
306 cobj->materials = g_slist_append(cobj->materials, material);
307
308 material->a = g3d_stream_read_int8(gd->stream) / 255.0;
309 material->b = g3d_stream_read_int8(gd->stream) / 255.0;
310 material->g = g3d_stream_read_int8(gd->stream) / 255.0;
311 material->r = g3d_stream_read_int8(gd->stream) / 255.0;
312 ld->nb -= 4;
313 }
314
315 return TRUE;
316}
317
318/* long ID */
319gboolean flt_cb_0033(FltGlobalData *gd, FltLocalData *ld)
320{
321 G3DObject *object = ld->g3dobj;
322
323 g_return_val_if_fail(object != NULL, FALSE);
324
325 g_free(object->name);
326 object->name = g_new0(gchar, ld->nb);
327 g3d_stream_read(gd->stream, object->name, ld->nb);
328 object->name[ld->nb - 1] = '\0';
329 ld->nb = 0;
330
331 return TRUE;
332}
333
334/* texture palette */
335gboolean flt_cb_0064(FltGlobalData *gd, FltLocalData *ld)
336{
337 gchar fname[201];
338 gint32 max, index, offx, offy;
339
340 g3d_stream_read(gd->stream, fname, 200);
341 ld->nb -= 200;
342
343 index = g3d_stream_read_int32_be(gd->stream);
344 offx = g3d_stream_read_int32_be(gd->stream);
345 offy = g3d_stream_read_int32_be(gd->stream);
346 ld->nb -= 12;
347
348 if(gd->texture_palette == NULL)
349 gd->texture_palette = g_new0(FltTexturePalette, 1);
350
351 max = MAX(index + 1, gd->texture_palette->size);
352 gd->texture_palette->size = max;
353 gd->texture_palette->offsets = g_realloc(gd->texture_palette->offsets,
354 max * 2 * sizeof(gint32));
355 gd->texture_palette->textures = g_realloc(gd->texture_palette->textures,
356 max * sizeof(G3DImage *));
357 gd->texture_palette->offsets[index * 2 + 0] = offx;
358 gd->texture_palette->offsets[index * 2 + 1] = offy;
359
360#if DEBUG > 2
361 g_debug("FLT: 0064: %s (index %d @ %d, %d)", fname, index, offx, offy);
362#endif
363
364 gd->texture_palette->textures[index] =
365 g3d_texture_load_cached(gd->context, gd->model, fname);
366
367 return TRUE;
368}
369
370static gboolean flt_inc_vertex_palette(FltGlobalData *gd)
371{
372 g_return_val_if_fail(gd->vertex_palette != NULL, FALSE);
373
374 gd->vertex_palette->n_entries ++;
375 gd->vertex_palette->offsets = g_realloc(
376 gd->vertex_palette->offsets,
377 gd->vertex_palette->n_entries * sizeof(goffset));
378 gd->vertex_palette->flags = g_realloc(
379 gd->vertex_palette->flags,
380 gd->vertex_palette->n_entries * sizeof(guint32));
381 gd->vertex_palette->vertex_data = g_realloc(
382 gd->vertex_palette->vertex_data,
383 gd->vertex_palette->n_entries * 3 * sizeof(G3DFloat));
384 gd->vertex_palette->normal_data = g_realloc(
385 gd->vertex_palette->normal_data,
386 gd->vertex_palette->n_entries * 3 * sizeof(G3DFloat));
387 gd->vertex_palette->tex_vertex_data = g_realloc(
388 gd->vertex_palette->tex_vertex_data,
389 gd->vertex_palette->n_entries * 2 * sizeof(G3DFloat));
390 gd->vertex_palette->vertex_materials = g_realloc(
391 gd->vertex_palette->vertex_materials,
392 gd->vertex_palette->n_entries * sizeof(G3DMaterial *));
393 return TRUE;
394}
395
396/* vertex palette */
397gboolean flt_cb_0067(FltGlobalData *gd, FltLocalData *ld)
398{
399 gd->vertex_palette = g_new0(FltVertexPalette, 1);
400 gd->vertex_palette->offset = 8;
401 return TRUE;
402}
403
404static G3DMaterial *flt_material_by_index(FltGlobalData *gd, guint32 i)
405{
406 G3DObject *colobj;
407
408 colobj = g3d_model_get_object_by_name(gd->model, "color palette");
409 if(colobj == NULL)
410 return NULL;
411
412 return g_slist_nth_data(colobj->materials, i);
413}
414
415#define FLOAT_EQUALS(a, b) (fabs((a) - (b)) < 0.001)
416
417static G3DMaterial *flt_find_color(G3DObject *pobj,
418 G3DFloat r, G3DFloat g, G3DFloat b, G3DFloat a)
419{
420 GSList *item;
421 G3DMaterial *material;
422
423 for(item = pobj->materials; item != NULL; item = item->next) {
424 material = item->data;
425 if(FLOAT_EQUALS(material->r, r) && FLOAT_EQUALS(material->g, g) &&
426 FLOAT_EQUALS(material->b, b) && FLOAT_EQUALS(material->a, a))
427 return material;
428 }
429 g_debug("did not find material");
430 return NULL;
431}
432
433static gboolean flt_handle_vertex_color(FltGlobalData *gd, FltLocalData *ld,
434 guint32 flags)
435{
436 G3DObject *vcolobj;
437 G3DMaterial *material;
438 G3DFloat r, g, b, a;
439
440 if(flags & FLT_FLAG_NO_COLOR)
441 return TRUE;
442
443 vcolobj = g3d_model_get_object_by_name(gd->model, "vertex colors");
444 if(vcolobj == NULL) {
445 vcolobj = g_new0(G3DObject, 1);
446 vcolobj->name = g_strdup("vertex colors");
447 gd->model->objects = g_slist_append(gd->model->objects, vcolobj);
448 }
449 a = (G3DFloat)g3d_stream_read_int8(gd->stream) / 255.0;
450 b = (G3DFloat)g3d_stream_read_int8(gd->stream) / 255.0;
451 g = (G3DFloat)g3d_stream_read_int8(gd->stream) / 255.0;
452 r = (G3DFloat)g3d_stream_read_int8(gd->stream) / 255.0;
453 ld->nb -= 4;
454
455 if(flags & FLT_FLAG_PACKED_COLOR) {
456 material = flt_find_color(vcolobj, r, g, b, a);
457 if(material == NULL) {
458 material = g3d_material_new();
459 material->r = r;
460 material->g = g;
461 material->b = b;
462 material->a = a;
463 material->name = g_strdup_printf(
464 "vertex material (%.2f, %.2f, %.2f, %.2f)", r, g, b, a);
465 vcolobj->materials = g_slist_prepend(vcolobj->materials, material);
466 }
467 } else {
468 /* color index */
469 material = flt_material_by_index(gd,
470 g3d_stream_read_int32_be(gd->stream));
471 ld->nb -= 4;
472 }
473 gd->vertex_palette->vertex_materials[gd->vertex_palette->n_entries - 1] =
474 material;
475 return TRUE;
476}
477
478/* vertex with color record */
479gboolean flt_cb_0068(FltGlobalData *gd, FltLocalData *ld)
480{
481 gint32 i, index;
482 guint32 flags;
483
484 if(!flt_inc_vertex_palette(gd))
485 return FALSE;
486
487 index = gd->vertex_palette->n_entries - 1;
488 gd->vertex_palette->offsets[index] = gd->vertex_palette->offset;
489 gd->vertex_palette->offset += ld->nb + 4;
490 gd->vertex_palette->flags[index] = 0;
491
492 /* color name index */
493 gd->vertex_palette->vertex_materials[index] =
494 flt_material_by_index(gd, g3d_stream_read_int16_be(gd->stream));
495 ld->nb -= 2;
496
497 /* flags */
498 flags = g3d_stream_read_int16_be(gd->stream);
499 ld->nb -= 2;
500
501 /* vertex coordinate */
502 for(i = 0; i < 3; i ++) {
503 gd->vertex_palette->vertex_data[index * 3 + i] =
504 g3d_stream_read_double_be(gd->stream);
505 ld->nb -= 8;
506 }
507
508 flt_handle_vertex_color(gd, ld, flags);
509
510 return TRUE;
511}
512
513/* vertex with color and normal record */
514gboolean flt_cb_0069(FltGlobalData *gd, FltLocalData *ld)
515{
516 gint32 i, index;
517 guint32 flags;
518
519 if(!flt_inc_vertex_palette(gd))
520 return FALSE;
521
522 index = gd->vertex_palette->n_entries - 1;
523 gd->vertex_palette->offsets[index] = gd->vertex_palette->offset;
524 gd->vertex_palette->offset += ld->nb + 4;
525 gd->vertex_palette->flags[index] = G3D_FLAG_FAC_NORMALS;
526
527 /* color name index */
528 gd->vertex_palette->vertex_materials[index] =
529 flt_material_by_index(gd, g3d_stream_read_int16_be(gd->stream));
530 ld->nb -= 2;
531
532 /* flags */
533 flags = g3d_stream_read_int16_be(gd->stream);
534 ld->nb -= 2;
535
536 /* vertex coordinate */
537 for(i = 0; i < 3; i ++) {
538 gd->vertex_palette->vertex_data[index * 3 + i] =
539 g3d_stream_read_double_be(gd->stream);
540 ld->nb -= 8;
541 }
542
543 /* vertex normal */
544 for(i = 0; i < 3; i ++) {
545 gd->vertex_palette->normal_data[index * 3 + i] =
546 g3d_stream_read_float_be(gd->stream);
547 ld->nb -= 4;
548 }
549
550 flt_handle_vertex_color(gd, ld, flags);
551
552 return TRUE;
553}
554
555/* vertex with color, normal and uv record */
556gboolean flt_cb_0070(FltGlobalData *gd, FltLocalData *ld)
557{
558 gint32 i, index;
559 guint32 flags;
560
561 if(!flt_inc_vertex_palette(gd))
562 return FALSE;
563
564 index = gd->vertex_palette->n_entries - 1;
565 gd->vertex_palette->offsets[index] = gd->vertex_palette->offset;
566 gd->vertex_palette->offset += ld->nb + 4;
567 gd->vertex_palette->flags[index] =
568 G3D_FLAG_FAC_NORMALS | G3D_FLAG_FAC_TEXMAP;
569
570 /* color name index */
571 gd->vertex_palette->vertex_materials[index] =
572 flt_material_by_index(gd, g3d_stream_read_int16_be(gd->stream));
573 ld->nb -= 2;
574
575 /* flags */
576 flags = g3d_stream_read_int16_be(gd->stream);
577 ld->nb -= 2;
578
579 /* vertex coordinate */
580 for(i = 0; i < 3; i ++) {
581 gd->vertex_palette->vertex_data[index * 3 + i] =
582 g3d_stream_read_double_be(gd->stream);
583 ld->nb -= 8;
584 }
585
586 /* vertex normal */
587 for(i = 0; i < 3; i ++) {
588 gd->vertex_palette->normal_data[index * 3 + i] =
589 g3d_stream_read_float_be(gd->stream);
590 ld->nb -= 4;
591 }
592
593 /* vertex texture coordinate */
594 for(i = 0; i < 2; i ++) {
595 gd->vertex_palette->tex_vertex_data[index * 2 + i] =
596 g3d_stream_read_float_be(gd->stream);
597 ld->nb -= 4;
598 }
599
600 flt_handle_vertex_color(gd, ld, flags);
601
602 return TRUE;
603}
604
605/* vertex with color and uv record */
606gboolean flt_cb_0071(FltGlobalData *gd, FltLocalData *ld)
607{
608 gint32 i, index;
609 guint32 flags;
610
611 if(!flt_inc_vertex_palette(gd))
612 return FALSE;
613
614 index = gd->vertex_palette->n_entries - 1;
615 gd->vertex_palette->offsets[index] = gd->vertex_palette->offset;
616 gd->vertex_palette->offset += ld->nb + 4;
617 gd->vertex_palette->flags[index] = G3D_FLAG_FAC_TEXMAP;
618
619 /* color name index */
620 gd->vertex_palette->vertex_materials[index] =
621 flt_material_by_index(gd, g3d_stream_read_int16_be(gd->stream));
622 ld->nb -= 2;
623
624 /* flags */
625 flags = g3d_stream_read_int16_be(gd->stream);
626 ld->nb -= 2;
627
628 /* vertex coordinate */
629 for(i = 0; i < 3; i ++) {
630 gd->vertex_palette->vertex_data[index * 3 + i] =
631 g3d_stream_read_double_be(gd->stream);
632 ld->nb -= 8;
633 }
634
635 /* vertex texture coordinate */
636 for(i = 0; i < 2; i ++) {
637 gd->vertex_palette->tex_vertex_data[index * 2 + i] =
638 g3d_stream_read_float_be(gd->stream);
639 ld->nb -= 4;
640 }
641
642 flt_handle_vertex_color(gd, ld, flags);
643
644 return TRUE;
645}
646
647static gint32 flt_vertex_palette_index_from_offset(FltGlobalData *gd,
648 goffset offset)
649{
650 FltVertexPalette *pal = gd->vertex_palette;
651 gint i;
652
653 g_return_val_if_fail(pal != NULL, -1);
654
655 for(i = 0; (i < pal->n_entries) && (pal->offsets[i] < offset); i ++);
656 if((i < pal->n_entries) && (pal->offsets[i] == offset))
657 return i;
658 g_warning("FLT: flt_vertex_palette_index_from_offset: "
659 "could not get index for offset %li (i=%d)", (long int)offset, i);
660 return -1;
661}
662
663/* vertex list */
664gboolean flt_cb_0072(FltGlobalData *gd, FltLocalData *ld)
665{
666 G3DFace *face = ld->level_object;
667 gint32 i, j, index;
668 guint32 n;
669
670 g_return_val_if_fail(face != NULL, FALSE);
671
672 n = ld->nb / 4;
673 face->vertex_count = n;
674 face->vertex_indices = g_new0(guint32, n);
675
676 for(i = 0; i < n; i ++) {
677 j = g3d_stream_read_int32_be(gd->stream);
678 ld->nb -= 4;
679
680#define FLT_SUPPORT_BROKEN_VERTEX_LIST 1
681#if FLT_SUPPORT_BROKEN_VERTEX_LIST
682 /* FIXME: there are some broken models which directly specify the
683 * index instead of a byte offset in the vertex palette */
684
685 if(gd->flags & FLT_FLAG_BROKEN_VERTEX_LIST)
686 index = j;
687 else
688 index = flt_vertex_palette_index_from_offset(gd, j);
689 if(index == -1) {
690 index = j;
691 gd->flags |= FLT_FLAG_BROKEN_VERTEX_LIST;
692 }
693#else
694 index = flt_vertex_palette_index_from_offset(gd, j);
695#endif
696 if(index == -1)
697 return FALSE;
698 face->vertex_indices[i] = index;
699 if(gd->vertex_palette->flags[index] & G3D_FLAG_FAC_NORMALS) {
700 /* copy normal data */
701 if(face->normals == NULL) {
702 face->normals = g_new0(G3DFloat, n * 3);
703 face->flags |= G3D_FLAG_FAC_NORMALS;
704 }
705 for(j = 0; j < 3; j ++)
706 face->normals[i * 3 + j] =
707 gd->vertex_palette->normal_data[index * 3 + j];
708 }
709 if(gd->vertex_palette->flags[index] & G3D_FLAG_FAC_TEXMAP) {
710 /* copy texture coordinate data */
711 if(face->tex_vertex_data == NULL) {
712 face->tex_vertex_data = g_new0(G3DFloat, n * 2);
713 face->tex_vertex_count = n;
714 if(face->tex_image)
715 face->flags |= G3D_FLAG_FAC_TEXMAP;
716 }
717 for(j = 0; j < 2; j ++)
718 face->tex_vertex_data[i * 2 + j] =
719 gd->vertex_palette->tex_vertex_data[index * 2 + j];
720 }
721 if(gd->vertex_palette->vertex_materials[index] != NULL)
722 face->material = gd->vertex_palette->vertex_materials[index];
723 }
724 return TRUE;
725}
726
727/* mesh */
728gboolean flt_cb_0084(FltGlobalData *gd, FltLocalData *ld)
729{
730 G3DObject *object;
731 gchar *namebuf[8];
732 gint32 index;
733
734 object = (G3DObject *)g_queue_peek_head(gd->oqueue);
735 g_return_val_if_fail(object != NULL, FALSE);
736
737 /* ASCII ID */
738 g3d_stream_read(gd->stream, namebuf, 8);
739 namebuf[7] = '\0';
740 ld->nb -= 8;
741
742 /* reserved */
743 g3d_stream_read_int32_be(gd->stream);
744 ld->nb -= 4;
745 /* IR color code */
746 g3d_stream_read_int32_be(gd->stream);
747 ld->nb -= 4;
748 /* priority */
749 g3d_stream_read_int16_be(gd->stream);
750 ld->nb -= 2;
751 /* draw type */
752 g3d_stream_read_int8(gd->stream);
753 ld->nb --;
754 /* texture white */
755 g3d_stream_read_int8(gd->stream);
756 ld->nb --;
757 /* color name index */
758 g3d_stream_read_int16_be(gd->stream);
759 ld->nb -= 2;
760 /* alternate color name index */
761 g3d_stream_read_int16_be(gd->stream);
762 ld->nb -= 2;
763 /* reserved */
764 g3d_stream_read_int8(gd->stream);
765 ld->nb --;
766 /* template (billboard) */
767 g3d_stream_read_int8(gd->stream);
768 ld->nb --;
769 /* detail texture pattern */
770 index = g3d_stream_read_int16_be(gd->stream);
771 ld->nb -= 2;
772 if(index > -1)
773 if(gd->texture_palette && (index < gd->texture_palette->size))
774 object->tex_image = gd->texture_palette->textures[index];
775 /* texture pattern */
776 index = g3d_stream_read_int16_be(gd->stream);
777 ld->nb -= 2;
778 if((index > -1) && (object->tex_image == NULL))
779 if(gd->texture_palette && (index < gd->texture_palette->size))
780 object->tex_image = gd->texture_palette->textures[index];
781
782 return TRUE;
783}
784
785/* local vertex pool */
786gboolean flt_cb_0085(FltGlobalData *gd, FltLocalData *ld)
787{
788 G3DObject *object;
789 guint32 nverts, attrmask;
790 gint32 i;
791
792 object = (G3DObject *)g_queue_peek_head(gd->oqueue);
793 g_return_val_if_fail(object != NULL, FALSE);
794
795 nverts = g3d_stream_read_int32_be(gd->stream);
796 attrmask = g3d_stream_read_int32_be(gd->stream);
797 ld->nb -= 8;
798
799 object->vertex_count = nverts;
800 object->vertex_data = g_new0(G3DFloat, nverts * 3);
801 object->tex_vertex_count = nverts;
802 object->tex_vertex_data = g_new0(G3DFloat, nverts * 2);
803
804 for(i = 0; i < nverts; i ++) {
805 if(attrmask & (1 << 31)) { /* has position */
806 object->vertex_data[i * 3 + 0] =
807 g3d_stream_read_double_be(gd->stream);
808 object->vertex_data[i * 3 + 1] =
809 g3d_stream_read_double_be(gd->stream);
810 object->vertex_data[i * 3 + 2] =
811 g3d_stream_read_double_be(gd->stream);
812 ld->nb -= 24;
813 }
814
815 if(attrmask & (1 << 30)) { /* has color index */
816 g3d_stream_read_int32_be(gd->stream);
817 ld->nb -= 4;
818 }
819
820 if(attrmask & (1 << 29)) { /* has RGBA color */
821 g3d_stream_read_int32_be(gd->stream);
822 ld->nb -= 4;
823 }
824
825 if(attrmask & (1 << 28)) { /* has normal */
826 g3d_stream_read_float_be(gd->stream);
827 g3d_stream_read_float_be(gd->stream);
828 g3d_stream_read_float_be(gd->stream);
829 ld->nb -= 12;
830 }
831
832 if(attrmask & (1 << 27)) { /* has base UV */
833 object->tex_vertex_data[i * 2 + 0] =
834 g3d_stream_read_float_be(gd->stream);
835 object->tex_vertex_data[i * 2 + 1] =
836 g3d_stream_read_float_be(gd->stream);
837 ld->nb -= 8;
838 }
839
840 if(attrmask & (1 << 26)) { /* has UV layer 1 */
841 g3d_stream_read_float_be(gd->stream);
842 g3d_stream_read_float_be(gd->stream);
843 ld->nb -= 8;
844 }
845
846 if(attrmask & (1 << 25)) { /* has UV layer 2 */
847 g3d_stream_read_float_be(gd->stream);
848 g3d_stream_read_float_be(gd->stream);
849 ld->nb -= 8;
850 }
851
852 if(attrmask & (1 << 24)) { /* has UV layer 3 */
853 g3d_stream_read_float_be(gd->stream);
854 g3d_stream_read_float_be(gd->stream);
855 ld->nb -= 8;
856 }
857
858 if(attrmask & (1 << 23)) { /* has UV layer 4 */
859 g3d_stream_read_float_be(gd->stream);
860 g3d_stream_read_float_be(gd->stream);
861 ld->nb -= 8;
862 }
863
864 if(attrmask & (1 << 22)) { /* has UV layer 5 */
865 g3d_stream_read_float_be(gd->stream);
866 g3d_stream_read_float_be(gd->stream);
867 ld->nb -= 8;
868 }
869
870 if(attrmask & (1 << 21)) { /* has UV layer 6 */
871 g3d_stream_read_float_be(gd->stream);
872 g3d_stream_read_float_be(gd->stream);
873 ld->nb -= 8;
874 }
875
876 if(attrmask & (1 << 20)) { /* has UV layer 7 */
877 g3d_stream_read_float_be(gd->stream);
878 g3d_stream_read_float_be(gd->stream);
879 ld->nb -= 8;
880 }
881 }
882
883 return TRUE;
884}
885
886/* mesh primitive */
887gboolean flt_cb_0086(FltGlobalData *gd, FltLocalData *ld)
888{
889 guint32 type, isize, nverts;
890 gint32 i;
891 G3DFace *face;
892 G3DObject *object;
893
894 object = (G3DObject *)g_queue_peek_head(gd->oqueue);
895 g_return_val_if_fail(object != NULL, FALSE);
896
897 type = g3d_stream_read_int16_be(gd->stream);
898 isize = g3d_stream_read_int16_be(gd->stream);
899 nverts = g3d_stream_read_int32_be(gd->stream);
900 ld->nb -= 8;
901
902 switch(type) {
903 case 1: /* triangle strip */
904 g_debug("0086: triangle strip");
905 break;
906
907 case 2: /* triangle fan */
908 g_debug("0086: triangle fan");
909 break;
910
911 case 3: /* quadriteral strip */
912 g_debug("0086: quadriteral strip");
913 break;
914
915 case 4: /* indexed polygon */
916 face = g_new0(G3DFace, 1);
917 face->material = (G3DMaterial *)g_slist_nth_data(object->materials,
918 0);
919 face->vertex_count = nverts;
920 face->vertex_indices = g_new0(guint32, nverts);
921 for(i = 0; i < nverts; i ++) {
922 face->vertex_indices[i] = flt_read_typed_index(
923 gd->stream, isize, &(ld->nb));
924 }
925 face->tex_image = object->tex_image;
926 if(face->tex_image != NULL) {
927 face->tex_vertex_count = nverts;
928 face->tex_vertex_data = g_new0(G3DFloat, nverts * 2);
929 for(i = 0; i < nverts; i ++) {
930 face->tex_vertex_data[i * 2 + 0] =
931 object->tex_vertex_data[
932 face->vertex_indices[i] * 2 + 0];
933 face->tex_vertex_data[i * 2 + 1] =
934 object->tex_vertex_data[
935 face->vertex_indices[i] * 2 + 1];
936 }
937 face->flags |= G3D_FLAG_FAC_TEXMAP;
938 }
939 object->faces = g_slist_append(object->faces, face);
940 break;
941
942 default:
943 g_warning("FLT: mesh primitive: unknown type %d\n", type);
944 }
945
946 return TRUE;
947}
948
949/* material palette */
950gboolean flt_cb_0113(FltGlobalData *gd, FltLocalData *ld)
951{
952 G3DMaterial *material;
953 gchar name[13];
954
955 material = g3d_material_new();
956
957 /* material index */
958 g3d_stream_read_int32_be(gd->stream);
959 ld->nb -= 4;
960 /* material name */
961 g3d_stream_read(gd->stream, name, 12);
962 ld->nb -= 12;
963 name[12] = '\0';
964 material->name = g_strdup(name);
965 /* flags */
966 g3d_stream_read_int32_be(gd->stream);
967 ld->nb -= 4;
968 /* ambient */
969 g3d_stream_read_float_be(gd->stream);
970 g3d_stream_read_float_be(gd->stream);
971 g3d_stream_read_float_be(gd->stream);
972 ld->nb -= 12;
973 /* diffuse */
974 material->r = g3d_stream_read_float_be(gd->stream);
975 material->g = g3d_stream_read_float_be(gd->stream);
976 material->b = g3d_stream_read_float_be(gd->stream);
977 ld->nb -= 12;
978 /* specular */
979 material->specular[0] = g3d_stream_read_float_be(gd->stream);
980 material->specular[1] = g3d_stream_read_float_be(gd->stream);
981 material->specular[2] = g3d_stream_read_float_be(gd->stream);
982 ld->nb -= 12;
983 /* emissive */
984 g3d_stream_read_float_be(gd->stream);
985 g3d_stream_read_float_be(gd->stream);
986 g3d_stream_read_float_be(gd->stream);
987 ld->nb -= 12;
988 /* shininess */
989 material->shininess = g3d_stream_read_float_be(gd->stream);
990 ld->nb -= 4;
991 /* alpha */
992 material->a = g3d_stream_read_float_be(gd->stream);
993 ld->nb -= 4;
994
995 gd->model->materials = g_slist_append(gd->model->materials, material);
996
997 return TRUE;
998}
999