diff options
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.c | 363 |
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 | |||
29 | static gboolean c4d_load_v5(G3DContext *context, G3DStream *stream, | ||
30 | G3DModel *model); | ||
31 | static gboolean c4d_load_v6(G3DContext *context, G3DStream *stream, | ||
32 | G3DModel *model); | ||
33 | |||
34 | EAPI | ||
35 | gboolean 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 | |||
60 | EAPI | ||
61 | gchar *plugin_description(void) | ||
62 | { | ||
63 | return g_strdup("Cinema4D models."); | ||
64 | } | ||
65 | |||
66 | EAPI | ||
67 | gchar **plugin_extensions(void) | ||
68 | { | ||
69 | return g_strsplit("c4d", ":", 0); | ||
70 | } | ||
71 | |||
72 | /*****************************************************************************/ | ||
73 | |||
74 | static 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 | |||
98 | static 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 | |||
311 | static 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 | |||
338 | static 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 | |||
350 | static 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 | } | ||