diff options
Diffstat (limited to '')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_cob/imp_cob.c | 430 |
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 | |||
36 | static gboolean cob_read_file_bin(G3DStream *stream, G3DModel *model, | ||
37 | gboolean is_be, G3DContext *context); | ||
38 | |||
39 | EAPI | ||
40 | gboolean 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 | |||
81 | EAPI | ||
82 | gchar *plugin_description(void) | ||
83 | { | ||
84 | return g_strdup("Caligari TrueSpace models."); | ||
85 | } | ||
86 | |||
87 | EAPI | ||
88 | gchar **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 | |||
104 | static 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 | |||
122 | static 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 | |||
143 | static 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 | |||
159 | static 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 | |||
287 | static 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 | |||
337 | static 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 | |||
365 | static 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 | ||