diff options
Diffstat (limited to '')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_max/imp_max_callbacks.c | 696 |
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 | |||
30 | static 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 | |||
53 | gboolean 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 | |||
71 | gboolean 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 | |||
88 | gboolean 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 | |||
111 | gboolean 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 | |||
148 | gboolean 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 */ | ||
162 | gboolean 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) */ | ||
201 | gboolean 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 */ | ||
233 | gboolean 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 */ | ||
320 | gboolean 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 */ | ||
338 | gboolean 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 */ | ||
387 | gboolean 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 */ | ||
404 | gboolean 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 */ | ||
411 | gboolean 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 */ | ||
434 | gboolean 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 */ | ||
475 | gboolean 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 */ | ||
530 | gboolean 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 */ | ||
562 | gboolean max_cb_0x08FE_0x0916(MaxGlobalData *global, MaxLocalData *local) | ||
563 | { | ||
564 | return max_cb_0x08FE_0x0128(global, local); | ||
565 | } | ||
566 | |||
567 | /* texture triangles */ | ||
568 | gboolean 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 */ | ||
589 | gboolean max_cb_0x08FE_0x2394(MaxGlobalData *global, MaxLocalData *local) | ||
590 | { | ||
591 | return max_cb_0x08FE_0x0914(global, local); | ||
592 | } | ||
593 | |||
594 | /* triangles */ | ||
595 | gboolean 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 */ | ||
643 | gboolean 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 */ | ||
660 | gboolean 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 */ | ||
678 | gboolean 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 | |||