aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_3ds/imp_3ds_callbacks.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_3ds/imp_3ds_callbacks.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_3ds/imp_3ds_callbacks.c992
1 files changed, 992 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_3ds/imp_3ds_callbacks.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_3ds/imp_3ds_callbacks.c
new file mode 100644
index 0000000..fdd9823
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_3ds/imp_3ds_callbacks.c
@@ -0,0 +1,992 @@
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#include <string.h>
23#include <math.h>
24
25#include <g3d/stream.h>
26#include <g3d/texture.h>
27#include <g3d/vector.h>
28#include <g3d/matrix.h>
29
30#include "imp_3ds_callbacks.h"
31
32#define X3DS_FLAG_TENSION 0x01
33#define X3DS_FLAG_CONTINUITY 0x02
34#define X3DS_FLAG_BIAS 0x04
35#define X3DS_FLAG_EASE_TO 0x08
36#define X3DS_FLAG_EASE_FROM 0x10
37
38gboolean x3ds_cb_0x0002(x3ds_global_data *global, x3ds_parent_data *parent)
39{
40 gint32 version;
41
42 version = g3d_stream_read_int32_le(global->stream);
43 parent->nb -= 4;
44#if DEBUG > 0
45 g_debug("[3DS] M3D version %d", version);
46#endif
47 return TRUE;
48}
49
50/* color float */
51gboolean x3ds_cb_0x0010(x3ds_global_data *global, x3ds_parent_data *parent)
52{
53 G3DMaterial *material;
54 G3DFloat r, g, b;
55
56 r = g3d_stream_read_float_le(global->stream);
57 g = g3d_stream_read_float_le(global->stream);
58 b = g3d_stream_read_float_le(global->stream);
59 parent->nb -= 12;
60
61 switch(parent->id)
62 {
63 case 0x1200: /* SOLID_BGND */
64 g3d_context_set_bgcolor(global->context, r, g, b, 1.0);
65 break;
66
67 case 0xA010: /* ambient color */
68 break;
69
70 case 0xA020: /* diffuse color */
71 material = (G3DMaterial *)parent->object;
72 g_return_val_if_fail(material, FALSE);
73
74 material->r = r;
75 material->g = g;
76 material->b = b;
77 break;
78
79 case 0xA030: /* specular color */
80 material = (G3DMaterial *)parent->object;
81 g_return_val_if_fail(material, FALSE);
82
83 material->specular[0] = r;
84 material->specular[1] = g;
85 material->specular[2] = b;
86 material->specular[3] = 0.25;
87 break;
88
89 default:
90#if DEBUG > 0
91 g_warning("[3DS] unhandled COLOR_F in 0x%04X", parent->id);
92#endif
93 break;
94 }
95
96 return TRUE;
97}
98
99/* color 24 */
100gboolean x3ds_cb_0x0011(x3ds_global_data *global, x3ds_parent_data *parent)
101{
102 G3DMaterial *material;
103 gint32 r, g, b;
104
105 material = (G3DMaterial *)parent->object;
106 g_return_val_if_fail(material, FALSE);
107
108 r = g3d_stream_read_int8(global->stream);
109 g = g3d_stream_read_int8(global->stream);
110 b = g3d_stream_read_int8(global->stream);
111 parent->nb -= 3;
112
113 switch(parent->id)
114 {
115
116 case 0xA010: /* ambient color */
117 break;
118
119 case 0xA020: /* diffuse color */
120 material->r = (G3DFloat)r / 255.0;
121 material->g = (G3DFloat)g / 255.0;
122 material->b = (G3DFloat)b / 255.0;
123 break;
124
125 case 0xA030: /* specular color */
126 material->specular[0] = (GLfloat)r / 255.0;
127 material->specular[1] = (GLfloat)g / 255.0;
128 material->specular[2] = (GLfloat)b / 255.0;
129 material->specular[3] = 0.25;
130 break;
131
132 default:
133#if DEBUG > 0
134 g_warning("[3DS] unhandled COLOR_24 in 0x%04X", parent->id);
135#endif
136 break;
137 }
138
139 return TRUE;
140}
141
142/* short percentage */
143gboolean x3ds_cb_0x0030(x3ds_global_data *global, x3ds_parent_data *parent)
144{
145 G3DMaterial *material;
146 gint32 percent;
147
148 material = (G3DMaterial *)parent->object;
149 g_return_val_if_fail(material, FALSE);
150
151 percent = g3d_stream_read_int16_le(global->stream);
152 parent->nb -= 2;
153
154 switch(parent->id)
155 {
156 case 0xA040: /* shininess */
157 material->shininess = (G3DFloat)percent / 100.0;
158 break;
159
160 case 0xA041: /* shininess (2) */
161 /* TODO: do something here? */
162 break;
163
164 case 0xA050: /* transparency */
165 material->a = 1.0 - ((G3DFloat)percent / 100.0);
166 break;
167
168 case 0xA052: /* fallthrough */
169 /* TODO: do something here? */
170 break;
171
172 case 0xA053: /* blur */
173 /* TODO: do something here? */
174 break;
175
176 case 0xA084: /* self illumination */
177 /* TODO: do something here? */
178 break;
179
180 case 0xA200: /* texture map */
181 /* TODO: do something here? */
182 break;
183
184 case 0xA210: /* opacity map */
185 /* TODO: do something here? */
186 g_debug("[3DS] opacity percentage: %d%%\n", percent);
187 break;
188
189 case 0xA220: /* reflection map */
190 /* TODO: do something here? */
191 break;
192
193 case 0xA230: /* bump map */
194 /* TODO: do something here? */
195 break;
196
197 default:
198#if DEBUG > 0
199 g_warning("[3DS] unhandled INT_PERCENTAGE in 0x%04X",
200 parent->id);
201#endif
202 break;
203 }
204
205 return TRUE;
206}
207
208/* float percentage */
209gboolean x3ds_cb_0x0031(x3ds_global_data *global, x3ds_parent_data *parent)
210{
211 G3DMaterial *material;
212 G3DFloat percent;
213
214 material = (G3DMaterial *)parent->object;
215 g_return_val_if_fail(material, FALSE);
216
217 percent = g3d_stream_read_float_le(global->stream);
218 parent->nb -= 4;
219
220 switch(parent->id)
221 {
222 case 0xA040: /* shininess */
223 material->shininess = percent;
224 break;
225
226 case 0xA050: /* transparency */
227 material->a = 1.0 - percent;
228 break;
229
230 default:
231#if DEBUG > 0
232 g_warning("[3DS] unhandled FLOAT_PERCENTAGE in 0x%04X",
233 parent->id);
234#endif
235 break;
236 }
237
238 return TRUE;
239}
240
241/* master scale */
242gboolean x3ds_cb_0x0100(x3ds_global_data *global, x3ds_parent_data *parent)
243{
244 global->scale = g3d_stream_read_float_le(global->stream);
245 parent->nb -= 4;
246
247 return TRUE;
248}
249
250/* named object */
251gboolean x3ds_cb_0x4000(x3ds_global_data *global, x3ds_parent_data *parent)
252{
253 gchar buffer[1024];
254
255 parent->nb -= x3ds_read_cstr(global->stream, buffer);
256 parent->object = x3ds_newobject(global->model, buffer);
257
258 return TRUE;
259}
260
261/* point array */
262gboolean x3ds_cb_0x4110(x3ds_global_data *global, x3ds_parent_data *parent)
263{
264 G3DObject *object;
265 gint32 i;
266
267 object = (G3DObject *)parent->object;
268 g_return_val_if_fail(object, FALSE);
269
270 object->vertex_count = g3d_stream_read_int16_le(global->stream);
271 parent->nb -= 2;
272
273 object->vertex_data = g_new0(G3DFloat, object->vertex_count * 3);
274 for(i = 0; i < object->vertex_count; i ++)
275 {
276 object->vertex_data[i * 3 + 0] = g3d_stream_read_float_le(global->stream);
277 object->vertex_data[i * 3 + 1] = g3d_stream_read_float_le(global->stream);
278 object->vertex_data[i * 3 + 2] = g3d_stream_read_float_le(global->stream);
279
280 parent->nb -= 12;
281
282 if((i % 1000) == 0) x3ds_update_progress(global, parent->level);
283 }
284 return TRUE;
285}
286
287/* face array */
288gboolean x3ds_cb_0x4120(x3ds_global_data *global, x3ds_parent_data *parent)
289{
290 gint32 i, flags, nfaces;
291#define X3DS_REORDER_FACES
292#ifdef X3DS_REORDER_FACES
293 gint32 p1 = -1, p2 = -1, bottle;
294#endif
295 G3DFace *face;
296 G3DObject *object;
297
298 object = (G3DObject *)parent->object;
299 g_return_val_if_fail(object, FALSE);
300
301 nfaces = g3d_stream_read_int16_le(global->stream);
302 parent->nb -= 2;
303
304 for(i = 0; i < nfaces; i ++)
305 {
306 face = g_new0(G3DFace, 1);
307
308 face->vertex_count = 3;
309 face->vertex_indices = g_malloc(3 * sizeof(guint32));
310
311 face->vertex_indices[0] = g3d_stream_read_int16_le(global->stream);
312 face->vertex_indices[1] = g3d_stream_read_int16_le(global->stream);
313 face->vertex_indices[2] = g3d_stream_read_int16_le(global->stream);
314 flags = g3d_stream_read_int16_le(global->stream);
315 parent->nb -= 8;
316
317#ifdef X3DS_REORDER_FACES
318 /* try to put all faces in the same direction */
319 if((p1 == face->vertex_indices[0]) && (p2 == face->vertex_indices[1]))
320 {
321 bottle = face->vertex_indices[0];
322 face->vertex_indices[0] = face->vertex_indices[2];
323 face->vertex_indices[2] = bottle;
324 }
325
326 p1 = face->vertex_indices[0];
327 p2 = face->vertex_indices[1];
328#endif
329
330 face->material = g_slist_nth_data(object->materials, 0);
331
332 object->faces = g_slist_append(object->faces, face);
333
334 if((i % 1000) == 0) x3ds_update_progress(global, parent->level);
335 }
336
337 return TRUE;
338}
339
340/* mesh mat group */
341gboolean x3ds_cb_0x4130(x3ds_global_data *global, x3ds_parent_data *parent)
342{
343 G3DObject *object;
344 gint32 i, j, facenum, nfaces;
345 gchar buffer[512];
346 G3DMaterial *material = NULL, *mat;
347 G3DFace *face;
348 GSList *mlist;
349
350 object = (G3DObject *)parent->object;
351 g_return_val_if_fail(object, FALSE);
352
353 /* name of material */
354 parent->nb -= x3ds_read_cstr(global->stream, buffer);
355
356 /* find material in list */
357 mlist = global->model->materials;
358 while(mlist != NULL)
359 {
360 mat = (G3DMaterial*)mlist->data;
361 if(strcmp(mat->name, buffer) == 0)
362 {
363 material = mat;
364 break;
365 }
366 mlist = mlist->next;
367 }
368
369 nfaces = g3d_stream_read_int16_le(global->stream);
370 parent->nb -= 2;
371
372 for(i = 0; i < nfaces; i ++)
373 {
374 facenum = g3d_stream_read_int16_le(global->stream);
375 parent->nb -= 2;
376
377 if(material != NULL)
378 {
379 face = (G3DFace*)g_slist_nth_data(object->faces, facenum);
380 if(face == NULL) continue;
381
382 face->material = material;
383
384 if(face->material->tex_image && object->tex_vertex_data)
385 {
386 face->flags |= G3D_FLAG_FAC_TEXMAP;
387 face->tex_image = face->material->tex_image;
388 face->tex_vertex_count = 3;
389 face->tex_vertex_data = g_new0(G3DFloat, 6);
390 for(j = 0; j < 3; j ++)
391 {
392 face->tex_vertex_data[j * 2 + 0] = object->tex_vertex_data[
393 face->vertex_indices[j] * 2 + 0];
394 face->tex_vertex_data[j * 2 + 1] = object->tex_vertex_data[
395 face->vertex_indices[j] * 2 + 1];
396 }
397 } /* textured face */
398 } /* material != NULL */
399
400 if((i % 1000) == 0) x3ds_update_progress(global, parent->level);
401 } /* 0..nfaces */
402
403 return TRUE;
404}
405
406/* texture vertices */
407gboolean x3ds_cb_0x4140(x3ds_global_data *global, x3ds_parent_data *parent)
408{
409 G3DObject *object;
410 gint32 i;
411
412 object = (G3DObject *)parent->object;
413 g_return_val_if_fail(object, FALSE);
414
415 object->tex_vertex_count = g3d_stream_read_int16_le(global->stream);
416 parent->nb -= 2;
417
418 object->tex_vertex_data = g_new0(G3DFloat, object->tex_vertex_count * 2);
419
420 for(i = 0; i < object->tex_vertex_count; i ++)
421 {
422 object->tex_vertex_data[i * 2 + 0] = g3d_stream_read_float_le(global->stream);
423 object->tex_vertex_data[i * 2 + 1] = g3d_stream_read_float_le(global->stream);
424 parent->nb -= 8;
425
426 if((i % 1000) == 0) x3ds_update_progress(global, parent->level);
427 }
428
429 return TRUE;
430}
431
432/* smoothing groups */
433gboolean x3ds_cb_0x4150(x3ds_global_data *global, x3ds_parent_data *parent)
434{
435 G3DObject *object;
436 G3DFace *face;
437 GSList *oface;
438 gint32 i, j, k, n=0, polynum, group;
439 guint32 *smooth_list;
440 G3DFloat *pnormal_list, *vertex_normal_buf;
441 G3DFloat a[3],b[3], *p0,*p1,*p2,*r;
442
443 /* read data */
444 object = (G3DObject *)parent->object;
445 g_return_val_if_fail(object, FALSE);
446
447 oface=object->faces;
448 polynum=0;
449 for(oface = object->faces; oface != NULL ; oface = oface->next)
450 polynum++; /* count polygons */
451
452 /* polygon normal list */
453 pnormal_list = g_new(float, 3 * polynum);
454 /* normals per vertice */
455 vertex_normal_buf = g_new0(float, 3 * object->vertex_count);
456
457 smooth_list = g_new(guint32, polynum);
458
459 for(i = 0 ; i < polynum ; i ++)
460 smooth_list[i] = g3d_stream_read_int32_le(global->stream);
461
462 parent->nb -= polynum * 4;
463 /* first, we calculate the normal by the polygon vertices (just vector
464 * product) */
465 i = 0;
466 for(oface = object->faces; oface != NULL ; oface=oface->next)
467 {
468 face = (G3DFace *)oface->data;
469 r = &(pnormal_list[i*3]);
470 p0 = &(object->vertex_data[3 * face->vertex_indices[0]]);
471 p1 = &(object->vertex_data[3 * face->vertex_indices[1]]);
472 p2 = &(object->vertex_data[3 * face->vertex_indices[2]]);
473
474 a[0]=p1[0] - p0[0];
475 a[1]=p1[1] - p0[1];
476 a[2]=p1[2] - p0[2];
477 b[0]=p2[0] - p0[0];
478 b[1]=p2[1] - p0[1];
479 b[2]=p2[2] - p0[2];
480
481 g3d_vector_normal(a[0], a[1], a[2], b[0], b[1], b[2],
482 &r[0], &r[1], &r[2]);
483
484 g3d_vector_unify(&r[0], &r[1], &r[2]);
485
486 face->flags |= G3D_FLAG_FAC_NORMALS;
487 i ++;
488 }
489
490 do {
491 /* find a suitable group. -1 means we've already taken care */
492 group = -1;
493 for(i = 0; i < polynum; i ++)
494 if((group = smooth_list[i]) != -1) /* found a group */
495 break;
496 /* handle this group */
497 if(group != -1)
498 {
499 /* SMOOTH
500 * we add normals of the polygons's vertices so each vertex will
501 * finally have
502 * the sum of the polygons normals where the vertex is part of.
503 *
504 * run0: clear the vertex_normal_buf for this group */
505 for(i = 0; i < object->vertex_count * 3; i ++)
506 vertex_normal_buf[i] = 0.0;
507 /* run1: add normals on themselves into the vertex_normal_buf */
508 i = 0;
509 for(oface = object->faces; oface != NULL ; oface = oface->next)
510 {
511 face = (G3DFace *) oface->data;
512 if(smooth_list[i] == group)
513 {
514 /* for all 3 vertices of the polygon */
515 for(j = 0; j < 3; j ++)
516 {
517 k = face->vertex_indices[j];
518 for(n = 0; n < 3; n ++)
519 vertex_normal_buf[k * 3 + n] +=
520 pnormal_list[i * 3 + n];
521 }
522 }
523 i ++;
524 }
525 i = 0;
526 /* run2: apply to the final vertex buffer */
527 for(oface = object->faces; oface != NULL ; oface = oface->next)
528 {
529 face = (G3DFace *)oface->data;
530 if(smooth_list[i] == group)
531 {
532 face->normals = g_new(G3DFloat, 9);
533 for(j = 0; j < 3; j ++)
534 {
535 k = face->vertex_indices[j];
536
537 g3d_vector_unify(
538 &(vertex_normal_buf[k * 3 + 0]),
539 &(vertex_normal_buf[k * 3 + 1]),
540 &(vertex_normal_buf[k * 3 + 2]));
541
542 if(vertex_normal_buf[k * 3 + 0] != 0.0F)
543 /* finally, we save the normal in our normal
544 * buffer */
545 memcpy(face->normals + j * 3,
546 vertex_normal_buf + k * 3,
547 sizeof(G3DFloat) * 3);
548 else
549 /* use the pbuf normal */
550 memcpy(face->normals + j * 3,
551 pnormal_list + i * 3,
552 sizeof(G3DFloat) * 3);
553
554 }
555 smooth_list[i] = -1; /* finished this polygon */
556 }
557 i++;
558 }
559 /* SMOOTH END */
560 }
561 } while (group != -1);
562
563 g_free(pnormal_list);
564 g_free(vertex_normal_buf);
565 g_free(smooth_list);
566 return TRUE;
567}
568
569/* mesh matrix */
570gboolean x3ds_cb_0x4160(x3ds_global_data *global, x3ds_parent_data *parent)
571{
572 G3DFloat matrix[16];
573 gint32 i;
574 G3DFloat det;
575
576 g3d_matrix_identity(matrix);
577 for(i = 0; i < 12; i ++)
578 matrix[(i / 3) * 4 + (i % 3)] = g3d_stream_read_float_le(global->stream);
579 parent->nb -= 48;
580
581 det = g3d_matrix_determinant(matrix);
582
583 g3d_matrix_dump(matrix);
584 g_debug("det: %f", det);
585
586
587 if(det < 0.0) {
588#if 0
589 G3DFloat scale[16];
590 g3d_matrix_identity(scale);
591 g3d_matrix_scale(-1.0, 1.0, 1.0, scale);
592 g3d_matrix_multiply(scale, matrix, matrix);
593 g3d_matrix_dump(matrix);
594#endif
595#define X3DS_MESH_TRANSFORM 0
596#if X3DS_MESH_TRANSFORM
597 object = parent->object;
598 if(object) {
599 object->transformation = g_new0(G3DTransformation, 1);
600 memcpy(object->transformation->matrix, matrix, 16 * sizeof(G3DFloat));
601 }
602
603#if 0
604 if(parent->object) {
605 g3d_object_transform(parent->object, matrix);
606 }
607#endif
608#endif
609 }
610 return TRUE;
611}
612
613/* material name */
614gboolean x3ds_cb_0xA000(x3ds_global_data *global, x3ds_parent_data *parent)
615{
616 G3DMaterial *material;
617 gchar buffer[1024];
618
619 g_return_val_if_fail(parent->object, FALSE);
620
621 parent->nb -= x3ds_read_cstr(global->stream, buffer);
622 material = (G3DMaterial *)(parent->object);
623
624 material->name = g_strdup(buffer);
625
626 return TRUE;
627}
628
629/* two sided material */
630gboolean x3ds_cb_0xA081(x3ds_global_data *global, x3ds_parent_data *parent)
631{
632 G3DMaterial *material;
633
634 material = (G3DMaterial *)parent->object;
635 g_return_val_if_fail(material, FALSE);
636
637 material->flags |= G3D_FLAG_MAT_TWOSIDE;
638
639 return TRUE;
640}
641
642/* texture map name */
643gboolean x3ds_cb_0xA300(x3ds_global_data *global, x3ds_parent_data *parent)
644{
645 G3DMaterial *material;
646 G3DImage *image;
647 gchar buffer[512];
648
649 material = (G3DMaterial *)parent->object;
650 g_return_val_if_fail(material, FALSE);
651
652 parent->nb -= x3ds_read_cstr(global->stream, buffer);
653
654 switch(parent->id)
655 {
656 case 0xA200: /* texture map */
657 material->tex_image = g3d_texture_load_cached(global->context,
658 global->model, buffer);
659 if(material->tex_image)
660 {
661 g3d_texture_flip_y(material->tex_image);
662 material->tex_image->tex_id = ++ global->max_tex_id;
663 }
664 break;
665
666 case 0xA210: /* opacity map */
667 image = g3d_texture_load(global->context, buffer);
668 if(image != NULL)
669 {
670 g3d_texture_flip_y(image);
671 material->tex_image = g3d_texture_merge_alpha(
672 material->tex_image, image);
673 g3d_texture_free(image);
674 }
675 break;
676
677 case 0xA220: /* reflection map */
678 /* TODO: implement */
679 break;
680
681 case 0xA230: /* bump map */
682 /* TODO: implement */
683 break;
684
685 default:
686#if DEBUG > 0
687 g_warning("[3DS] unhandled texture name in 0x%04X", parent->id);
688#endif
689
690 break;
691 }
692
693 return TRUE;
694}
695
696/* texture map scale u */
697gboolean x3ds_cb_0xA354(x3ds_global_data *global, x3ds_parent_data *parent)
698{
699 G3DMaterial *material;
700 G3DImage *image;
701 G3DFloat scale;
702
703 material = (G3DMaterial *)parent->object;
704 g_return_val_if_fail(material, FALSE);
705
706 image = material->tex_image;
707 g_return_val_if_fail(image, FALSE);
708
709 scale = g3d_stream_read_float_le(global->stream);
710 parent->nb -= 4;
711
712 image->tex_scale_u = scale;
713#if DEBUG > 3
714 g_debug("[3DS] scale_u: %f", image->tex_scale_u);
715#endif
716
717 return TRUE;
718}
719
720/* texture map scale v */
721gboolean x3ds_cb_0xA356(x3ds_global_data *global, x3ds_parent_data *parent)
722{
723 G3DMaterial *material;
724 G3DImage *image;
725 G3DFloat scale;
726
727 material = (G3DMaterial *)parent->object;
728 g_return_val_if_fail(material, FALSE);
729
730 image = material->tex_image;
731 g_return_val_if_fail(image, FALSE);
732
733 scale = g3d_stream_read_float_le(global->stream);
734 parent->nb -= 4;
735
736 image->tex_scale_v = scale;
737#if DEBUG > 3
738 g_debug("[3DS] scale_v: %f", image->tex_scale_v);
739#endif
740
741 return TRUE;
742}
743
744/* material */
745gboolean x3ds_cb_0xAFFF(x3ds_global_data *global, x3ds_parent_data *parent)
746{
747 G3DMaterial *material;
748 G3DObject *object;
749
750 material = g3d_material_new();
751
752 if(parent->object)
753 {
754 object = (G3DObject *)parent->object;
755 object->materials = g_slist_append(object->materials, material);
756 }
757 else
758 {
759 global->model->materials = g_slist_append(global->model->materials,
760 material);
761 }
762
763 parent->object = material;
764
765 return TRUE;
766}
767
768/* keyframe data header */
769gboolean x3ds_cb_0xB00A(x3ds_global_data *global, x3ds_parent_data *parent)
770{
771 gint32 rev, len;
772 gchar buffer[512];
773
774 rev = g3d_stream_read_int16_le(global->stream);
775 parent->nb -= 2;
776 parent->nb -= x3ds_read_cstr(global->stream, buffer);
777 len = g3d_stream_read_int16_le(global->stream);
778 parent->nb -= 2;
779
780#if DEBUG > 0
781 g_debug("[3DS] keyframe data: r%d, %d frames, \"%s\"",
782 rev, len, buffer);
783#endif
784 return TRUE;
785}
786
787/* node header */
788gboolean x3ds_cb_0xB010(x3ds_global_data *global, x3ds_parent_data *parent)
789{
790 GSList *olist;
791 G3DObject *object;
792 gchar buffer[512];
793
794 parent->nb -= x3ds_read_cstr(global->stream, buffer);
795#if DEBUG > 3
796 g_debug("[3DS] NODE_HDR: %s", buffer);
797#endif
798
799 /* find object by name */
800 olist = global->model->objects;
801 while(olist)
802 {
803 object = (G3DObject *)olist->data;
804 if(strcmp(object->name, buffer) == 0)
805 {
806 parent->level_object = object;
807 break;
808 }
809 olist = olist->next;
810 }
811
812 g3d_stream_read_int16_le(global->stream); /* flags 1 */
813 g3d_stream_read_int16_le(global->stream); /* flags 2 */
814 g3d_stream_read_int16_le(global->stream); /* ? */
815 parent->nb -= 6;
816
817 return TRUE;
818}
819
820/* pivot */
821gboolean x3ds_cb_0xB013(x3ds_global_data *global, x3ds_parent_data *parent)
822{
823 G3DObject *object;
824#if 0
825 gint32 i;
826#endif
827 G3DFloat x, y, z;
828
829 object = parent->level_object;
830 if(object == NULL) return FALSE;
831
832 x = g3d_stream_read_float_le(global->stream);
833 y = g3d_stream_read_float_le(global->stream);
834 z = g3d_stream_read_float_le(global->stream);
835 parent->nb -= 12;
836
837#if DEBUG > 3
838 g_debug("[3DS]: PIVOT: (%.2f,%.2f,%.2f)", x, y, z);
839#endif
840
841 return TRUE;
842}
843
844#define X3DS_ENABLE_POS_TRACK_TAG 0
845
846/* position tracking tag */
847gboolean x3ds_cb_0xB020(x3ds_global_data *global, x3ds_parent_data *parent)
848{
849 G3DObject *object;
850 gint32 i, flags, fflags, nkeys, fnum;
851#if X3DS_ENABLE_POS_TRACK_TAG
852 gint32 j;
853#endif
854 G3DFloat x, y, z;
855
856 object = parent->level_object;
857 if(object == NULL) return FALSE;
858
859 flags = g3d_stream_read_int16_le(global->stream);
860 g3d_stream_skip(global->stream, 8);
861 nkeys = g3d_stream_read_int32_le(global->stream);
862
863 parent->nb -= 14;
864
865 for(i = 0; i < nkeys; i ++)
866 {
867 fnum = g3d_stream_read_int32_le(global->stream);
868 fflags = g3d_stream_read_int16_le(global->stream);
869 parent->nb -= 6;
870
871 if(fflags & X3DS_FLAG_TENSION)
872 {
873 g3d_stream_read_float_le(global->stream);
874 parent->nb -= 4;
875 }
876 if(fflags & X3DS_FLAG_CONTINUITY)
877 {
878 g3d_stream_read_float_le(global->stream);
879 parent->nb -= 4;
880 }
881 if(fflags & X3DS_FLAG_BIAS)
882 {
883 g3d_stream_read_float_le(global->stream);
884 parent->nb -= 4;
885 }
886 if(fflags & X3DS_FLAG_EASE_TO)
887 {
888 g3d_stream_read_float_le(global->stream);
889 parent->nb -= 4;
890 }
891 if(fflags & X3DS_FLAG_EASE_FROM)
892 {
893 g3d_stream_read_float_le(global->stream);
894 parent->nb -= 4;
895 }
896
897 x = g3d_stream_read_float_le(global->stream);
898 y = g3d_stream_read_float_le(global->stream);
899 z = g3d_stream_read_float_le(global->stream);
900 parent->nb -= 12;
901#if DEBUG > 3
902 g_debug("[3DS]: POS_TRACK_TAG: frame %d: (%.2f,%.2f,%.2f) (0x%X) "
903 "object: %s",
904 fnum, x, y, z, fflags, object->name);
905#endif
906
907#if X3DS_ENABLE_POS_TRACK_TAG
908 if(fnum == 0)
909 {
910#if 1
911 for(j = 0; j < object->vertex_count; j ++)
912 {
913 object->vertex_data[j * 3 + 0] -= x;
914 object->vertex_data[j * 3 + 1] -= y;
915 object->vertex_data[j * 3 + 2] -= z;
916 }
917#endif
918 }
919#endif
920 }
921
922 return TRUE;
923}
924
925/* rotation tracking tag */
926gboolean x3ds_cb_0xB021(x3ds_global_data *global, x3ds_parent_data *parent)
927{
928 G3DObject *object;
929 gint32 i, j, flags, nkeys, fnum;
930 G3DFloat x, y, z, rot;
931 G3DFloat matrix[16];
932
933 object = parent->level_object;
934 if(object == NULL) return FALSE;
935
936 flags = g3d_stream_read_int16_le(global->stream);
937 g3d_stream_skip(global->stream, 8);
938 nkeys = g3d_stream_read_int16_le(global->stream);
939 g3d_stream_read_int16_le(global->stream);
940 parent->nb -= 14;
941
942 for(i = 0; i < nkeys; i ++)
943 {
944 fnum = g3d_stream_read_int16_le(global->stream);
945 g3d_stream_read_int32_le(global->stream);
946 parent->nb -= 6;
947
948 rot = g3d_stream_read_float_le(global->stream);
949 x = g3d_stream_read_float_le(global->stream);
950 y = g3d_stream_read_float_le(global->stream);
951 z = g3d_stream_read_float_le(global->stream);
952 parent->nb -= 16;
953#if DEBUG > 3
954 g_debug(
955 "[3DS]: ROT_TRACK_TAG: frame %d: (%.2f,%.2f,%.2f), %.2f rad",
956 fnum, x, y, z, rot);
957#endif
958 if(fnum == -1)
959 {
960#if 1
961 g3d_matrix_identity(matrix);
962 g3d_matrix_rotate(rot, x, y, z, matrix);
963
964 for(j = 0; j < object->vertex_count; j ++)
965 {
966 g3d_vector_transform(
967 &(object->vertex_data[j * 3 + 0]),
968 &(object->vertex_data[j * 3 + 1]),
969 &(object->vertex_data[j * 3 + 2]),
970 matrix);
971 }
972#endif
973 }
974 }
975
976 return TRUE;
977
978}
979
980/* node id */
981gboolean x3ds_cb_0xB030(x3ds_global_data *global, x3ds_parent_data *parent)
982{
983 gint32 id;
984
985 id = g3d_stream_read_int16_le(global->stream);
986 parent->nb -= 2;
987#if DEBUG > 3
988 g_debug("[3DS] NODE_ID: %d", id);
989#endif
990
991 return TRUE;
992}