aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_cob/imp_cob.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_cob/imp_cob.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_cob/imp_cob.c430
1 files changed, 430 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_cob/imp_cob.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_cob/imp_cob.c
new file mode 100644
index 0000000..0e9df6b
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_cob/imp_cob.c
@@ -0,0 +1,430 @@
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
27#include <g3d/types.h>
28#include <g3d/context.h>
29#include <g3d/material.h>
30#include <g3d/model.h>
31#include <g3d/vector.h>
32#include <g3d/matrix.h>
33#include <g3d/stream.h>
34#include <g3d/iff.h>
35
36static gboolean cob_read_file_bin(G3DStream *stream, G3DModel *model,
37 gboolean is_be, G3DContext *context);
38
39EAPI
40gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream,
41 G3DModel *model, gpointer user_data)
42{
43 gchar header[32];
44 gboolean file_is_ascii, file_is_be;
45 G3DMatrix rmatrix[16];
46
47 if(g3d_stream_read(stream, header, 32) != 32) {
48 g_warning("COB: could not read header");
49 return FALSE;
50 }
51
52 if(strncmp(header, "Caligari ", 9) != 0) {
53 g_warning("COB: '%s' is not a valid TrueSpace file", stream->uri);
54 return FALSE;
55 }
56
57 file_is_ascii = (header[15] == 'A');
58 file_is_be = (header[16] == 'H');
59
60#if DEBUG > 0
61 g_debug("COB: file version %.*s, %s, %s endian\n",
62 6, header + 9,
63 file_is_ascii ? "ASCII" : "binary",
64 file_is_be ? "big" : "little" );
65#endif
66
67 if(file_is_ascii) {
68 g_warning("COB: ASCII files are unsupported at the moment");
69 return FALSE;
70 }
71
72 cob_read_file_bin(stream, model, file_is_be, context);
73
74 g3d_matrix_identity(rmatrix);
75 g3d_matrix_rotate_xyz(G_PI * -90.0 / 180, 0.0, 0.0, rmatrix);
76 g3d_model_transform(model, rmatrix);
77
78 return TRUE;
79}
80
81EAPI
82gchar *plugin_description(void)
83{
84 return g_strdup("Caligari TrueSpace models.");
85}
86
87EAPI
88gchar **plugin_extensions(void)
89{
90 return g_strsplit("cob", ":", 0);
91}
92
93/*
94 * COB specific
95 */
96
97#define cob_read_e(stream, what, be) \
98 ((be) ? g3d_stream_read_ ## what ## _be(stream) : \
99 g3d_stream_read_ ## what ## _le(stream))
100
101#define COB_F_HOLE 0x08
102#define COB_F_BACKCULL 0x10
103
104static gboolean cob_read_chunk_header_bin(G3DStream *stream, gboolean is_be,
105 guint32 *type, guint16 *ver_maj, guint16 *ver_min,
106 guint32 *id, guint32 *parent_id, guint32 *len)
107{
108 *type =
109 (g3d_stream_read_int8(stream) << 24) +
110 (g3d_stream_read_int8(stream) << 16) +
111 (g3d_stream_read_int8(stream) << 8) +
112 (g3d_stream_read_int8(stream));
113 *ver_maj = cob_read_e(stream, int16, is_be);
114 *ver_min = cob_read_e(stream, int16, is_be);
115 *id = cob_read_e(stream, int32, is_be);
116 *parent_id = cob_read_e(stream, int32, is_be);
117 *len = cob_read_e(stream, int32, is_be);
118
119 return TRUE;
120}
121
122static gchar *cob_read_name_bin(G3DStream *stream, guint32 *len, gboolean is_be)
123{
124 gchar *buffer, *name;
125 guint32 dc, namelen;
126
127 dc = cob_read_e(stream, int16, is_be);
128 *len -= 2;
129
130 namelen = cob_read_e(stream, int16, is_be);
131 *len -= 2;
132
133 buffer = g_new0(gchar, namelen + 1);
134 g3d_stream_read(stream, buffer, namelen);
135 *len -= namelen;
136
137 name = g_strdup_printf("%s (%d)", buffer, dc);
138
139 g_free(buffer);
140 return name;
141}
142
143static G3DObject *cob_read_grou_bin(G3DStream *stream, guint32 len, gboolean is_be)
144{
145 G3DObject *object;
146
147 object = g_new0(G3DObject, 1);
148 object->name = cob_read_name_bin(stream, &len, is_be);
149#if DEBUG > 0
150 g_debug("COB: Grou: name is '%s'", object->name);
151#endif
152
153 if(len > 0)
154 g3d_stream_skip(stream, len);
155
156 return object;
157}
158
159static G3DObject *cob_read_polh_bin(G3DStream *stream, guint32 len, gboolean is_be,
160 G3DContext *context)
161{
162 G3DObject *object;
163 guint32 nfaces, i;
164 G3DFloat curpos[16];
165
166 object = g_new0(G3DObject, 1);
167 object->name = cob_read_name_bin(stream, &len, is_be);
168#if DEBUG > 0
169 g_debug("COB: PolH: name is '%s'", object->name);
170#endif
171
172 /* local axes: 4 x 12 */
173 g3d_stream_skip(stream, 48);
174 len -= 48;
175
176 /* current position: 3 x 16 */
177 g3d_matrix_identity(curpos);
178 for(i = 0; i < 12; i ++)
179 {
180 curpos[i] = cob_read_e(stream, float, is_be);
181 len -= 4;
182 }
183 g3d_matrix_transpose(curpos);
184
185 /*g3d_matrix_dump(curpos);*/
186
187 /* vertex list */
188 object->vertex_count = cob_read_e(stream, int32, is_be);
189 len -= 4;
190 object->vertex_data = g_new0(G3DFloat, object->vertex_count * 3);
191 for(i = 0; i < object->vertex_count; i ++)
192 {
193 object->vertex_data[i*3+0] = cob_read_e(stream, float, is_be);
194 object->vertex_data[i*3+1] = cob_read_e(stream, float, is_be);
195 object->vertex_data[i*3+2] = cob_read_e(stream, float, is_be);
196 g3d_vector_transform(
197 &(object->vertex_data[i*3+0]),
198 &(object->vertex_data[i*3+1]),
199 &(object->vertex_data[i*3+2]),
200 curpos);
201 g3d_context_update_interface(context);
202 len -= 12;
203 }
204
205 /* texture vertex list */
206 object->tex_vertex_count = cob_read_e(stream, int32, is_be);
207 len -= 4;
208 object->tex_vertex_data = g_new0(G3DFloat, object->tex_vertex_count * 2);
209 for(i = 0; i < object->tex_vertex_count; i ++)
210 {
211 object->tex_vertex_data[i*2+0] = cob_read_e(stream, float, is_be);
212 object->tex_vertex_data[i*2+1] = cob_read_e(stream, float, is_be);
213 g3d_context_update_interface(context);
214 len -= 8;
215 }
216
217 /* faces and holes */
218 nfaces = cob_read_e(stream, int32, is_be);
219 len -= 4;
220 for(i = 0; i < nfaces; i ++)
221 {
222 G3DFace *face;
223 guint8 flags;
224 guint32 nverts, j, matidx;
225
226 flags = g3d_stream_read_int8(stream);
227 len -= 1;
228 if(flags & COB_F_HOLE)
229 {
230 /* hole: ignore for now */
231 nverts = cob_read_e(stream, int16, is_be);
232 len -= 2;
233 for(j = 0; j < nverts; j ++)
234 {
235 cob_read_e(stream, int32, is_be);
236 cob_read_e(stream, int32, is_be);
237 len -= 8;
238 }
239 }
240 else
241 {
242 /* "real" face */
243 nverts = cob_read_e(stream, int16, is_be);
244 len -= 2;
245 matidx = cob_read_e(stream, int16, is_be);
246 len -= 2;
247 face = g_new0(G3DFace, 1);
248
249 face->vertex_count = nverts;
250 face->vertex_indices = g_new0(guint32, nverts);
251 for(j = 0; j < nverts; j ++)
252 {
253 face->vertex_indices[j] = cob_read_e(stream, int32, is_be);
254 cob_read_e(stream, int32, is_be); /* UV indices */
255 len -= 8;
256 }
257
258 /* set material */
259 if(matidx < g_slist_length(object->materials))
260 face->material = g_slist_nth_data(object->materials, matidx);
261 else
262 {
263 for(j = g_slist_length(object->materials); j <= matidx; j ++)
264 {
265 G3DMaterial *material = g3d_material_new();
266 material->name = g_strdup_printf("fallback material %d",
267 j);
268 object->materials =
269 g_slist_append(object->materials, material);
270 }
271
272 face->material = g_slist_nth_data(object->materials, matidx);
273 }
274
275 object->faces = g_slist_prepend(object->faces, face);
276 }
277
278 g3d_context_update_interface(context);
279 }
280
281 if(len > 0)
282 g3d_stream_skip(stream, len);
283
284 return object;
285}
286
287static int cob_read_mat1_bin(G3DStream *stream, guint32 len, gboolean is_be,
288 G3DObject *object)
289{
290 G3DMaterial *material;
291 guint32 matidx;
292
293 g_return_val_if_fail(object != NULL, FALSE);
294
295 matidx = cob_read_e(stream, int16, is_be);
296 len -= 2;
297
298 material = g_slist_nth_data(object->materials, matidx);
299
300 if(material)
301 {
302 g_free(material->name);
303 material->name = g_strdup_printf("material #%d", matidx);
304
305 /* shader type */
306 g3d_stream_read_int8(stream);
307 len --;
308
309 /* facet type */
310 g3d_stream_read_int8(stream);
311 len --;
312
313 /* autofacet angle */
314 g3d_stream_read_int8(stream);
315 len --;
316
317 /* RGBA */
318 material->r = cob_read_e(stream, float, is_be);
319 material->g = cob_read_e(stream, float, is_be);
320 material->b = cob_read_e(stream, float, is_be);
321 material->a = cob_read_e(stream, float, is_be);
322 len -= 16;
323 }
324 else
325 {
326#if DEBUG > 0
327 g_debug("COB: Mat1: material #%d not used, ignoring...", matidx);
328#endif
329 }
330
331 if(len > 0)
332 g3d_stream_skip(stream, len);
333
334 return TRUE;
335}
336
337static int cob_read_unit_bin(G3DStream *stream, guint32 len, gboolean is_be)
338{
339 guint16 uidx;
340#if DEBUG > 0
341 static gchar *units[] = {
342 "millimeters",
343 "centimeters",
344 "meters",
345 "kilometers",
346 "inches",
347 "feet",
348 "yards",
349 "miles",
350 "points" };
351#endif
352
353 uidx = cob_read_e(stream, int16, is_be);
354#if DEBUG > 0
355 if(uidx >= (sizeof(units) / sizeof(gchar *)))
356 {
357 g_warning("COB: Unit: out of range (%d)", uidx);
358 return FALSE;
359 }
360 g_debug("COB: units are %s", units[uidx]);
361#endif
362 return TRUE;
363}
364
365static gboolean cob_read_file_bin(G3DStream *stream, G3DModel *model,
366 gboolean is_be, G3DContext *context)
367{
368 G3DObject *object = NULL;
369 guint32 type, id, parent_id, len;
370 guint16 ver_min, ver_maj;
371 gboolean exit = FALSE;
372
373 do {
374 cob_read_chunk_header_bin(stream, is_be, &type, &ver_maj, &ver_min,
375 &id, &parent_id, &len);
376
377#if DEBUG > 0
378 g_debug("\\[%c%c%c%c] 0x%08x (0x%08x) %d bytes",
379 (type >> 24) & 0xFF, (type >> 16) & 0xFF,
380 (type >> 8) & 0xFF, type & 0xFF,
381 id, parent_id, len);
382#endif
383
384 switch(type)
385 {
386 case G3D_IFF_MKID('E', 'N', 'D', ' '):
387 /* end of file */
388 exit = TRUE;
389 break;
390
391 case G3D_IFF_MKID('G', 'r', 'o', 'u'):
392 /* group */
393 object = cob_read_grou_bin(stream, len, is_be);
394#if 0
395 model->objects = g_slist_append(model->objects, object);
396#endif
397 break;
398
399 case G3D_IFF_MKID('M', 'a', 't', '1'):
400 cob_read_mat1_bin(stream, len, is_be, object);
401 break;
402
403 case G3D_IFF_MKID('P', 'o', 'l', 'H'):
404 /* polygonal data */
405 object = cob_read_polh_bin(stream, len, is_be, context);
406 model->objects = g_slist_append(model->objects, object);
407 break;
408
409 case G3D_IFF_MKID('U', 'n', 'i', 't'):
410 cob_read_unit_bin(stream, len, is_be);
411 break;
412
413 default:
414#if DEBUG > 0
415 g_warning("COB: unknown chunk type: %c%c%c%c: 0x%08x (0x%08x),"
416 " %u bytes",
417 (type >> 24) & 0xFF, (type >> 16) & 0xFF,
418 (type >> 8) & 0xFF, type & 0xFF,
419 id, parent_id, len);
420#endif
421 g3d_stream_skip(stream, len);
422 break;
423 }
424 }
425 while(type && !exit);
426
427 return TRUE;
428}
429
430#undef cob_read_e