aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_c4d/imp_c4d.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_c4d/imp_c4d.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_c4d/imp_c4d.c363
1 files changed, 363 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_c4d/imp_c4d.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_c4d/imp_c4d.c
new file mode 100644
index 0000000..93415f2
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_c4d/imp_c4d.c
@@ -0,0 +1,363 @@
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/types.h>
26#include <g3d/stream.h>
27#include <g3d/debug.h>
28
29static gboolean c4d_load_v5(G3DContext *context, G3DStream *stream,
30 G3DModel *model);
31static gboolean c4d_load_v6(G3DContext *context, G3DStream *stream,
32 G3DModel *model);
33
34EAPI
35gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream,
36 G3DModel *model, gpointer user_data)
37{
38 gchar magic[5];
39
40 g3d_stream_read(stream, magic, 4);
41 magic[4] = '\0';
42 if(strncmp(magic + 1, "C4D", 3) == 0) {
43 g3d_stream_read(stream, magic, 4);
44 if(strncmp(magic, "C4D6", 4) == 0)
45 return c4d_load_v6(context, stream, model);
46 else {
47 g_warning("unknown C4D magic: %s", magic);
48 return FALSE;
49 }
50 } else if(strncmp(magic + 1, "C50", 3) == 0) {
51 g_debug("C4D v5: %s", magic);
52 return c4d_load_v5(context, stream, model);
53 } else {
54 g_warning("C4D: unknown magic %s, not a C4D file?", magic);
55 return FALSE;
56 }
57 return TRUE;
58}
59
60EAPI
61gchar *plugin_description(void)
62{
63 return g_strdup("Cinema4D models.");
64}
65
66EAPI
67gchar **plugin_extensions(void)
68{
69 return g_strsplit("c4d", ":", 0);
70}
71
72/*****************************************************************************/
73
74static gchar *c4d_read_wchar(G3DStream *stream, gsize *n_bytes)
75{
76 guint32 len;
77 gunichar2 *u16text;
78 gchar *text;
79 gint32 i;
80 GError *error = NULL;
81
82 len = g3d_stream_read_int32_be(stream);
83 *n_bytes += 4 + len;
84 u16text = g_new0(gunichar2, len + 1);
85 for(i = 0; i < len / 2; i ++)
86 u16text[i] = g3d_stream_read_int16_be(stream);
87 text = g_utf16_to_utf8(u16text, len, NULL, NULL, &error);
88 if(error != NULL) {
89 g_warning("UTF-16 to UTF-8 conversion failed: %s", error->message);
90 g_error_free(error);
91 }
92 g_free(u16text);
93 return text;
94}
95
96#define C4D_DEBUG_OPCODE 0
97
98static gboolean c4d_handle_opcode(guint8 opcode, G3DStream *stream,
99 G3DModel *model, gsize *n_bytes, guint32 *level)
100{
101 guint8 u1, *data;
102 guint16 w1, w2, w3;
103 guint32 x1, x3;
104 gsize x2;
105 G3DFloat f1, f2, f3;
106 gchar *str;
107 gint32 i;
108
109 switch(opcode) {
110 case 0x01: /* 64 bit something */
111 *level += 1;
112 x1 = g3d_stream_read_int32_be(stream);
113 x2 = g3d_stream_read_int32_be(stream);
114 *n_bytes += 8;
115#if DEBUG > C4D_DEBUG_OPCODE
116 g_debug("\\%s01: 0x%08x 0x%08x", debug_pad(*level), x1, x2);
117#endif
118 break;
119 case 0x02: /* no payload */
120#if DEBUG > C4D_DEBUG_OPCODE
121 g_debug("\\%s02", debug_pad(*level));
122#endif
123 if(*level == 0) {
124 g_warning("E: 02: level == 0)");
125 } else
126 *level -= 1;
127 break;
128 case 0x0C: /* 8 bit something */
129 u1 = g3d_stream_read_int8(stream);
130 *n_bytes += 1;
131#if DEBUG > C4D_DEBUG_OPCODE
132 g_debug("\\%s0C: 0x%02x", debug_pad(*level), u1);
133#endif
134 break;
135 case 0x0F: /* 32 bit something */
136 x1 = g3d_stream_read_int32_be(stream);
137 *n_bytes += 4;
138#if DEBUG > C4D_DEBUG_OPCODE
139 g_debug("\\%s0F: 0x%08x", debug_pad(*level), x1);
140#endif
141 break;
142 case 0x10: /* 32 bit something */
143 x1 = g3d_stream_read_int32_be(stream);
144 *n_bytes += 4;
145#if DEBUG > C4D_DEBUG_OPCODE
146 g_debug("\\%s10: 0x%08x", debug_pad(*level), x1);
147#endif
148 break;
149 case 0x13: /* float */
150 f1 = g3d_stream_read_float_be(stream);
151 *n_bytes += 4;
152#if DEBUG > C4D_DEBUG_OPCODE
153 g_debug("\\%s13: %.3f", debug_pad(*level), f1);
154#endif
155 break;
156 case 0x15: /* 8 bit something */
157 u1 = g3d_stream_read_int8(stream);
158 *n_bytes += 1;
159#if DEBUG > C4D_DEBUG_OPCODE
160 g_debug("\\%s15: 0x%02x", debug_pad(*level), u1);
161#endif
162 break;
163 case 0x16: /* 2 x float */
164 f1 = g3d_stream_read_float_be(stream);
165 f2 = g3d_stream_read_float_be(stream);
166 *n_bytes += 8;
167#if DEBUG > C4D_DEBUG_OPCODE
168 g_debug("\\%s16: %.3f, %.3f", debug_pad(*level), f1, f2);
169#endif
170 break;
171 case 0x17: /* 3 x float */
172 f1 = g3d_stream_read_float_be(stream);
173 f2 = g3d_stream_read_float_be(stream);
174 f3 = g3d_stream_read_float_be(stream);
175 *n_bytes += 12;
176#if DEBUG > C4D_DEBUG_OPCODE
177 g_debug("\\%s17: %.3f, %.3f, %.3f", debug_pad(*level), f1, f2, f3);
178#endif
179 break;
180 case 0x19: /* 12 x float */
181#if DEBUG > C4D_DEBUG_OPCODE
182 g_debug("\\%s19:", debug_pad(*level));
183#endif
184 for(i = 0; i < 4; i ++) {
185 f1 = g3d_stream_read_float_be(stream);
186 f2 = g3d_stream_read_float_be(stream);
187 f3 = g3d_stream_read_float_be(stream);
188 *n_bytes += 12;
189#if DEBUG > C4D_DEBUG_OPCODE
190 g_debug("\\%s %.3f, %.3f, %.3f", debug_pad(*level),
191 f1, f2, f3);
192#endif
193 }
194 break;
195 case 0x80: /* data */
196 x1 = g3d_stream_read_int32_be(stream);
197 *n_bytes += 4 + x1;
198 data = g_new0(guint8, x1);
199 g3d_stream_read(stream, data, x1);
200#if DEBUG > C4D_DEBUG_OPCODE
201 g_debug("\\%s80: %d bytes of data", debug_pad(*level), x1);
202#endif
203 g_free(data);
204 break;
205 case 0x81: /* embedded file */
206 x1 = g3d_stream_read_int32_be(stream);
207 *n_bytes += 4;
208 g3d_stream_skip(stream, x1);
209 *n_bytes += x1;
210#if DEBUG > C4D_DEBUG_OPCODE
211 g_debug("\\%s81: skipped %d bytes", debug_pad(*level), x1);
212#endif
213 break;
214 case 0x82: /* wide-char string */
215 str = c4d_read_wchar(stream, n_bytes);
216#if DEBUG > C4D_DEBUG_OPCODE
217 g_debug("\\%s82: %s", debug_pad(*level), str);
218#endif
219 if(str)
220 g_free(str);
221 break;
222 case 0x83: /* file name */
223 str = c4d_read_wchar(stream, n_bytes);
224#if DEBUG > C4D_DEBUG_OPCODE
225 g_debug("\\%s83: %s", debug_pad(*level), str);
226#endif
227 if(str)
228 g_free(str);
229 break;
230 case 0x84: /* typed content */
231 x1 = g3d_stream_read_int32_be(stream);
232 *n_bytes += 4;
233 x2 = 0;
234#if DEBUG > C4D_DEBUG_OPCODE
235 g_debug("\\%s84: 0x%08x", debug_pad(*level), x1);
236#endif
237 *level += 1;
238 while(x2 < x1) {
239 u1 = g3d_stream_read_int8(stream);
240 x2 ++;
241 if(!c4d_handle_opcode(u1, stream, model, &x2, level))
242 return FALSE;
243 x3 = g3d_stream_read_int32_be(stream);
244 x2 += 4;
245 u1 = g3d_stream_read_int8(stream);
246 x2 += 1;
247 }
248 *level -= 1;
249 *n_bytes += x1;
250 break;
251 case 0x85: /* n * 3 * float */
252 x1 = g3d_stream_read_int32_be(stream);
253 *n_bytes += 4;
254#if DEBUG > C4D_DEBUG_OPCODE
255 g_debug("\\%s85:", debug_pad(*level));
256#endif
257 for(i = 0; i < (x1 / 12); i ++) {
258 f1 = g3d_stream_read_float_be(stream);
259 f2 = g3d_stream_read_float_be(stream);
260 f3 = g3d_stream_read_float_be(stream);
261 *n_bytes += 12;
262#if DEBUG > C4D_DEBUG_OPCODE
263 g_debug("\\%s %.3f, %.3f, %.3f", debug_pad(*level),
264 f1, f2, f3);
265#endif
266 }
267 break;
268 case 0x86: /* n * int16 */
269 x1 = g3d_stream_read_int32_be(stream);
270 *n_bytes += 4;
271#if DEBUG > C4D_DEBUG_OPCODE
272 g_debug("\\%s86:", debug_pad(*level));
273#endif
274 for(i = 0; i < (x1 / 2); i ++) {
275 w1 = g3d_stream_read_int16_be(stream);
276 *n_bytes += 2;
277#if DEBUG > C4D_DEBUG_OPCODE
278 g_debug("\\%s 0x%04x", debug_pad(*level), w1);
279#endif
280 }
281 break;
282 case 0x87: /* n * 3 * int16 */
283 x1 = g3d_stream_read_int32_be(stream);
284 *n_bytes += 4;
285#if DEBUG > C4D_DEBUG_OPCODE
286 g_debug("\\%s87:", debug_pad(*level));
287#endif
288 for(i = 0; i < (x1 / 6); i ++) {
289 w1 = g3d_stream_read_int16_be(stream);
290 w2 = g3d_stream_read_int16_be(stream);
291 w3 = g3d_stream_read_int16_be(stream);
292 *n_bytes += 6;
293#if DEBUG > C4D_DEBUG_OPCODE
294 g_debug("\\%s 0x%04x 0x%04x 0x%04x", debug_pad(*level),
295 w1, w2, w3);
296#endif
297 }
298 break;
299 default:
300 if(g3d_stream_eof(stream))
301 return TRUE;
302#if DEBUG > 0
303 g_debug("%sunknown opcode 0x%02X @ 0x%08x", debug_pad(*level),
304 opcode, (guint32)g3d_stream_tell(stream));
305#endif
306 return FALSE;
307 }
308 return TRUE;
309}
310
311static gboolean c4d_read_v5_cntr(G3DContext *context, G3DStream *stream,
312 G3DModel *model, goffset *n_bytes, guint32 level)
313{
314 guint32 id;
315 goffset size;
316
317 while(!g3d_stream_eof(stream) && (*n_bytes > 0)) {
318 id = g3d_stream_read_int32_be(stream);
319 size = g3d_stream_read_int32_be(stream);
320 *n_bytes -= 8;
321 if(*n_bytes < 0)
322 return FALSE;
323#if DEBUG > 0
324 g_debug("\\%s0x%08x @ 0x%08x (%u bytes)", debug_pad(level), id,
325 (guint32)g3d_stream_tell(stream), (guint32)size);
326#endif
327 *n_bytes -= size;
328 if((id == 0x00001647) || (id == 0x0000139c)) {
329 if(!c4d_read_v5_cntr(context, stream, model, &size, level + 1))
330 return FALSE;
331 } else {
332 g3d_stream_skip(stream, size);
333 }
334 }
335 return TRUE;
336}
337
338static gboolean c4d_load_v5(G3DContext *context, G3DStream *stream,
339 G3DModel *model)
340{
341 goffset n_bytes;
342
343 n_bytes = g3d_stream_read_int32_be(stream); /* file size */
344 g3d_stream_read_int32_be(stream); /* DOK5 */
345 g3d_stream_read_int32_be(stream); /* unknown 1 */
346
347 return c4d_read_v5_cntr(context, stream, model, &n_bytes, 0);
348}
349
350static gboolean c4d_load_v6(G3DContext *context, G3DStream *stream,
351 G3DModel *model)
352{
353 guint8 opcode;
354 gsize n_bytes = 0;
355 guint32 level = 0;
356
357 while(!g3d_stream_eof(stream)) {
358 opcode = g3d_stream_read_int8(stream);
359 if(!c4d_handle_opcode(opcode, stream, model, &n_bytes, &level))
360 return FALSE;
361 }
362 return TRUE;
363}