diff options
Diffstat (limited to '')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_dae/imp_dae_cb.c | 877 |
1 files changed, 877 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_dae/imp_dae_cb.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_dae/imp_dae_cb.c new file mode 100644 index 0000000..d6aea7d --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_dae/imp_dae_cb.c | |||
@@ -0,0 +1,877 @@ | |||
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 | |||
25 | #include <g3d/config.h> | ||
26 | |||
27 | #include <g3d/types.h> | ||
28 | #include <g3d/material.h> | ||
29 | #include <g3d/matrix.h> | ||
30 | #include <g3d/object.h> | ||
31 | #include <g3d/texture.h> | ||
32 | #include <g3d/stream.h> | ||
33 | |||
34 | #include "imp_dae_cb.h" | ||
35 | #include "imp_dae_chunks.h" | ||
36 | #include "imp_dae_xml.h" | ||
37 | |||
38 | typedef struct { | ||
39 | guint32 offset; | ||
40 | enum { | ||
41 | SEM_UNKNOWN, | ||
42 | SEM_VERTEX, | ||
43 | SEM_NORMAL, | ||
44 | SEM_TEXCOORD | ||
45 | } semantic; | ||
46 | gchar *source; | ||
47 | } DaeInput; | ||
48 | |||
49 | /*****************************************************************************/ | ||
50 | |||
51 | static G3DMaterial *dae_get_material_by_name(DaeGlobalData *global, | ||
52 | const gchar *id, guint32 level) | ||
53 | { | ||
54 | G3DMaterial *material; | ||
55 | GSList *mitem; | ||
56 | xmlNodePtr matnode; | ||
57 | |||
58 | /* try to find material */ | ||
59 | for(mitem = global->model->materials; mitem != NULL; mitem = mitem->next) { | ||
60 | material = (G3DMaterial *)mitem->data; | ||
61 | if(strcmp(material->name, id) == 0) | ||
62 | return material; | ||
63 | } | ||
64 | |||
65 | material = g3d_material_new(); | ||
66 | material->name = g_strdup(id); | ||
67 | global->model->materials = g_slist_append(global->model->materials, | ||
68 | material); | ||
69 | |||
70 | /* find material in library */ | ||
71 | matnode = dae_library_lookup(global->lib, "symbol", id); | ||
72 | |||
73 | if(matnode) { | ||
74 | dae_xml_parse(global, matnode, dae_chunks_material, | ||
75 | level, material); | ||
76 | } | ||
77 | return material; | ||
78 | } | ||
79 | |||
80 | static GSList *dae_get_inputs(xmlNodePtr node) | ||
81 | { | ||
82 | xmlNodePtr inode = NULL; | ||
83 | gchar *soff, *ssem; | ||
84 | DaeInput *input; | ||
85 | GSList *inputs = NULL; | ||
86 | |||
87 | while(dae_xml_next_child_by_tagname(node, &inode, "input")) { | ||
88 | input = g_new0(DaeInput, 1); | ||
89 | soff = dae_xml_get_attr(inode, "offset"); | ||
90 | if(soff) { | ||
91 | input->offset = atoi(soff); | ||
92 | g_free(soff); | ||
93 | } | ||
94 | ssem = dae_xml_get_attr(inode, "semantic"); | ||
95 | if(ssem) { | ||
96 | if(strcmp(ssem, "VERTEX") == 0) | ||
97 | input->semantic = SEM_VERTEX; | ||
98 | else if(strcmp(ssem, "NORMAL") == 0) | ||
99 | input->semantic = SEM_NORMAL; | ||
100 | else if(strcmp(ssem, "TEXCOORD") == 0) | ||
101 | input->semantic = SEM_TEXCOORD; | ||
102 | else { | ||
103 | g_warning("DAE: unknown input semantic '%s'", ssem); | ||
104 | input->semantic = SEM_UNKNOWN; | ||
105 | } | ||
106 | g_free(ssem); | ||
107 | } | ||
108 | input->source = dae_xml_get_attr(inode, "source"); | ||
109 | inputs = g_slist_append(inputs, input); | ||
110 | } | ||
111 | return inputs; | ||
112 | } | ||
113 | |||
114 | static void dae_inputs_free(GSList *inputs) | ||
115 | { | ||
116 | GSList *item; | ||
117 | DaeInput *input; | ||
118 | |||
119 | for(item = inputs; item != NULL; item = item->next) { | ||
120 | input = (DaeInput *)item->data; | ||
121 | if(input->source) | ||
122 | g_free(input->source); | ||
123 | g_free(input); | ||
124 | item->data = NULL; | ||
125 | } | ||
126 | g_slist_free(inputs); | ||
127 | } | ||
128 | |||
129 | static gboolean dae_load_source(DaeLibrary *lib, gchar *id, | ||
130 | G3DFloat **asrc, guint32 *nsrc) | ||
131 | { | ||
132 | xmlNodePtr snode, fnode; | ||
133 | gchar *scnt, *next = NULL; | ||
134 | gint i; | ||
135 | |||
136 | snode = dae_library_lookup(lib, "source", id + 1); | ||
137 | #if DEBUG > 0 | ||
138 | g_debug("DAE: source '%s': %p", id + 1, (void *)snode); | ||
139 | #endif | ||
140 | if(snode == NULL) | ||
141 | return FALSE; | ||
142 | |||
143 | fnode = dae_xml_get_child_by_tagname(snode, "float_array"); | ||
144 | if(fnode == NULL) | ||
145 | return FALSE; | ||
146 | |||
147 | scnt = dae_xml_get_attr(fnode, "count"); | ||
148 | #if DEBUG > 0 | ||
149 | g_debug("DAE: float_array count=\"%s\"", scnt); | ||
150 | #endif | ||
151 | if(scnt == NULL) | ||
152 | return FALSE; | ||
153 | *nsrc = atoi(scnt); | ||
154 | g_free(scnt); | ||
155 | if(*nsrc == 0) | ||
156 | return FALSE; | ||
157 | |||
158 | *asrc = g_new0(G3DFloat, *nsrc); | ||
159 | for(i = 0; i < *nsrc; i ++) | ||
160 | #if G3D_FLOAT_IS_DOUBLE | ||
161 | if(!dae_xml_next_double(fnode, &next, &((*asrc)[i]))) | ||
162 | #else | ||
163 | if(!dae_xml_next_float(fnode, &next, &((*asrc)[i]))) | ||
164 | #endif | ||
165 | return FALSE; | ||
166 | |||
167 | return TRUE; | ||
168 | } | ||
169 | |||
170 | /*****************************************************************************/ | ||
171 | |||
172 | gboolean dae_cb_bind_material(DaeGlobalData *global, DaeLocalData *local) | ||
173 | { | ||
174 | return dae_xml_parse(global, local->node, dae_chunks_bind_material, | ||
175 | local->level, local->user_data); | ||
176 | } | ||
177 | |||
178 | gboolean dae_cb_effect(DaeGlobalData *global, DaeLocalData *local) | ||
179 | { | ||
180 | return dae_xml_parse(global, local->node, dae_chunks_effect, | ||
181 | local->level, local->user_data); | ||
182 | } | ||
183 | |||
184 | gboolean dae_cb_geometry(DaeGlobalData *global, DaeLocalData *local) | ||
185 | { | ||
186 | G3DObject *object; | ||
187 | G3DMaterial *material; | ||
188 | |||
189 | object = (G3DObject *)local->user_data; | ||
190 | g_return_val_if_fail(object != NULL, FALSE); | ||
191 | |||
192 | material = g3d_material_new(); | ||
193 | material->name = g_strdup("(default material)"); | ||
194 | object->materials = g_slist_append(object->materials, material); | ||
195 | |||
196 | if(local->instance) { | ||
197 | /* parse original node */ | ||
198 | dae_xml_parse(global, local->instance, | ||
199 | dae_chunks_geometry, local->level, object); | ||
200 | } | ||
201 | |||
202 | /* parse instanced stuff */ | ||
203 | return dae_xml_parse(global, local->node, dae_chunks_geometry, | ||
204 | local->level, object); | ||
205 | } | ||
206 | |||
207 | gboolean dae_cb_matrix(DaeGlobalData *global, DaeLocalData *local) | ||
208 | { | ||
209 | G3DObject *object = local->user_data; | ||
210 | G3DTransformation *transform; | ||
211 | gchar *next = NULL; | ||
212 | gint i; | ||
213 | |||
214 | g_return_val_if_fail(object != NULL, FALSE); | ||
215 | |||
216 | transform = object->transformation; | ||
217 | if(transform == NULL) { | ||
218 | transform = g_new0(G3DTransformation, 1); | ||
219 | g3d_matrix_identity(transform->matrix); | ||
220 | object->transformation = transform; | ||
221 | } | ||
222 | |||
223 | for(i = 0; i < 16; i ++) | ||
224 | #if G3D_FLOAT_IS_DOUBLE | ||
225 | dae_xml_next_double(local->node, &next, transform->matrix + i); | ||
226 | #else | ||
227 | dae_xml_next_float(local->node, &next, transform->matrix + i); | ||
228 | #endif | ||
229 | g3d_matrix_transpose(transform->matrix); | ||
230 | #if DEBUG > 3 | ||
231 | g_debug("DAE: matrix for '%s':", object->name); | ||
232 | g3d_matrix_dump(transform->matrix); | ||
233 | #endif | ||
234 | return TRUE; | ||
235 | } | ||
236 | |||
237 | gboolean dae_cb_mesh(DaeGlobalData *global, DaeLocalData *local) | ||
238 | { | ||
239 | return dae_xml_parse(global, local->node, dae_chunks_mesh, | ||
240 | local->level, local->user_data); | ||
241 | } | ||
242 | |||
243 | gboolean dae_cb_newparam(DaeGlobalData *global, DaeLocalData *local) | ||
244 | { | ||
245 | G3DMaterial *material = (G3DMaterial *)local->user_data; | ||
246 | G3DStream *imgstream = NULL; | ||
247 | xmlNodePtr n1, n2; | ||
248 | gchar *siid = NULL, *filename, *subfile; | ||
249 | #ifdef HAVE_LIBGSF | ||
250 | gchar *container, *pipe; | ||
251 | #endif | ||
252 | |||
253 | g_return_val_if_fail(material != NULL, FALSE); | ||
254 | |||
255 | n1 = dae_xml_get_child_by_tagname(local->node, "surface"); | ||
256 | if(n1 != NULL) { | ||
257 | n2 = dae_xml_get_child_by_tagname(n1, "init_from"); | ||
258 | if(n2 != NULL) | ||
259 | siid = g_strdup((gchar *)n2->children->content); | ||
260 | } | ||
261 | if(siid == NULL) | ||
262 | return FALSE; | ||
263 | |||
264 | n1 = dae_library_lookup(global->lib, "image", siid); | ||
265 | g_free(siid); | ||
266 | if(n1 == NULL) | ||
267 | return FALSE; | ||
268 | |||
269 | n2 = dae_xml_get_child_by_tagname(n1, "init_from"); | ||
270 | if(n2 == NULL) | ||
271 | return FALSE; | ||
272 | |||
273 | filename = (gchar *)n2->children->content; | ||
274 | |||
275 | if(strncmp(global->stream->uri, "zip://", 6) == 0) { | ||
276 | #ifdef HAVE_LIBGSF | ||
277 | /* .dae was loaded from .kmz, get texture from .kmz, too */ | ||
278 | pipe = strchr(global->stream->uri, '|'); | ||
279 | if(pipe != NULL) { | ||
280 | container = g_strndup(global->stream->uri + 6, | ||
281 | (pipe - global->stream->uri) - 6); | ||
282 | subfile = filename; | ||
283 | while(strncmp(subfile, "../", 3) == 0) | ||
284 | subfile += 3; | ||
285 | g_debug("DAE: loading '%s' from: '%s'", subfile, container); | ||
286 | imgstream = g3d_stream_open_zip_from_stream(global->stream->zip_container, subfile); | ||
287 | } | ||
288 | #endif | ||
289 | } else { | ||
290 | imgstream = g3d_stream_open_file(filename, "rb"); | ||
291 | if(imgstream == NULL) { | ||
292 | /* if opened from unpacked doc.kml, textures are found in | ||
293 | * ../images/, so strip leading ../ */ | ||
294 | subfile = filename; | ||
295 | while(strncmp(subfile, "../", 3) == 0) | ||
296 | subfile += 3; | ||
297 | imgstream = g3d_stream_open_file(subfile, "rb"); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | if(imgstream != NULL) { | ||
302 | material->tex_image = g3d_texture_load_from_stream(global->context, | ||
303 | global->model, imgstream); | ||
304 | if(material->tex_image) { | ||
305 | material->tex_image->tex_env = G3D_TEXENV_DECAL; | ||
306 | } | ||
307 | g3d_stream_close(imgstream); | ||
308 | return TRUE; | ||
309 | } | ||
310 | |||
311 | return FALSE; | ||
312 | } | ||
313 | |||
314 | gboolean dae_cb_node(DaeGlobalData *global, DaeLocalData *local) | ||
315 | { | ||
316 | G3DObject *object, *pobject; | ||
317 | G3DMatrix matrix[16]; | ||
318 | gchar *name; | ||
319 | |||
320 | name = dae_xml_get_attr(local->node, "name"); | ||
321 | if(name == NULL) | ||
322 | name = dae_xml_get_attr(local->node, "id"); | ||
323 | if(name == NULL) | ||
324 | return FALSE; | ||
325 | |||
326 | pobject = (G3DObject *)local->user_data; | ||
327 | object = g_new0(G3DObject, 1); | ||
328 | object->name = name; | ||
329 | if(pobject) | ||
330 | pobject->objects = g_slist_append(pobject->objects, object); | ||
331 | else | ||
332 | global->model->objects = g_slist_append(global->model->objects, | ||
333 | object); | ||
334 | |||
335 | if(dae_xml_parse(global, local->node, dae_chunks_node, local->level, | ||
336 | object)) { | ||
337 | if(object->transformation) { | ||
338 | g3d_object_transform(object, object->transformation->matrix); | ||
339 | #if DEBUG > 3 | ||
340 | g_debug("DAE: transforming object '%s'", object->name); | ||
341 | g3d_matrix_dump(object->transformation->matrix); | ||
342 | #endif | ||
343 | g_free(object->transformation); | ||
344 | object->transformation = NULL; | ||
345 | } | ||
346 | |||
347 | if(!pobject) { | ||
348 | g3d_matrix_identity(matrix); | ||
349 | g3d_matrix_rotate(-90.0 * G_PI / 180.0, 1.0, 0.0, 0.0, matrix); | ||
350 | g3d_object_transform(object, matrix); | ||
351 | } | ||
352 | return TRUE; | ||
353 | } | ||
354 | return FALSE; | ||
355 | } | ||
356 | |||
357 | gboolean dae_cb_phong(DaeGlobalData *global, DaeLocalData *local) | ||
358 | { | ||
359 | G3DMaterial *material = (G3DMaterial *)local->user_data; | ||
360 | xmlNodePtr n1, n2; | ||
361 | gchar *next; | ||
362 | |||
363 | g_return_val_if_fail(material != NULL, FALSE); | ||
364 | |||
365 | /* diffuse */ | ||
366 | n1 = dae_xml_get_child_by_tagname(local->node, "diffuse"); | ||
367 | if(n1 != NULL) { | ||
368 | n2 = dae_xml_get_child_by_tagname(n1, "color"); | ||
369 | if(n2 != NULL) { | ||
370 | next = NULL; | ||
371 | #if G3D_FLOAT_IS_DOUBLE | ||
372 | dae_xml_next_double(n2, &next, &(material->r)); | ||
373 | dae_xml_next_double(n2, &next, &(material->g)); | ||
374 | dae_xml_next_double(n2, &next, &(material->b)); | ||
375 | dae_xml_next_double(n2, &next, &(material->a)); | ||
376 | #else | ||
377 | dae_xml_next_float(n2, &next, &(material->r)); | ||
378 | dae_xml_next_float(n2, &next, &(material->g)); | ||
379 | dae_xml_next_float(n2, &next, &(material->b)); | ||
380 | dae_xml_next_float(n2, &next, &(material->a)); | ||
381 | #endif | ||
382 | } | ||
383 | } | ||
384 | |||
385 | /* specular */ | ||
386 | n1 = dae_xml_get_child_by_tagname(local->node, "specular"); | ||
387 | if(n1 != NULL) { | ||
388 | n2 = dae_xml_get_child_by_tagname(n1, "color"); | ||
389 | if(n2 != NULL) { | ||
390 | next = NULL; | ||
391 | /* These are floats either way. */ | ||
392 | dae_xml_next_float(n2, &next, &(material->specular[0])); | ||
393 | dae_xml_next_float(n2, &next, &(material->specular[1])); | ||
394 | dae_xml_next_float(n2, &next, &(material->specular[2])); | ||
395 | dae_xml_next_float(n2, &next, &(material->specular[3])); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | return TRUE; | ||
400 | } | ||
401 | |||
402 | gboolean dae_cb_polylist(DaeGlobalData *global, DaeLocalData *local) | ||
403 | { | ||
404 | G3DObject *object = local->user_data; | ||
405 | G3DFace *face; | ||
406 | G3DMaterial *material; | ||
407 | xmlNodePtr pnode, vnode; | ||
408 | gchar *scnt, *smat, *nextp = NULL, *nextv = NULL; | ||
409 | guint32 count, normal_count, tex_count, flags = 0; | ||
410 | gint i, j, nv, tmp; | ||
411 | GSList *inputs, *item; | ||
412 | DaeInput *input; | ||
413 | G3DFloat *normal_data = NULL, *tex_data = NULL; | ||
414 | |||
415 | g_return_val_if_fail(object != NULL, FALSE); | ||
416 | |||
417 | scnt = dae_xml_get_attr(local->node, "count"); | ||
418 | g_return_val_if_fail(scnt != NULL, FALSE); | ||
419 | count = atoi(scnt); | ||
420 | g_free(scnt); | ||
421 | g_return_val_if_fail(count != 0, FALSE); | ||
422 | |||
423 | pnode = dae_xml_get_child_by_tagname(local->node, "p"); | ||
424 | vnode = dae_xml_get_child_by_tagname(local->node, "vcount"); | ||
425 | g_return_val_if_fail((pnode != NULL) && (vnode != NULL), FALSE); | ||
426 | |||
427 | /* material */ | ||
428 | material = g_slist_nth_data(object->materials, 0); | ||
429 | smat = dae_xml_get_attr(local->node, "material"); | ||
430 | if(smat != NULL) { | ||
431 | material = dae_get_material_by_name(global, smat, local->level); | ||
432 | g_free(smat); | ||
433 | } | ||
434 | |||
435 | /* get all inputs */ | ||
436 | inputs = dae_get_inputs(local->node); | ||
437 | for(item = inputs; item != NULL; item = item->next) { | ||
438 | input = (DaeInput *)item->data; | ||
439 | if(input->semantic == SEM_NORMAL) | ||
440 | if(dae_load_source(global->lib, input->source, | ||
441 | &normal_data, &normal_count)) | ||
442 | flags |= G3D_FLAG_FAC_NORMALS; | ||
443 | if(input->semantic == SEM_TEXCOORD) | ||
444 | if(dae_load_source(global->lib, input->source, | ||
445 | &tex_data, &tex_count) && (material->tex_image != NULL)) | ||
446 | flags |= G3D_FLAG_FAC_TEXMAP; | ||
447 | } | ||
448 | |||
449 | for(i = 0; i < count; i ++) { | ||
450 | if(dae_xml_next_int(vnode, &nextv, &nv) && (nv > 0)) { | ||
451 | face = g_new0(G3DFace, 1); | ||
452 | face->vertex_count = nv; | ||
453 | face->vertex_indices = g_new0(guint32, nv); | ||
454 | face->material = material; | ||
455 | face->flags = flags; | ||
456 | object->faces = g_slist_append(object->faces, face); | ||
457 | |||
458 | if(face->flags & G3D_FLAG_FAC_NORMALS) { | ||
459 | face->normals = g_new0(G3DFloat, nv * 3); | ||
460 | } | ||
461 | if(face->flags & G3D_FLAG_FAC_TEXMAP) { | ||
462 | face->tex_image = material->tex_image; | ||
463 | face->tex_vertex_count = nv; | ||
464 | face->tex_vertex_data = g_new0(G3DFloat, nv * 2); | ||
465 | } | ||
466 | |||
467 | for(j = 0; j < nv; j ++) { | ||
468 | for(item = inputs; item != NULL; item = item->next) { | ||
469 | input = (DaeInput *)item->data; | ||
470 | dae_xml_next_int(pnode, &nextp, &tmp); | ||
471 | switch(input->semantic) { | ||
472 | case SEM_VERTEX: | ||
473 | face->vertex_indices[j] = tmp; | ||
474 | if(face->vertex_indices[j] >= object->vertex_count) | ||
475 | { | ||
476 | g_warning("polylist: [%s] face[%d] (%d) >= %d", | ||
477 | object->name, j, face->vertex_indices[j], | ||
478 | object->vertex_count); | ||
479 | face->vertex_indices[j] = 0; | ||
480 | } | ||
481 | break; | ||
482 | case SEM_NORMAL: | ||
483 | if(flags & G3D_FLAG_FAC_NORMALS) { | ||
484 | face->normals[j * 3 + 0] = | ||
485 | normal_data[tmp * 3 + 0]; | ||
486 | face->normals[j * 3 + 1] = | ||
487 | normal_data[tmp * 3 + 1]; | ||
488 | face->normals[j * 3 + 2] = | ||
489 | normal_data[tmp * 3 + 2]; | ||
490 | } | ||
491 | break; | ||
492 | case SEM_TEXCOORD: | ||
493 | if(flags & G3D_FLAG_FAC_TEXMAP) { | ||
494 | face->tex_vertex_data[j * 2 + 0] = | ||
495 | tex_data[tmp * 2 + 0]; | ||
496 | face->tex_vertex_data[j * 2 + 1] = 1.0 - | ||
497 | tex_data[tmp * 2 + 1]; | ||
498 | } | ||
499 | break; | ||
500 | case SEM_UNKNOWN: | ||
501 | break; | ||
502 | } | ||
503 | } /* inputs */ | ||
504 | } | ||
505 | #if DEBUG > 3 | ||
506 | g_debug("DAE: %-2i, %-2i, %-2i, (%-2i)", | ||
507 | face->vertex_indices[0], | ||
508 | face->vertex_indices[1], | ||
509 | face->vertex_indices[2], | ||
510 | ((nv > 3) ? face->vertex_indices[3] : -1)); | ||
511 | #endif | ||
512 | } | ||
513 | } | ||
514 | |||
515 | if(tex_data) | ||
516 | g_free(tex_data); | ||
517 | if(normal_data) | ||
518 | g_free(normal_data); | ||
519 | dae_inputs_free(inputs); | ||
520 | |||
521 | return TRUE; | ||
522 | } | ||
523 | |||
524 | gboolean dae_cb_profile_COMMON(DaeGlobalData *global, DaeLocalData *local) | ||
525 | { | ||
526 | return dae_xml_parse(global, local->node, dae_chunks_profile_COMMON, | ||
527 | local->level, local->user_data); | ||
528 | } | ||
529 | |||
530 | gboolean dae_cb_rotate(DaeGlobalData *global, DaeLocalData *local) | ||
531 | { | ||
532 | G3DObject *object = local->user_data; | ||
533 | G3DTransformation *transform; | ||
534 | G3DFloat x = 0.0, y = 0.0, z = 0.0, a = 0.0, m[16]; | ||
535 | gchar *next = NULL; | ||
536 | |||
537 | g_return_val_if_fail(object != NULL, FALSE); | ||
538 | |||
539 | transform = object->transformation; | ||
540 | if(transform == NULL) { | ||
541 | transform = g_new0(G3DTransformation, 1); | ||
542 | g3d_matrix_identity(transform->matrix); | ||
543 | object->transformation = transform; | ||
544 | } | ||
545 | |||
546 | #if G3D_FLOAT_IS_DOUBLE | ||
547 | dae_xml_next_double(local->node, &next, &x); | ||
548 | dae_xml_next_double(local->node, &next, &y); | ||
549 | dae_xml_next_double(local->node, &next, &z); | ||
550 | dae_xml_next_double(local->node, &next, &a); | ||
551 | #else | ||
552 | dae_xml_next_float(local->node, &next, &x); | ||
553 | dae_xml_next_float(local->node, &next, &y); | ||
554 | dae_xml_next_float(local->node, &next, &z); | ||
555 | dae_xml_next_float(local->node, &next, &a); | ||
556 | #endif | ||
557 | g_return_val_if_fail((x != 0.0) || (y != 0.0) || (z != 0.0), FALSE); | ||
558 | g3d_matrix_rotate(a, x, y, z, m); | ||
559 | g3d_matrix_multiply(transform->matrix, m, transform->matrix); | ||
560 | #if DEBUG > 3 | ||
561 | g_debug("DAE: rotation for '%s': %.2f, %.2f, %.2f - %.2f", object->name, | ||
562 | x, y, z, a); | ||
563 | g3d_matrix_dump(transform->matrix); | ||
564 | #endif | ||
565 | return TRUE; | ||
566 | } | ||
567 | |||
568 | gboolean dae_cb_scale(DaeGlobalData *global, DaeLocalData *local) | ||
569 | { | ||
570 | G3DObject *object = local->user_data; | ||
571 | G3DTransformation *transform; | ||
572 | G3DFloat x = 0.0, y = 0.0, z = 0.0; | ||
573 | gchar *next = NULL; | ||
574 | |||
575 | g_return_val_if_fail(object != NULL, FALSE); | ||
576 | |||
577 | transform = object->transformation; | ||
578 | if(transform == NULL) { | ||
579 | transform = g_new0(G3DTransformation, 1); | ||
580 | g3d_matrix_identity(transform->matrix); | ||
581 | object->transformation = transform; | ||
582 | } | ||
583 | |||
584 | #if G3D_FLOAT_IS_DOUBLE | ||
585 | dae_xml_next_double(local->node, &next, &x); | ||
586 | dae_xml_next_double(local->node, &next, &y); | ||
587 | dae_xml_next_double(local->node, &next, &z); | ||
588 | #else | ||
589 | dae_xml_next_float(local->node, &next, &x); | ||
590 | dae_xml_next_float(local->node, &next, &y); | ||
591 | dae_xml_next_float(local->node, &next, &z); | ||
592 | #endif | ||
593 | g3d_matrix_scale(x, y, z, transform->matrix); | ||
594 | #if DEBUG > 3 | ||
595 | g_debug("DAE: scale for '%s': %.2f, %.2f, %.2f", object->name, | ||
596 | x, y, z); | ||
597 | g3d_matrix_dump(transform->matrix); | ||
598 | #endif | ||
599 | return TRUE; | ||
600 | } | ||
601 | |||
602 | gboolean dae_cb_source(DaeGlobalData *global, DaeLocalData *local) | ||
603 | { | ||
604 | gchar *id; | ||
605 | |||
606 | id = dae_xml_get_attr(local->node, "id"); | ||
607 | if(id) { | ||
608 | dae_library_add(global->lib, "source", id, local->node); | ||
609 | g_free(id); | ||
610 | return TRUE; | ||
611 | } | ||
612 | return FALSE; | ||
613 | } | ||
614 | |||
615 | gboolean dae_cb_technique(DaeGlobalData *global, DaeLocalData *local) | ||
616 | { | ||
617 | return dae_xml_parse(global, local->node, dae_chunks_technique, | ||
618 | local->level, local->user_data); | ||
619 | } | ||
620 | |||
621 | /* instance_geometry::bind_material::technique_common */ | ||
622 | gboolean dae_cb_technique_common(DaeGlobalData *global, DaeLocalData *local) | ||
623 | { | ||
624 | xmlNodePtr node = NULL, tnode; | ||
625 | gchar *symbol, *target; | ||
626 | |||
627 | while(dae_xml_next_child_by_tagname(local->node, &node, | ||
628 | "instance_material")) { | ||
629 | symbol = dae_xml_get_attr(node, "symbol"); | ||
630 | if(symbol == NULL) | ||
631 | continue; | ||
632 | target = dae_xml_get_attr(node, "target"); | ||
633 | if(target == NULL) { | ||
634 | g_free(symbol); | ||
635 | continue; | ||
636 | } | ||
637 | tnode = dae_library_lookup(global->lib, "material", target + 1); | ||
638 | if(tnode) | ||
639 | dae_library_add(global->lib, "symbol", symbol, tnode); | ||
640 | g_free(symbol); | ||
641 | g_free(target); | ||
642 | } | ||
643 | return TRUE; | ||
644 | } | ||
645 | |||
646 | gboolean dae_cb_translate(DaeGlobalData *global, DaeLocalData *local) | ||
647 | { | ||
648 | G3DObject *object = local->user_data; | ||
649 | G3DTransformation *transform; | ||
650 | G3DFloat x = 0.0, y = 0.0, z = 0.0; | ||
651 | gchar *next = NULL; | ||
652 | |||
653 | g_return_val_if_fail(object != NULL, FALSE); | ||
654 | |||
655 | transform = object->transformation; | ||
656 | if(transform == NULL) { | ||
657 | transform = g_new0(G3DTransformation, 1); | ||
658 | g3d_matrix_identity(transform->matrix); | ||
659 | object->transformation = transform; | ||
660 | } | ||
661 | |||
662 | #if G3D_FLOAT_IS_DOUBLE | ||
663 | dae_xml_next_double(local->node, &next, &x); | ||
664 | dae_xml_next_double(local->node, &next, &y); | ||
665 | dae_xml_next_double(local->node, &next, &z); | ||
666 | #else | ||
667 | dae_xml_next_float(local->node, &next, &x); | ||
668 | dae_xml_next_float(local->node, &next, &y); | ||
669 | dae_xml_next_float(local->node, &next, &z); | ||
670 | #endif | ||
671 | g3d_matrix_translate(x, y, z, transform->matrix); | ||
672 | #if DEBUG > 3 | ||
673 | g_debug("DAE: translation for '%s': %.2f, %.2f, %.2f", object->name, | ||
674 | x, y, z); | ||
675 | g3d_matrix_dump(transform->matrix); | ||
676 | #endif | ||
677 | return TRUE; | ||
678 | } | ||
679 | |||
680 | gboolean dae_cb_triangles(DaeGlobalData *global, DaeLocalData *local) | ||
681 | { | ||
682 | G3DObject *object = local->user_data; | ||
683 | G3DFace *face; | ||
684 | G3DMaterial *material; | ||
685 | xmlNodePtr pnode; | ||
686 | gchar *scnt, *smat, *nextp = NULL; | ||
687 | guint32 count, normal_count, tex_count, flags = 0; | ||
688 | G3DFloat *normal_data = NULL, *tex_data = NULL; | ||
689 | gint i, j, tmp; | ||
690 | GSList *inputs, *item; | ||
691 | DaeInput *input; | ||
692 | |||
693 | g_return_val_if_fail(object != NULL, FALSE); | ||
694 | |||
695 | scnt = dae_xml_get_attr(local->node, "count"); | ||
696 | g_return_val_if_fail(scnt != NULL, FALSE); | ||
697 | count = atoi(scnt); | ||
698 | g_return_val_if_fail(count != 0, FALSE); | ||
699 | g_free(scnt); | ||
700 | |||
701 | pnode = dae_xml_get_child_by_tagname(local->node, "p"); | ||
702 | g_return_val_if_fail(pnode != NULL, FALSE); | ||
703 | |||
704 | /* material */ | ||
705 | material = g_slist_nth_data(object->materials, 0); | ||
706 | smat = dae_xml_get_attr(local->node, "material"); | ||
707 | if(smat != NULL) { | ||
708 | material = dae_get_material_by_name(global, smat, local->level); | ||
709 | g_free(smat); | ||
710 | } | ||
711 | |||
712 | /* get all inputs */ | ||
713 | inputs = dae_get_inputs(local->node); | ||
714 | for(item = inputs; item != NULL; item = item->next) { | ||
715 | input = (DaeInput *)item->data; | ||
716 | if(input->semantic == SEM_NORMAL) | ||
717 | if(dae_load_source(global->lib, input->source, | ||
718 | &normal_data, &normal_count)) { | ||
719 | flags |= G3D_FLAG_FAC_NORMALS; | ||
720 | } | ||
721 | if(input->semantic == SEM_TEXCOORD) | ||
722 | if(dae_load_source(global->lib, input->source, | ||
723 | &tex_data, &tex_count) && (material->tex_image != NULL)) { | ||
724 | flags |= G3D_FLAG_FAC_TEXMAP; | ||
725 | } | ||
726 | } | ||
727 | |||
728 | for(i = 0; i < count; i ++) { | ||
729 | face = g_new0(G3DFace, 1); | ||
730 | face->vertex_count = 3; | ||
731 | face->vertex_indices = g_new0(guint32, 3); | ||
732 | face->material = material; | ||
733 | face->flags = flags; | ||
734 | object->faces = g_slist_append(object->faces, face); | ||
735 | |||
736 | if(face->flags & G3D_FLAG_FAC_NORMALS) { | ||
737 | face->normals = g_new0(G3DFloat, 3 * 3); | ||
738 | } | ||
739 | if(face->flags & G3D_FLAG_FAC_TEXMAP) { | ||
740 | face->tex_image = material->tex_image; | ||
741 | face->tex_vertex_count = 3; | ||
742 | face->tex_vertex_data = g_new0(G3DFloat, 3 * 2); | ||
743 | } | ||
744 | |||
745 | for(j = 0; j < 3; j ++) { | ||
746 | for(item = inputs; item != NULL; item = item->next) { | ||
747 | input = (DaeInput *)item->data; | ||
748 | dae_xml_next_int(pnode, &nextp, &tmp); | ||
749 | switch(input->semantic) { | ||
750 | case SEM_VERTEX: | ||
751 | face->vertex_indices[j] = tmp; | ||
752 | if(face->vertex_indices[j] >= object->vertex_count) { | ||
753 | g_warning("triangles: [%s] face[%d] (%d) >= %d", | ||
754 | object->name, j, face->vertex_indices[j], | ||
755 | object->vertex_count); | ||
756 | face->vertex_indices[j] = 0; | ||
757 | } | ||
758 | break; | ||
759 | case SEM_NORMAL: | ||
760 | if(flags & G3D_FLAG_FAC_NORMALS) { | ||
761 | face->normals[j * 3 + 0] = | ||
762 | normal_data[tmp * 3 + 0]; | ||
763 | face->normals[j * 3 + 1] = | ||
764 | normal_data[tmp * 3 + 1]; | ||
765 | face->normals[j * 3 + 2] = | ||
766 | normal_data[tmp * 3 + 2]; | ||
767 | } | ||
768 | break; | ||
769 | case SEM_TEXCOORD: | ||
770 | if(flags & G3D_FLAG_FAC_TEXMAP) { | ||
771 | face->tex_vertex_data[j * 2 + 0] = | ||
772 | tex_data[tmp * 2 + 0]; | ||
773 | face->tex_vertex_data[j * 2 + 1] = 1.0 - | ||
774 | tex_data[tmp * 2 + 1]; | ||
775 | } | ||
776 | break; | ||
777 | case SEM_UNKNOWN: | ||
778 | break; | ||
779 | } | ||
780 | } /* inputs */ | ||
781 | #if DEBUG > 3 | ||
782 | g_debug("DAE: %-2i, %-2i, %-2i", | ||
783 | face->vertex_indices[0], | ||
784 | face->vertex_indices[1], | ||
785 | face->vertex_indices[2]); | ||
786 | #endif | ||
787 | } | ||
788 | } | ||
789 | if(tex_data) | ||
790 | g_free(tex_data); | ||
791 | if(normal_data) | ||
792 | g_free(normal_data); | ||
793 | dae_inputs_free(inputs); | ||
794 | |||
795 | return TRUE; | ||
796 | } | ||
797 | |||
798 | gboolean dae_cb_vertices(DaeGlobalData *global, DaeLocalData *local) | ||
799 | { | ||
800 | return dae_xml_parse(global, local->node, dae_chunks_vertices, | ||
801 | local->level, local->user_data); | ||
802 | } | ||
803 | |||
804 | gboolean dae_cb_vertices__input(DaeGlobalData *global, DaeLocalData *local) | ||
805 | { | ||
806 | G3DObject *object = (G3DObject *)(local->user_data); | ||
807 | gchar *sid, *sem, *cnt, *next = NULL; | ||
808 | gboolean skip = FALSE; | ||
809 | xmlNodePtr snode, fanode; | ||
810 | gint i, j; | ||
811 | |||
812 | g_return_val_if_fail(object != NULL, FALSE); | ||
813 | |||
814 | sem = dae_xml_get_attr(local->node, "semantic"); | ||
815 | sid = dae_xml_get_attr(local->node, "source"); | ||
816 | g_return_val_if_fail((sem != NULL) && (sid != NULL), FALSE); | ||
817 | |||
818 | /* get 'source' node, skip leading '#' from 'source' attribute */ | ||
819 | snode = dae_library_lookup(global->lib, "source", sid + 1); | ||
820 | #if DEBUG > 0 | ||
821 | g_debug("DAE: looking up source '%s' from library: %p", sid + 1, | ||
822 | (void *)snode); | ||
823 | #endif | ||
824 | g_return_val_if_fail(snode != NULL, FALSE); | ||
825 | |||
826 | if(sem) | ||
827 | g_free(sem); | ||
828 | if(sid) | ||
829 | g_free(sid); | ||
830 | |||
831 | /* TODO: check technique_common/accessor */ | ||
832 | |||
833 | fanode = dae_xml_get_child_by_tagname(snode, "float_array"); | ||
834 | if(fanode) { | ||
835 | cnt = dae_xml_get_attr(fanode, "count"); | ||
836 | #if DEBUG > 0 | ||
837 | g_debug("DAE: float_array count=\"%s\"", cnt); | ||
838 | #endif | ||
839 | g_return_val_if_fail(cnt != NULL, FALSE); | ||
840 | |||
841 | object->vertex_count = atoi(cnt); | ||
842 | g_return_val_if_fail(object->vertex_count != 0, FALSE); | ||
843 | |||
844 | object->vertex_data = g_new0(G3DFloat, 3 * object->vertex_count); | ||
845 | for(i = 0; i < object->vertex_count / 3; i ++) | ||
846 | { | ||
847 | for(j = 0; j < 3; j ++) | ||
848 | { | ||
849 | #if G3D_FLOAT_IS_DOUBLE | ||
850 | if(!dae_xml_next_double(fanode, &next, &(object->vertex_data[i * 3 + j]))) | ||
851 | #else | ||
852 | if(!dae_xml_next_float(fanode, &next, &(object->vertex_data[i * 3 + j]))) | ||
853 | #endif | ||
854 | { | ||
855 | skip = TRUE; | ||
856 | break; | ||
857 | } | ||
858 | } | ||
859 | #if DEBUG > 3 | ||
860 | g_debug("DAE: %-3.2f, %-3.2f, %-3.2f", | ||
861 | object->vertex_data[i * 3 + 0], | ||
862 | object->vertex_data[i * 3 + 1], | ||
863 | object->vertex_data[i * 3 + 2]); | ||
864 | #endif | ||
865 | if(skip) | ||
866 | break; | ||
867 | } | ||
868 | } | ||
869 | |||
870 | return TRUE; | ||
871 | } | ||
872 | |||
873 | gboolean dae_cb_visual_scene(DaeGlobalData *global, DaeLocalData *local) | ||
874 | { | ||
875 | return dae_xml_parse(global, local->node, dae_chunks_visual_scene, | ||
876 | local->level, NULL); | ||
877 | } | ||