aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ac3d/imp_ac3d.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ac3d/imp_ac3d.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ac3d/imp_ac3d.c534
1 files changed, 534 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ac3d/imp_ac3d.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ac3d/imp_ac3d.c
new file mode 100644
index 0000000..61199ae
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ac3d/imp_ac3d.c
@@ -0,0 +1,534 @@
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 <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <locale.h>
27
28#include <glib.h>
29
30#include <g3d/types.h>
31#include <g3d/context.h>
32#include <g3d/stream.h>
33#include <g3d/material.h>
34#include <g3d/texture.h>
35#include <g3d/debug.h>
36
37#define AC3D_FLAG_ACC 0x01
38
39struct ac3d_transform {
40 G3DFloat offx, offy, offz;
41};
42
43static gint32 ac3d_read_object(G3DStream *stream, G3DContext *context,
44 G3DModel *model, gchar *line, struct ac3d_transform *transform,
45 guint32 flags, GSList **objectlist, gint32 *rowcnt, guint32 level);
46
47EAPI
48gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream,
49 G3DModel *model, gpointer user_data)
50{
51 struct ac3d_transform *transform;
52 gchar buffer[2049], namebuf[257], *filename;
53 guint32 version, ti1, flags = 0;
54 G3DMaterial *material;
55 G3DFloat tf1, tf2, tf3, tf4, tf5, tf6, trans;
56 gint32 rowcnt = 0;
57
58 setlocale(LC_NUMERIC, "C");
59
60 rowcnt ++;
61 g3d_stream_read_line(stream, buffer, 2048);
62
63 if(strncmp(buffer, "AC3D", 4) != 0)
64 {
65 g_warning("file is not a AC3D model");
66 return FALSE;
67 }
68
69 filename = g3d_stream_get_uri(stream);
70 if(g_ascii_strcasecmp(filename + strlen(filename) - 4, ".acc") == 0)
71 {
72#if DEBUG > 0
73 g_debug("AC3D: .acc file");
74#endif
75 flags |= AC3D_FLAG_ACC;
76 }
77
78 version = strtoul(buffer + 4, NULL, 16);
79
80#if DEBUG > 0
81 g_debug("AC3D: version %d", version);
82#endif
83
84 while(g3d_stream_read_line(stream, buffer, 2048))
85 {
86 rowcnt ++;
87 if(strncmp(buffer, "MATERIAL", 8) == 0)
88 {
89 material = g3d_material_new();
90 if(sscanf(buffer,
91 "MATERIAL %s "
92 "rgb " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " "
93 "amb " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " "
94 "emis " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " "
95 "spec %f %f %f "
96 "shi %u "
97 "trans " G3D_SCANF_FLOAT,
98 namebuf,
99 &(material->r), &(material->g), &(material->b),
100 &tf1, &tf2, &tf3,
101 &tf4, &tf5, &tf6,
102 &(material->specular[0]),
103 &(material->specular[1]),
104 &(material->specular[2]),
105 &ti1,
106 &trans) != 15)
107 {
108 g_warning("AC3D: error reading material line (%s)", buffer);
109 }
110
111 material->name = g_strdup(namebuf);
112 material->a = 1.0 - trans;
113
114 model->materials = g_slist_append(model->materials, material);
115 g_debug("\\(0) Material (line %d)", rowcnt);
116 }
117 else if(strncmp(buffer, "OBJECT", 6) == 0)
118 {
119 transform = g_new0(struct ac3d_transform, 1);
120 g_debug("\\(0) Object (line %d)", rowcnt);
121 ac3d_read_object(stream, context, model, buffer, transform, flags,
122 &(model->objects), &rowcnt, 1);
123 }
124 else
125 {
126#if DEBUG > 0
127 g_warning("AC3D: unhandled line: %s", buffer);
128#endif
129 }
130 }
131
132 return TRUE;
133}
134
135EAPI
136gchar *plugin_description(G3DContext *context)
137{
138 return g_strdup("AC3D models.");
139}
140
141EAPI
142gchar **plugin_extensions(G3DContext *context)
143{
144 return g_strsplit("ac:acc", ":", 0);
145}
146
147/*
148 * AC3D specific
149 */
150
151static gchar *ac3d_remove_quotes(gchar *text)
152{
153 if(text[0] == '"')
154 return g_strndup(text + 1, strlen(text) - 2);
155 else
156 return g_strdup(text);
157}
158
159/**
160 * ac3d_read_object:
161 * returns: number of objects (including sub-objects) read, 0 in case of
162 * error.
163 */
164
165static gint32 ac3d_read_object(G3DStream *stream, G3DContext *context,
166 G3DModel *model, gchar *line, struct ac3d_transform *parent_transform,
167 guint32 flags, GSList **objectlist, gint32 *rowcnt, guint32 level)
168{
169 struct ac3d_transform *transform;
170 G3DObject *object;
171 G3DMaterial *material = NULL;
172 G3DFace *face;
173 gchar buffer[2049], namebuf[257];
174 guint32 nkids, ti1, i, surf_flags, surf_done;
175 guint32 i1, i2, i3;
176 G3DFloat u1, u2, u3, v1, v2, v3;
177 G3DFloat locx = 0.0, locy = 0.0, locz = 0.0;
178 G3DFloat texrepu = 1.0, texrepv = 1.0, texoffu = 0.0, texoffv = 0.0;
179 G3DFloat texscaleu = 1.0, texscalev = 1.0;
180 G3DFloat crease = 0.0;
181 guint32 len, facecnt = 0;
182 gchar *filename;
183 gint32 kidsread, objectcount = 0;
184 G3DFloat pcnt, prev_pcnt = 0.0;
185
186 if(sscanf(line, "OBJECT %s", namebuf) != 1)
187 {
188 g_warning("AC3D: error reading object line (%s)", line);
189 }
190
191 transform = g_new0(struct ac3d_transform, 1);
192 memcpy(transform, parent_transform, sizeof(struct ac3d_transform));
193
194 object = g_new0(G3DObject, 1);
195 objectcount ++;
196 *(objectlist) = g_slist_append(*(objectlist), object);
197
198 while(g3d_stream_read_line(stream, buffer, 2048))
199 {
200 *rowcnt += 1;
201 if(strncmp(buffer, "kids", 4) == 0)
202 {
203 /* final line of object */
204 if(sscanf(buffer, "kids %u", &nkids) != 1)
205 {
206 g_warning("AC3D: error reading kids line (%s)", buffer);
207 return 0;
208 }
209 for(i = 0; i < nkids; i ++)
210 {
211 /* read kids */
212 *rowcnt += 1;
213 g3d_stream_read_line(stream, buffer, 2048);
214#if DEBUG > 0
215 g_debug("\\%s(%d) Object (line %d)", debug_pad(level),
216 level, *rowcnt);
217#endif
218 kidsread = ac3d_read_object(stream, context, model, buffer,
219 transform, flags, &(object->objects), rowcnt, level + 1);
220 objectcount += kidsread;
221 }
222
223#if DEBUG > 0
224 g_debug("AC3D: \"%s\": %d sub-objects read",
225 object->name ? object->name : "unnamed",
226 objectcount - 1);
227#endif
228
229 if(crease > 0.0)
230 {
231 /* doesn't really work */
232#if 0
233 g3d_object_smooth(object, crease);
234#endif
235 }
236 return objectcount;
237 }
238 else if(strncmp(buffer, "name", 4) == 0)
239 {
240 if(sscanf(buffer, "name %s", namebuf) != 1)
241 {
242 g_warning("AC3D: error reading name line (%s)", buffer);
243 }
244 else
245 {
246 object->name = g_strdup(namebuf);
247 }
248 }
249 else if(strncmp(buffer, "loc", 3) == 0)
250 {
251 if(sscanf(buffer, "loc " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT, &locx, &locy, &locz) != 3)
252 {
253 g_warning("AC3D: error reading loc line (%s)", buffer);
254 locx = locy = locz = 0.0;
255 }
256
257 transform->offx += locx;
258 transform->offy += locy;
259 transform->offz += locz;
260 }
261 else if(strncmp(buffer, "numvert", 7) == 0)
262 {
263 if(sscanf(buffer, "numvert %u", &(object->vertex_count)) != 1)
264 {
265 g_warning("AC3D: error reading numvert line (%s)", buffer);
266 object->vertex_count = 0;
267 }
268 else
269 {
270 object->vertex_data =
271 g_new0(G3DFloat, object->vertex_count * 3);
272 for(i = 0; i < object->vertex_count; i ++)
273 {
274 if(g3d_stream_read_line(stream, buffer, 2048))
275 {
276 *rowcnt += 1;
277 if(sscanf(buffer, G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT,
278 &(object->vertex_data[i * 3 + 0]),
279 &(object->vertex_data[i * 3 + 1]),
280 &(object->vertex_data[i * 3 + 2])) != 3)
281 {
282 g_warning("AC3D: error reading vertex (%s)",
283 buffer);
284 }
285
286 object->vertex_data[i * 3 + 0] += transform->offx;
287 object->vertex_data[i * 3 + 1] += transform->offy;
288 object->vertex_data[i * 3 + 2] += transform->offz;
289 }
290 }
291 }
292 /* END numvert */
293 }
294 else if(strncmp(buffer, "numsurf", 7) == 0)
295 {
296 /* ignore for now */
297 }
298 else if(strncmp(buffer, "SURF", 4) == 0)
299 {
300 surf_done = 0;
301
302 if(sscanf(buffer, "SURF %x", &surf_flags) != 1)
303 {
304 g_warning("AC3D: error reading surf (%s)", buffer);
305 }
306
307 while(!surf_done)
308 {
309 if(!g3d_stream_read_line(stream, buffer, 2048))
310 return 0;
311 *rowcnt += 1;
312
313 if(sscanf(buffer, "refs %u", &ti1) == 1)
314 {
315 if(!(flags & AC3D_FLAG_ACC))
316 {
317 face = g_new0(G3DFace, 1);
318 face->vertex_count = ti1;
319 face->vertex_indices =
320 g_new0(guint32, face->vertex_count);
321 face->material = material;
322
323 face->tex_image = object->tex_image;
324 if(face->tex_image)
325 {
326 face->flags |= G3D_FLAG_FAC_TEXMAP;
327 }
328
329 face->tex_vertex_count = ti1;
330 face->tex_vertex_data =
331 g_new0(G3DFloat, 2 * face->tex_vertex_count);
332
333 /* normal face */
334 for(i = 0; i < face->vertex_count; i ++)
335 {
336 if(!g3d_stream_read_line(stream, buffer, 2048))
337 return 0;
338 *rowcnt += 1;
339
340 if(sscanf(buffer, "%u " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT,
341 &(face->vertex_indices[i]),
342 &(face->tex_vertex_data[i * 2 + 0]),
343 &(face->tex_vertex_data[i * 2 + 1])) != 3)
344 {
345 g_warning(
346 "AC3D: error reading vertex index (%s)",
347 buffer);
348 }
349 face->tex_vertex_data[i * 2 + 0] *=
350 (texrepu * texscaleu);
351 face->tex_vertex_data[i * 2 + 1] *=
352 (texrepv * texscalev);
353
354 face->tex_vertex_data[i * 2 + 0] += texoffu;
355 face->tex_vertex_data[i * 2 + 1] += texoffv;
356
357#if 0
358 face->tex_coords[i * 2 + 0] *= texscaleu;
359 face->tex_coords[i * 2 + 1] *= texscalev;
360#endif
361 }
362
363 if(face->material && (face->vertex_count >= 3))
364 object->faces =
365 g_slist_prepend(object->faces, face);
366
367 } /* not .acc */
368 else
369 {
370 /* triangle stripes */
371 i = 0;
372 while(i < ti1)
373 {
374 face = g_new0(G3DFace, 1);
375 face->vertex_count = 3;
376 face->vertex_indices = g_new0(guint32, 3);
377
378 face->material = material;
379
380 face->tex_image = object->tex_image;
381 if(face->tex_image)
382 {
383 face->flags |= G3D_FLAG_FAC_TEXMAP;
384 }
385
386 face->tex_vertex_count = 3;
387 face->tex_vertex_data =
388 g_new0(G3DFloat, 2 * face->tex_vertex_count);
389
390 if(i == 0)
391 {
392 /* TODO: error handling */
393 g3d_stream_read_line(stream, buffer, 2048);
394 sscanf(buffer, "%u " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT, &i1, &u1, &v1);
395 g3d_stream_read_line(stream, buffer, 2048);
396 sscanf(buffer, "%u " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT, &i2, &u2, &v2);
397 g3d_stream_read_line(stream, buffer, 2048);
398 sscanf(buffer, "%u " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT, &i3, &u3, &v3);
399
400 *rowcnt += 3;
401 i += 3;
402 }
403 else
404 {
405 /* TODO: error handling */
406 i1 = i2;
407 u1 = u2;
408 v1 = v2;
409 i2 = i3;
410 u2 = u3;
411 v2 = v3;
412
413 g3d_stream_read_line(stream, buffer, 2048);
414 *rowcnt += 1;
415 sscanf(buffer, "%u " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT, &i3, &u3, &v3);
416
417 i ++;
418 }
419
420 face->vertex_indices[0] = i1;
421 face->tex_vertex_data[0] = u1;
422 face->tex_vertex_data[1] = v1;
423 if(facecnt % 2) {
424 face->vertex_indices[1] = i3;
425 face->vertex_indices[2] = i2;
426 face->tex_vertex_data[2] = u3;
427 face->tex_vertex_data[3] = v3;
428 face->tex_vertex_data[4] = u2;
429 face->tex_vertex_data[5] = v2;
430 } else {
431 face->vertex_indices[1] = i2;
432 face->vertex_indices[2] = i3;
433 face->tex_vertex_data[2] = u2;
434 face->tex_vertex_data[3] = v2;
435 face->tex_vertex_data[4] = u3;
436 face->tex_vertex_data[5] = v3;
437 }
438
439 object->faces =
440 g_slist_prepend(object->faces, face);
441 facecnt ++;
442 }
443 } /* .acc */
444
445 surf_done = 1;
446 }
447 else if(sscanf(buffer, "mat %u", &ti1) == 1)
448 {
449 material = g_slist_nth_data(model->materials, ti1);
450 }
451 }
452
453 material = NULL;
454 /* END SURF */
455 }
456 else if(strncmp(buffer, "texture", 7) == 0)
457 {
458 if(sscanf(buffer, "texture %s", namebuf) == 1)
459 {
460 filename = ac3d_remove_quotes(namebuf);
461 object->tex_image = g3d_texture_load_cached(context, model,
462 filename);
463 if(object->tex_image)
464 {
465 g3d_texture_prepare(object->tex_image);
466
467 texscaleu = object->tex_image->tex_scale_u;
468 texscalev = object->tex_image->tex_scale_v;
469 }
470 }
471 else
472 {
473 g_warning("error reading texture line (%s)", buffer);
474 }
475 }
476 else if(strncmp(buffer, "texrep", 6) == 0)
477 {
478 if(sscanf(buffer, "texrep " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT, &texrepu, &texrepv) != 2)
479 {
480 g_warning("error reading texrep line (%s)", buffer);
481 texrepu = 1.0;
482 texrepv = 1.0;
483 }
484
485 if(texrepu == 0.0) texrepu = 1.0;
486 if(texrepv == 0.0) texrepv = 1.0;
487 }
488 else if(strncmp(buffer, "texoff", 6) == 0)
489 {
490 if(sscanf(buffer, "texoff " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT, &texoffu, &texoffv) != 2)
491 {
492 g_warning("error reading texoff line (%s)", buffer);
493 }
494 }
495 else if(strncmp(buffer, "crease", 6) == 0)
496 {
497 if(sscanf(buffer, "crease " G3D_SCANF_FLOAT, &crease) != 1)
498 {
499 g_warning("AC3D: error reading crease line (%i): %s",
500 *rowcnt, buffer);
501 }
502 }
503 else if(strncmp(buffer, "data ", 5) == 0)
504 {
505 /* object data */
506 if(sscanf(buffer, "data %u", &len) != 1)
507 {
508 g_warning("AC3D: error in data line (%i): %s",
509 *rowcnt, buffer);
510 }
511 /* object data on next line */
512 g3d_stream_read_line(stream, buffer, 2048);
513 *rowcnt += 1;
514 }
515 else
516 {
517#if DEBUG > 0
518 g_warning("AC3D: unhandled line %d: %s", *rowcnt, buffer);
519#endif
520 }
521
522 pcnt = (G3DFloat)g3d_stream_tell(stream) /
523 (G3DFloat)g3d_stream_size(stream);
524 if((pcnt - prev_pcnt) > 0.005) {
525 prev_pcnt = pcnt;
526 g3d_context_update_progress_bar(context, pcnt, TRUE);
527 }
528 }
529
530 /* cleanup */
531 g_free(transform);
532
533 return 0;
534}