aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max_callbacks.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max_callbacks.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max_callbacks.c696
1 files changed, 696 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max_callbacks.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max_callbacks.c
new file mode 100644
index 0000000..219ad4f
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max_callbacks.c
@@ -0,0 +1,696 @@
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 <g3d/material.h>
25#include <g3d/stream.h>
26#include <g3d/debug.h>
27
28#include "imp_max_callbacks.h"
29
30static gchar *max_read_wchar(G3DStream *stream, guint32 n)
31{
32 gint32 i;
33 gunichar2 *u16text;
34 gchar *text;
35 GError *error = NULL;
36
37 u16text = g_new0(gunichar2, n + 1);
38 for(i = 0; i < n; i ++) {
39 u16text[i] = g3d_stream_read_int16_le(stream);
40 }
41
42 text = g_utf16_to_utf8(u16text, n, NULL, NULL, &error);
43 if(error != NULL) {
44 g_warning("UTF-16 to UTF-8 conversion failed: %s",
45 error->message);
46 g_error_free(error);
47 }
48 g_free(u16text);
49
50 return text;
51}
52
53gboolean max_cb_debug_int32(MaxGlobalData *global, MaxLocalData *local)
54{
55 union {
56 gint32 i;
57 G3DFloat f;
58 } u;
59
60 while(local->nb >= 4) {
61 u.i = g3d_stream_read_int32_le(global->stream);
62 local->nb -= 4;
63#if DEBUG > 0
64 g_debug("|%s[D32] 0x%08x, %d, %.2f", debug_pad(local->level),
65 u.i, u.i, u.f);
66#endif
67 }
68 return TRUE;
69}
70
71gboolean max_cb_debug_wchars(MaxGlobalData *global, MaxLocalData *local)
72{
73 gchar *str;
74 guint32 len;
75
76 len = local->nb / 2;
77 str = max_read_wchar(global->stream, len);
78 local->nb -= len * 2;
79#if DEBUG > 0
80 g_debug("|%s[TEXT] %s (%d)", debug_pad(local->level),
81 str, len);
82#endif
83 g_free(str);
84
85 return TRUE;
86}
87
88gboolean max_cb_debug_string(MaxGlobalData *global, MaxLocalData *local)
89{
90 gchar *str;
91 guint32 len;
92
93 g_return_val_if_fail(local->nb >= 4, FALSE);
94 len = g3d_stream_read_int32_le(global->stream);
95 local->nb -= 4;
96 if(len > local->nb)
97 len = local->nb;
98
99 str = g_new0(gchar, len + 1);
100 g3d_stream_read(global->stream, str, len);
101 local->nb -= len;
102#if DEBUG > 0
103 g_debug("|%s[TEXT] %s (%d)", debug_pad(local->level),
104 str, len);
105#endif
106 g_free(str);
107
108 return TRUE;
109}
110
111gboolean max_cb_0x0001_0x0005(MaxGlobalData *global, MaxLocalData *local)
112{
113 gchar *str;
114 gint32 len, i, w3[3], cnt = 0;
115
116 if(local->nb < 4)
117 return FALSE;
118
119 /* flags? */
120 i = g3d_stream_read_int32_le(global->stream);
121 local->nb -= 4;
122
123#if DEBUG > 0
124 g_debug("|%s[PROP] 0x%08x", debug_pad(local->level), i);
125#endif
126
127 while(local->nb > 0) {
128 len = g3d_stream_read_int32_le(global->stream);
129 local->nb -= 4;
130 str = g_malloc0(len + 1);
131 g3d_stream_read(global->stream, str, len);
132 local->nb -= len;
133 for(i = 0; i < 3; i ++)
134 w3[i] = g3d_stream_read_int16_le(global->stream);
135 local->nb -= 6;
136 cnt ++;
137#if DEBUG > 0
138 g_debug("|%s[PROP] %04d: '%s' (%d bytes) [%d, %d, %d]",
139 debug_pad(local->level),
140 cnt, str, len,
141 w3[0], w3[1], w3[2]);
142#endif
143 g_free(str);
144 }
145 return TRUE;
146}
147
148gboolean max_cb_IDFILE_0x1201(MaxGlobalData *global, MaxLocalData *local)
149{
150 guint16 width, height;
151
152 width = g3d_stream_read_int16_le(global->stream);
153 height = g3d_stream_read_int16_le(global->stream);
154 local->nb -= 4;
155#if DEBUG > 0
156 g_debug("|%s[IMG] %u x %u", debug_pad(local->level), width, height);
157#endif
158 return TRUE;
159}
160
161/* vertex data */
162gboolean max_cb_0x08FE_0x0100(MaxGlobalData *global, MaxLocalData *local)
163{
164 guint32 num;
165 gint i, j;
166 G3DObject *object;
167
168 if(local->nb < 4)
169 return FALSE;
170
171 /* vertices */
172 num = g3d_stream_read_int32_le(global->stream);
173 local->nb -= 4;
174 object = (G3DObject *)local->object;
175 if(object == NULL) {
176 g_warning("MAX: 0x08FE::0x0100: no object");
177 return FALSE;
178 }
179
180#if DEBUG > 0
181 g_debug("|%s[VERT] %d vertices", debug_pad(local->level), num);
182#endif
183 global->vertex_offset = object->vertex_count;
184 object->vertex_count += num;
185 object->vertex_data = g_realloc(object->vertex_data,
186 object->vertex_count * 3 * sizeof(G3DFloat));
187
188 for(i = 0; i < num; i ++) {
189 if(local->nb < 16)
190 return FALSE;
191 g3d_stream_read_int32_le(global->stream); /* always 0 */
192 for(j = 0; j < 3; j ++)
193 object->vertex_data[(global->vertex_offset + i) * 3 + j] =
194 g3d_stream_read_float_le(global->stream);
195 local->nb -= 16;
196 }
197 return TRUE;
198}
199
200/* lines (vertex indices) */
201gboolean max_cb_0x08FE_0x010A(MaxGlobalData *global, MaxLocalData *local)
202{
203 guint32 num;
204 gint i, j;
205 guint32 v[3];
206
207 if(local->nb < 4)
208 return FALSE;
209
210 num = g3d_stream_read_int32_le(global->stream);
211 local->nb -= 4;
212
213#if DEBUG > 0
214 g_debug("|%s[LINE] %d lines", debug_pad(local->level), num);
215#endif
216 for(i = 0; i < num; i ++) {
217 if(local->nb < 12)
218 return FALSE;
219 for(j = 0; j < 3; j ++) {
220 v[j] = g3d_stream_read_int32_le(global->stream);
221 }
222 local->nb -= 12;
223
224#if DEBUG > 1
225 g_debug("|%s[LINE] 0x%08x: (%d => %d)", debug_pad(local->level),
226 v[0], v[1], v[2]);
227#endif
228 }
229 return TRUE;
230}
231
232/* polygon data */
233gboolean max_cb_0x08FE_0x011A(MaxGlobalData *global, MaxLocalData *local)
234{
235 gint32 i;
236 guint32 numpoly, type, numvert, cntpoly = 0;
237 G3DObject *object = (G3DObject *)local->object;
238 G3DFace *face;
239 G3DMaterial *material;
240
241 g_return_val_if_fail(local->nb >= 4, FALSE);
242 g_return_val_if_fail(object != NULL, FALSE);
243
244 material = (G3DMaterial *)g_slist_nth_data(global->model->materials,
245 (global->vertex_offset ? 1 : 0));
246 g_return_val_if_fail(material != NULL, FALSE);
247
248 numpoly = g3d_stream_read_int32_le(global->stream);
249 local->nb -= 4;
250#if DEBUG > 0
251 g_debug("|%s[POLY] %d polygons to read", debug_pad(local->level),
252 numpoly);
253#endif
254 while(local->nb >= 4) {
255 numvert = g3d_stream_read_int32_le(global->stream);
256 local->nb -= 4;
257#if DEBUG > 0
258 g_debug("|%s[POLY] %04d: %d vertices", debug_pad(local->level),
259 cntpoly, numvert);
260#endif
261 g_return_val_if_fail(numvert >= 3, FALSE);
262
263 face = g_new0(G3DFace, 1);
264 face->material = material;
265 face->vertex_count = numvert;
266 face->vertex_indices = g_new0(guint32, numvert);
267 object->faces = g_slist_append(object->faces, face);
268 for(i = 0; i < numvert; i ++) {
269 face->vertex_indices[i] =
270 global->vertex_offset +
271 g3d_stream_read_int32_le(global->stream);
272 local->nb -= 4;
273 g_return_val_if_fail(
274 face->vertex_indices[i] < object->vertex_count, FALSE);
275 }
276 type = g3d_stream_read_int16_le(global->stream);
277 local->nb -= 2;
278
279 if(type & 0xFFC6) {
280 g_warning("MAX: 0x011A: unhandled 0x%08x", type);
281#if DEBUG > 0
282 numvert = MIN(local->nb / 2, 20);
283 for(i = 0; i < numvert; i ++) {
284 g_debug("|%s[POLY] 0x%04x", debug_pad(local->level),
285 g3d_stream_read_int16_le(global->stream));
286 local->nb -= 2;
287 }
288#endif
289 return FALSE;
290 }
291
292 /* FIXME: order of additional data most likely wrong */
293 for(i = 3; i < numvert; i ++) {
294 g3d_stream_read_int32_le(global->stream);
295 g3d_stream_read_int32_le(global->stream);
296 local->nb -= 8;
297 }
298 if(type & 0x0001) {
299 g3d_stream_read_int32_le(global->stream);
300 local->nb -= 4;
301 }
302 if(type & 0x0008) {
303 g3d_stream_read_int16_le(global->stream);
304 local->nb -= 2;
305 }
306 if(type & 0x0010) {
307 g3d_stream_read_int32_le(global->stream);
308 local->nb -= 4;
309 }
310 cntpoly ++;
311 }
312#if DEBUG > 0
313 g_debug("|%s[POLY] %d faces added to object", debug_pad(local->level),
314 cntpoly);
315#endif
316 return TRUE;
317}
318
319/* texture vertices */
320gboolean max_cb_0x08FE_0x0128(MaxGlobalData *global, MaxLocalData *local)
321{
322 guint32 num;
323 G3DObject *object = (G3DObject *)local->object;
324
325 g_return_val_if_fail(local->nb >= 4, FALSE);
326 g_return_val_if_fail(object != NULL, FALSE);
327
328 num = g3d_stream_read_int32_le(global->stream);
329 local->nb -= 4;
330
331#if DEBUG > 0
332 g_debug("|%s[TEXV] %d texture vertices", debug_pad(local->level), num);
333#endif
334 return TRUE;
335}
336
337/* texture indices */
338gboolean max_cb_0x08FE_0x012B(MaxGlobalData *global, MaxLocalData *local)
339{
340 gint i;
341 guint32 *vdata, vcnt, maxidx = 0, numpoly = 0, maxvcnt = 0;
342#if 0
343 G3DObject *object = (G3DObject *)local->object;
344 G3DFace *face;
345
346 g_return_val_if_fail(object != NULL, FALSE);
347#endif
348
349 while(local->nb >= 4) {
350 vcnt = g3d_stream_read_int32_le(global->stream);
351 local->nb -= 4;
352 if(vcnt > maxvcnt)
353 maxvcnt = vcnt;
354#if 0
355 face = g_new0(G3DFace, 1);
356 face->vertex_count = vcnt;
357#endif
358 if(local->nb < (vcnt * 4)) {
359#if DEBUG > 0
360 g_debug("|%s[TIDX] %d polygons, max index: %d, max vcnt: %d "
361 "(nb=%d, vcnt=%d)", debug_pad(local->level),
362 numpoly, maxidx, maxvcnt, local->nb, vcnt);
363#endif
364
365 return FALSE;
366 }
367 vdata = g_new0(guint32, vcnt);
368 numpoly ++;
369 for(i = 0; i < vcnt; i ++) {
370 vdata[i] = g3d_stream_read_int32_le(global->stream);
371 local->nb -= 4;
372 if(vdata[i] > maxidx)
373 maxidx = vdata[i];
374 }
375#if 1
376 g_free(vdata);
377#endif
378 }
379#if DEBUG > 0
380 g_debug("|%s[TIDX] %d polygons, max index: %d, max vcnt: %d",
381 debug_pad(local->level), numpoly, maxidx, maxvcnt);
382#endif
383 return TRUE;
384}
385
386/* geometric object */
387gboolean max_cb_IDROOT_IDGEOM(MaxGlobalData *global, MaxLocalData *local)
388{
389 G3DObject *object;
390
391 object = g_new0(G3DObject, 1);
392 object->name = g_strdup_printf("0x%04X object @ 0x%08x",
393 local->id, (guint32)g3d_stream_tell(global->stream));
394 local->object = object;
395 global->model->objects = g_slist_append(global->model->objects, object);
396
397 global->object = object;
398 global->vertex_offset = 0;
399
400 return TRUE;
401}
402
403/* mesh */
404gboolean max_cb_IDGEOM_0x08FE(MaxGlobalData *global, MaxLocalData *local)
405{
406 g_return_val_if_fail(global->object != NULL, FALSE);
407 return TRUE;
408}
409
410/* object name */
411gboolean max_cb_IDGEOM_0x0962(MaxGlobalData *global, MaxLocalData *local)
412{
413 G3DObject *object = (G3DObject *)local->object;
414 gchar *name;
415 gint32 len;
416
417 g_return_val_if_fail(object != NULL, FALSE);
418
419 g_free(object->name);
420 len = local->nb / 2;
421 name = max_read_wchar(global->stream, len);
422 object->name = g_strdup_printf("%s (0x%08x)",
423 name, (guint32)g3d_stream_tell(global->stream) - len - 6);
424 g_free(name);
425#if DEBUG > 0
426 g_debug("|%s[NAME] %s", debug_pad(local->level), object->name);
427#endif
428 local->nb -= len * 2;
429
430 return TRUE;
431}
432
433/* single face */
434gboolean max_cb_0x0118_0x0110(MaxGlobalData *global, MaxLocalData *local)
435{
436 guint32 num;
437 gint i;
438 G3DObject *object = (G3DObject *)local->object;
439 G3DMaterial *mat;
440 G3DFace *face;
441
442 g_return_val_if_fail(local->nb >= 4, FALSE);
443 g_return_val_if_fail(object != NULL, FALSE);
444
445 mat = (G3DMaterial *)g_slist_nth_data(global->model->materials,
446 (global->vertex_offset ? 1 : 0));
447
448 num = g3d_stream_read_int32_le(global->stream);
449 local->nb -= 4;
450
451 face = g_new0(G3DFace, 1);
452 face->vertex_count = num;
453 face->vertex_indices = g_new0(guint32, num);
454 face->material = mat;
455 object->faces = g_slist_append(object->faces, face);
456
457 g_return_val_if_fail(local->nb >= (num * 4), FALSE);
458 for(i = 0; i < num; i ++) {
459 face->vertex_indices[i] =
460 global->vertex_offset +
461 g3d_stream_read_int32_le(global->stream);
462 local->nb -= 4;
463 if(face->vertex_indices[i] >= object->vertex_count) {
464 g_warning("MAX: 0x0118::0x0110: vertex index (%d) >= "
465 "vertex count (%d)",
466 face->vertex_indices[i],
467 object->vertex_count);
468 face->vertex_indices[i] = 0;
469 }
470 }
471 return TRUE;
472}
473
474/* triangles */
475gboolean max_cb_0x08FE_0x0912(MaxGlobalData *global, MaxLocalData *local)
476{
477 guint32 num;
478 gint i, j;
479 G3DObject *object;
480 G3DFace *face;
481 G3DMaterial *mat;
482
483 mat = (G3DMaterial *)g_slist_nth_data(global->model->materials,
484 (global->vertex_offset ? 1 : 0));
485
486 if(local->nb < 4)
487 return FALSE;
488
489 /* faces */
490 num = g3d_stream_read_int32_le(global->stream);
491 local->nb -= 4;
492 object = (G3DObject *)local->object;
493 if(object == NULL) {
494 g_warning("MAX: 0x08FE::0x0912: no object");
495 return FALSE;
496 }
497#if DEBUG > 0
498 g_debug("|%s[TRIS] %d triangles", debug_pad(local->level), num);
499#endif
500 for(i = 0; i < num; i ++) {
501 face = g_new0(G3DFace, 1);
502 face->vertex_count = 3;
503 face->vertex_indices = g_new0(guint32, 3);
504 face->material = mat;
505 object->faces = g_slist_append(object->faces, face);
506
507 if(local->nb < 20)
508 return FALSE;
509 for(j = 0; j < 3; j ++) {
510 face->vertex_indices[j] =
511 global->vertex_offset +
512 g3d_stream_read_int32_le(global->stream);
513 if(face->vertex_indices[j] >= object->vertex_count) {
514 g_warning("MAX: 0x08FE::0x0912: vertex index too high"
515 " (%d (0x%08x) >= %d)",
516 face->vertex_indices[j], face->vertex_indices[j],
517 object->vertex_count);
518 face->vertex_indices[j] = 0;
519 }
520 }
521 /* unknown for now */
522 g3d_stream_read_int32_le(global->stream);
523 g3d_stream_read_int32_le(global->stream);
524 local->nb -= 20;
525 }
526 return TRUE;
527}
528
529/* vertices */
530gboolean max_cb_0x08FE_0x0914(MaxGlobalData *global, MaxLocalData *local)
531{
532 guint32 num;
533 gint i, j;
534 G3DObject *object = (G3DObject *)local->object;
535
536 g_return_val_if_fail(local->nb >= 4, FALSE);
537 g_return_val_if_fail(object != NULL, FALSE);
538
539 /* vertices */
540 num = g3d_stream_read_int32_le(global->stream);
541 local->nb -= 4;
542#if DEBUG > 0
543 g_debug("|%s[VERT] %d vertices", debug_pad(local->level), num);
544#endif
545 global->vertex_offset = object->vertex_count;
546 object->vertex_count += num;
547 object->vertex_data = g_realloc(object->vertex_data,
548 object->vertex_count * 3 * sizeof(G3DFloat));
549
550 for(i = 0; i < num; i ++) {
551 if(local->nb < 12)
552 return FALSE;
553 for(j = 0; j < 3; j ++)
554 object->vertex_data[(global->vertex_offset + i) * 3 + j] =
555 g3d_stream_read_float_le(global->stream);
556 local->nb -= 12;
557 }
558 return TRUE;
559}
560
561/* texture vertices */
562gboolean max_cb_0x08FE_0x0916(MaxGlobalData *global, MaxLocalData *local)
563{
564 return max_cb_0x08FE_0x0128(global, local);
565}
566
567/* texture triangles */
568gboolean max_cb_0x08FE_0x0918(MaxGlobalData *global, MaxLocalData *local)
569{
570 guint32 cnttris = 0;
571
572 while(local->nb >= 12) {
573 cnttris ++;
574
575 g3d_stream_read_int32_le(global->stream);
576 g3d_stream_read_int32_le(global->stream);
577 g3d_stream_read_int32_le(global->stream);
578 local->nb -= 12;
579 }
580
581#if DEBUG > 0
582 g_debug("|%s[TEXI] %d textured triangles (%d bytes left)",
583 debug_pad(local->level), cnttris, local->nb);
584#endif
585 return 0;
586}
587
588/* vertices */
589gboolean max_cb_0x08FE_0x2394(MaxGlobalData *global, MaxLocalData *local)
590{
591 return max_cb_0x08FE_0x0914(global, local);
592}
593
594/* triangles */
595gboolean max_cb_0x08FE_0x2396(MaxGlobalData *global, MaxLocalData *local)
596{
597 guint32 num;
598 gint32 i, j;
599 G3DObject *object = (G3DObject *)local->object;
600 G3DFace *face;
601 G3DMaterial *mat;
602
603 mat = (G3DMaterial *)g_slist_nth_data(global->model->materials,
604 (global->vertex_offset ? 1 : 0));
605
606 g_return_val_if_fail(local->nb >= 4, FALSE);
607 g_return_val_if_fail(object != NULL, FALSE);
608
609 /* faces */
610 num = g3d_stream_read_int32_le(global->stream);
611 local->nb -= 4;
612#if DEBUG > 0
613 g_debug("|%s[TRIS] %d triangles", debug_pad(local->level), num);
614#endif
615 for(i = 0; i < num; i ++) {
616 g_return_val_if_fail(local->nb >= 12, FALSE);
617
618 face = g_new0(G3DFace, 1);
619 face->vertex_count = 3;
620 face->vertex_indices = g_new0(guint32, 3);
621 face->material = mat;
622 object->faces = g_slist_append(object->faces, face);
623
624 g_return_val_if_fail(local->nb >= 12, FALSE);
625 for(j = 0; j < 3; j ++) {
626 face->vertex_indices[j] =
627 global->vertex_offset +
628 g3d_stream_read_int32_le(global->stream);
629 local->nb -= 4;
630 if(face->vertex_indices[j] >= object->vertex_count) {
631 g_warning("MAX: 0x08FE::0x2396: vertex index too high"
632 " (%d (0x%08x) >= %d)",
633 face->vertex_indices[j], face->vertex_indices[j],
634 object->vertex_count);
635 face->vertex_indices[j] = 0;
636 }
637 }
638 }
639 return TRUE;
640}
641
642/* material */
643gboolean max_cb_IDMATG_0x4000(MaxGlobalData *global, MaxLocalData *local)
644{
645 G3DMaterial *material;
646
647 if(strcmp(global->subfile, "Scene") != 0)
648 return FALSE;
649
650 material = g3d_material_new();
651 material->name = g_strdup_printf("0x4000 material @ 0x%08x",
652 (guint32)g3d_stream_tell(global->stream));
653 local->object = material;
654 global->model->materials = g_slist_append(global->model->materials,
655 material);
656 return TRUE;
657}
658
659/* material name */
660gboolean max_cb_0x4000_0x4001(MaxGlobalData *global, MaxLocalData *local)
661{
662 guint32 len;
663 G3DMaterial *material = (G3DMaterial *)local->object;
664
665 g_return_val_if_fail(material != NULL, FALSE);
666 if(material->name)
667 g_free(material->name);
668 len = local->nb / 2;
669 material->name = max_read_wchar(global->stream, len);
670 local->nb -= len * 2;
671#if DEBUG > 0
672 g_debug("|%s[MATN] %s", debug_pad(local->level), material->name);
673#endif
674 return TRUE;
675}
676
677/* material color */
678gboolean max_cb_0x4000_0x4030(MaxGlobalData *global, MaxLocalData *local)
679{
680 G3DMaterial *material = (G3DMaterial *)local->object;
681
682 g_return_val_if_fail(material != NULL, FALSE);
683 g_return_val_if_fail(local->nb >= 16, FALSE);
684
685 material->r = g3d_stream_read_float_le(global->stream);
686 material->g = g3d_stream_read_float_le(global->stream);
687 material->b = g3d_stream_read_float_le(global->stream);
688 material->a = g3d_stream_read_float_le(global->stream);
689 local->nb -= 16;
690#if DEBUG > 0
691 g_debug("|%s[MATC] %.2f, %.2f, %.2f, %.2f", debug_pad(local->level),
692 material->r, material->g, material->b, material->a);
693#endif
694 return TRUE;
695}
696