diff options
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_leocad/imp_leocad.c')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_leocad/imp_leocad.c | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_leocad/imp_leocad.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_leocad/imp_leocad.c new file mode 100644 index 0000000..590c342 --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_leocad/imp_leocad.c | |||
@@ -0,0 +1,496 @@ | |||
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 <stdlib.h> | ||
24 | #include <string.h> | ||
25 | #include <locale.h> | ||
26 | |||
27 | #include <math.h> | ||
28 | |||
29 | #include <g3d/types.h> | ||
30 | #include <g3d/context.h> | ||
31 | #include <g3d/model.h> | ||
32 | #include <g3d/read.h> | ||
33 | #include <g3d/vector.h> | ||
34 | #include <g3d/matrix.h> | ||
35 | |||
36 | #include "imp_leocad_library.h" | ||
37 | |||
38 | static int leocad_load_lcd(G3DStream *stream, G3DModel *model, | ||
39 | LeoCadLibrary *library, G3DContext *context); | ||
40 | |||
41 | EAPI | ||
42 | gpointer plugin_init(G3DContext *context) | ||
43 | { | ||
44 | LeoCadLibrary *library; | ||
45 | const gchar *libdir; | ||
46 | |||
47 | libdir = g_getenv("LEOCAD_LIB"); | ||
48 | if(libdir == NULL) | ||
49 | libdir = "/usr/local/share/leocad"; | ||
50 | |||
51 | library = leocad_library_load(libdir); | ||
52 | |||
53 | if(library == NULL) | ||
54 | { | ||
55 | #if DEBUG > 1 | ||
56 | g_warning("LeoCAD: failed to load library"); | ||
57 | #endif | ||
58 | return NULL; | ||
59 | } | ||
60 | |||
61 | return library; | ||
62 | } | ||
63 | |||
64 | EAPI | ||
65 | void plugin_cleanup(gpointer user_data) | ||
66 | { | ||
67 | LeoCadLibrary *library; | ||
68 | |||
69 | #if DEBUG > 1 | ||
70 | g_debug("LeoCAD: cleaning up library\n"); | ||
71 | #endif | ||
72 | |||
73 | library = (LeoCadLibrary *)user_data; | ||
74 | |||
75 | if(library) | ||
76 | leocad_library_free(library); | ||
77 | } | ||
78 | |||
79 | EAPI | ||
80 | gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream, | ||
81 | G3DModel *model, gpointer user_data) | ||
82 | { | ||
83 | LeoCadLibrary *library; | ||
84 | |||
85 | library = (LeoCadLibrary *)user_data; | ||
86 | |||
87 | if(library == NULL) | ||
88 | { | ||
89 | g_warning("LeoCAD: library not loaded"); | ||
90 | return FALSE; | ||
91 | } | ||
92 | |||
93 | setlocale(LC_NUMERIC, "C"); | ||
94 | |||
95 | return leocad_load_lcd(stream, model, library, context); | ||
96 | } | ||
97 | |||
98 | EAPI | ||
99 | gchar *plugin_description(G3DContext *context) | ||
100 | { | ||
101 | return g_strdup("LeoCAD models."); | ||
102 | } | ||
103 | |||
104 | EAPI | ||
105 | gchar **plugin_extensions(G3DContext *context) | ||
106 | { | ||
107 | return g_strsplit("lcd", ":", 0); | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * LeoCAD specific stuff | ||
112 | */ | ||
113 | |||
114 | static gboolean leocad_change_key(guint16 ktime, G3DFloat *param, guint8 ktype, | ||
115 | G3DFloat *matrix, G3DFloat *mloc, gboolean *valid_matrix) | ||
116 | { | ||
117 | /* get first frame */ | ||
118 | if(ktime == 1) | ||
119 | { | ||
120 | switch(ktype) | ||
121 | { | ||
122 | case 0x00: /* translation */ | ||
123 | g3d_matrix_identity(mloc); | ||
124 | g3d_matrix_translate(param[0], param[1], param[2], mloc); | ||
125 | g3d_matrix_multiply(matrix, mloc, matrix); | ||
126 | *valid_matrix = TRUE; | ||
127 | break; | ||
128 | |||
129 | case 0x01: /* rotation */ | ||
130 | g3d_matrix_rotate((G3DFloat)param[3] * G_PI / 180.0, | ||
131 | param[0], param[1], param[2], matrix); | ||
132 | g3d_matrix_multiply(mloc, matrix, matrix); | ||
133 | *valid_matrix = TRUE; | ||
134 | break; | ||
135 | |||
136 | default: | ||
137 | break; | ||
138 | } | ||
139 | } | ||
140 | #if DEBUG > 0 | ||
141 | g_debug("LeoCAD: key 0x%02x (%d): %+2.2f %+2.2f %+2.2f %+2.2f", | ||
142 | ktype, ktime, param[0], param[1], param[2], param[3]); | ||
143 | #endif | ||
144 | return TRUE; | ||
145 | } | ||
146 | |||
147 | static gboolean leocad_load_lcd_piece(G3DStream *stream, G3DModel *model, | ||
148 | LeoCadLibrary *library, G3DFloat lcdversion) | ||
149 | { | ||
150 | guint32 i, j, k, nkeys, nobjs; | ||
151 | guint16 ktime; | ||
152 | guint8 pver, over, ktype, color = 0, len8; | ||
153 | gchar name[9]; | ||
154 | G3DFloat param[4], matrix[16], mloc[16]; | ||
155 | G3DFloat offx = 0.0, offy = 0.0, offz = 0.0; | ||
156 | G3DFloat rotx = 0.0, roty = 0.0, rotz = 0.0; | ||
157 | G3DObject *object; | ||
158 | G3DMaterial *mat_change; | ||
159 | G3DFace *face; | ||
160 | GSList *fitem; | ||
161 | gboolean valid_matrix = FALSE; | ||
162 | |||
163 | g3d_matrix_identity(mloc); | ||
164 | g3d_matrix_identity(matrix); | ||
165 | |||
166 | mat_change = leocad_library_get_nth_material(library, 0x10); | ||
167 | |||
168 | if(lcdversion > 0.4) | ||
169 | { | ||
170 | pver = g3d_stream_read_int8(stream); | ||
171 | |||
172 | if(pver >= 9) | ||
173 | { | ||
174 | /* object stuff */ | ||
175 | over = g3d_stream_read_int8(stream); | ||
176 | nobjs = g3d_stream_read_int32_le(stream); | ||
177 | for(i = 0; i < nobjs; i ++) | ||
178 | { | ||
179 | /* time */ | ||
180 | ktime = g3d_stream_read_int16_le(stream); | ||
181 | /* param */ | ||
182 | param[0] = g3d_stream_read_float_le(stream); | ||
183 | param[1] = g3d_stream_read_float_le(stream); | ||
184 | param[2] = g3d_stream_read_float_le(stream); | ||
185 | param[3] = g3d_stream_read_float_le(stream); | ||
186 | /* type */ | ||
187 | ktype = g3d_stream_read_int8(stream); | ||
188 | |||
189 | leocad_change_key(ktime, param, ktype, matrix, mloc, | ||
190 | &valid_matrix); | ||
191 | } | ||
192 | |||
193 | if(over == 1) | ||
194 | { | ||
195 | nobjs = g3d_stream_read_int32_le(stream); | ||
196 | for(i = 0; i < nobjs; i ++) | ||
197 | { | ||
198 | ktime = g3d_stream_read_int16_le(stream); | ||
199 | param[0] = g3d_stream_read_float_le(stream); | ||
200 | param[1] = g3d_stream_read_float_le(stream); | ||
201 | param[2] = g3d_stream_read_float_le(stream); | ||
202 | param[3] = g3d_stream_read_float_le(stream); | ||
203 | ktype = g3d_stream_read_int8(stream); | ||
204 | } | ||
205 | } | ||
206 | } | ||
207 | else /* pver < 9 */ | ||
208 | { | ||
209 | if(pver > 5) | ||
210 | { | ||
211 | nkeys = g3d_stream_read_int32_le(stream); | ||
212 | for(i = 0; i < nkeys; i ++) | ||
213 | { | ||
214 | /* param */ | ||
215 | param[0] = g3d_stream_read_float_le(stream); | ||
216 | param[1] = g3d_stream_read_float_le(stream); | ||
217 | param[2] = g3d_stream_read_float_le(stream); | ||
218 | param[3] = g3d_stream_read_float_le(stream); | ||
219 | |||
220 | /* time */ | ||
221 | ktime = g3d_stream_read_int16_le(stream); | ||
222 | |||
223 | /* type */ | ||
224 | ktype = g3d_stream_read_int8(stream); | ||
225 | |||
226 | leocad_change_key(ktime, param, ktype, matrix, mloc, | ||
227 | &valid_matrix); | ||
228 | |||
229 | } /* keys */ | ||
230 | |||
231 | nkeys = g3d_stream_read_int32_le(stream); | ||
232 | for(i = 0; i < nkeys; i ++) | ||
233 | { | ||
234 | /* param */ | ||
235 | param[0] = g3d_stream_read_float_le(stream); | ||
236 | param[1] = g3d_stream_read_float_le(stream); | ||
237 | param[2] = g3d_stream_read_float_le(stream); | ||
238 | param[3] = g3d_stream_read_float_le(stream); | ||
239 | |||
240 | /* time */ | ||
241 | ktime = g3d_stream_read_int16_le(stream); | ||
242 | |||
243 | /* type */ | ||
244 | ktype = g3d_stream_read_int8(stream); | ||
245 | } | ||
246 | } /* pver > 5 */ | ||
247 | else /* pver <= 5 */ | ||
248 | { | ||
249 | if(pver > 2) | ||
250 | { | ||
251 | nkeys = g3d_stream_read_int8(stream); | ||
252 | for(i = 0; i < nkeys; i ++) | ||
253 | { | ||
254 | if(pver > 3) | ||
255 | { | ||
256 | #if DEBUG > 2 | ||
257 | g_debug("LeoCAD: matrix\n"); | ||
258 | #endif | ||
259 | /* matrix */ | ||
260 | for(j = 0; j < 4; j ++) | ||
261 | for(k = 0; k < 4; k ++) | ||
262 | matrix[j * 4 + k] = | ||
263 | g3d_stream_read_float_le(stream); | ||
264 | |||
265 | valid_matrix = TRUE; | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | /* move: 3 x float */ | ||
270 | offx = g3d_stream_read_float_le(stream); | ||
271 | offy = g3d_stream_read_float_le(stream); | ||
272 | offz = g3d_stream_read_float_le(stream); | ||
273 | |||
274 | /* rotate: 3 x float */ | ||
275 | rotx = g3d_stream_read_float_le(stream); | ||
276 | roty = g3d_stream_read_float_le(stream); | ||
277 | rotz = g3d_stream_read_float_le(stream); | ||
278 | } | ||
279 | |||
280 | /* time */ | ||
281 | ktime = g3d_stream_read_int8(stream); | ||
282 | |||
283 | /* bl? */ | ||
284 | g3d_stream_read_int32_le(stream); | ||
285 | } /* .. nkeys */ | ||
286 | } /* pver > 2 */ | ||
287 | else /* pver <= 2 */ | ||
288 | { | ||
289 | /* move: 3 x float */ | ||
290 | offx = g3d_stream_read_float_le(stream); | ||
291 | offy = g3d_stream_read_float_le(stream); | ||
292 | offz = g3d_stream_read_float_le(stream); | ||
293 | |||
294 | /* rotate: 3 x float */ | ||
295 | rotx = g3d_stream_read_float_le(stream); | ||
296 | roty = g3d_stream_read_float_le(stream); | ||
297 | rotz = g3d_stream_read_float_le(stream); | ||
298 | } | ||
299 | } /* pver <= 5 */ | ||
300 | } /* pver < 9 */ | ||
301 | |||
302 | /* common stuff */ | ||
303 | |||
304 | /* name of piece */ | ||
305 | g3d_stream_read(stream, name, 9); | ||
306 | |||
307 | /* color */ | ||
308 | color = g3d_stream_read_int8(stream); | ||
309 | |||
310 | if(pver < 5) | ||
311 | color = leocad_library_convert_color(color); | ||
312 | |||
313 | #if DEBUG > 0 | ||
314 | g_debug("LeoCAD: [%d]: '%-8s', color 0x%02x", pver, name, color); | ||
315 | #endif | ||
316 | |||
317 | /* step show */ | ||
318 | g3d_stream_read_int8(stream); | ||
319 | |||
320 | /* step hide */ | ||
321 | if(pver > 1) | ||
322 | g3d_stream_read_int8(stream); | ||
323 | |||
324 | if(pver > 5) | ||
325 | { | ||
326 | /* frame show */ | ||
327 | g3d_stream_read_int16_le(stream); | ||
328 | /* frame hide */ | ||
329 | g3d_stream_read_int16_le(stream); | ||
330 | |||
331 | if(pver > 7) { | ||
332 | /* state */ | ||
333 | g3d_stream_read_int8(stream); | ||
334 | |||
335 | len8 = g3d_stream_read_int8(stream); | ||
336 | g3d_stream_skip(stream, len8); | ||
337 | } else { /* pver <= 7 */ | ||
338 | /* hide */ | ||
339 | g3d_stream_read_int32_le(stream); | ||
340 | g3d_stream_skip(stream, 81); | ||
341 | } /* pver <= 7 */ | ||
342 | |||
343 | if(pver > 6) { | ||
344 | /* group pointer ?! */ | ||
345 | g3d_stream_read_int32_le(stream); | ||
346 | } | ||
347 | } /* pver > 5 */ | ||
348 | else /* pver <= 5 */ | ||
349 | { | ||
350 | /* group pointer ?! */ | ||
351 | g3d_stream_read_int8(stream); | ||
352 | |||
353 | /* hide */ | ||
354 | g3d_stream_read_int8(stream); | ||
355 | } | ||
356 | |||
357 | } /* lcdversion > 0.4 */ | ||
358 | |||
359 | object = leocad_library_get_piece(library, name); | ||
360 | if(object == NULL) | ||
361 | { | ||
362 | g_warning("LeoCAD: failed to load piece '%s'", name); | ||
363 | return FALSE; | ||
364 | } | ||
365 | |||
366 | /* matrix */ | ||
367 | if(!valid_matrix) | ||
368 | { | ||
369 | /* translation */ | ||
370 | g3d_matrix_identity(mloc); | ||
371 | g3d_matrix_translate(offx, offy, offz, mloc); | ||
372 | /* rotation */ | ||
373 | rotx = (G3DFloat)(rotx * G_PI) / 180.0; | ||
374 | roty = (G3DFloat)(roty * G_PI) / 180.0; | ||
375 | rotz = (G3DFloat)(rotz * G_PI) / 180.0; | ||
376 | g3d_matrix_identity(matrix); | ||
377 | g3d_matrix_rotate_xyz(rotx, roty, rotz, matrix); | ||
378 | |||
379 | /* combine */ | ||
380 | g3d_matrix_multiply(mloc, matrix, matrix); | ||
381 | } | ||
382 | |||
383 | /*g3d_matrix_dump(matrix);*/ | ||
384 | |||
385 | /* transform vertices */ | ||
386 | for(i = 0; i < object->vertex_count; i ++) | ||
387 | g3d_vector_transform( | ||
388 | &(object->vertex_data[i * 3 + 0]), | ||
389 | &(object->vertex_data[i * 3 + 1]), | ||
390 | &(object->vertex_data[i * 3 + 2]), | ||
391 | matrix); | ||
392 | |||
393 | /* change color */ | ||
394 | fitem = object->faces; | ||
395 | while(fitem) | ||
396 | { | ||
397 | face = (G3DFace *)fitem->data; | ||
398 | if(face->material == mat_change) | ||
399 | { | ||
400 | face->material = leocad_library_get_nth_material(library, color); | ||
401 | } | ||
402 | |||
403 | if(face->material == NULL) | ||
404 | { | ||
405 | face->material = leocad_library_get_nth_material(library, 0); | ||
406 | } | ||
407 | |||
408 | fitem = fitem->next; | ||
409 | } | ||
410 | |||
411 | /* add to model object list */ | ||
412 | model->objects = g_slist_append(model->objects, object); | ||
413 | |||
414 | return TRUE; | ||
415 | } | ||
416 | |||
417 | static gboolean leocad_load_lcd(G3DStream *stream, G3DModel *model, | ||
418 | LeoCadLibrary *library, G3DContext *context) | ||
419 | { | ||
420 | gchar magic[32]; | ||
421 | float version; | ||
422 | guint32 i, count; | ||
423 | G3DFloat r, g, b; | ||
424 | G3DMatrix rmatrix[16]; | ||
425 | |||
426 | g3d_stream_read(stream, magic, 32); | ||
427 | if(strncmp(magic, "LeoCAD", 6) != 0) { | ||
428 | g_warning("LeoCAD: '%s' is not a valid LeoCAD project file", | ||
429 | stream->uri); | ||
430 | return FALSE; | ||
431 | } | ||
432 | |||
433 | sscanf(&magic[7], "%f", &version); | ||
434 | |||
435 | if(version > 0.4) { | ||
436 | #if DEBUG > 0 | ||
437 | g_debug("LeoCAD: file version %.1f, getting next float", version); | ||
438 | #endif | ||
439 | version = g3d_stream_read_float_le(stream); | ||
440 | } | ||
441 | |||
442 | #if DEBUG > 0 | ||
443 | g_debug("LeoCAD: file version %.1f", version); | ||
444 | #endif | ||
445 | |||
446 | r = g3d_stream_read_int8(stream) / 255.0; | ||
447 | g = g3d_stream_read_int8(stream) / 255.0; | ||
448 | b = g3d_stream_read_int8(stream) / 255.0; | ||
449 | /* background color */ | ||
450 | g3d_context_set_bgcolor(context, r, g, b, 1.0); | ||
451 | g3d_stream_read_int8(stream); | ||
452 | |||
453 | /* view */ | ||
454 | if(version < 0.6) { | ||
455 | /* eye: 3 x double */ | ||
456 | g3d_stream_skip(stream, 24); | ||
457 | |||
458 | /* target: 3 x double */ | ||
459 | g3d_stream_skip(stream, 24); | ||
460 | } | ||
461 | |||
462 | /* angle snap */ | ||
463 | g3d_stream_read_int32_le(stream); | ||
464 | /* snap */ | ||
465 | g3d_stream_read_int32_le(stream); | ||
466 | /* line width */ | ||
467 | g3d_stream_read_float_le(stream); | ||
468 | /* detail */ | ||
469 | g3d_stream_read_int32_le(stream); | ||
470 | /* cur group */ | ||
471 | g3d_stream_read_int32_le(stream); | ||
472 | /* cur color */ | ||
473 | g3d_stream_read_int32_le(stream); | ||
474 | /* action */ | ||
475 | g3d_stream_read_int32_le(stream); | ||
476 | /* cur step */ | ||
477 | g3d_stream_read_int32_le(stream); | ||
478 | |||
479 | if(version > 0.8) { | ||
480 | /* scene */ | ||
481 | g3d_stream_read_int32_le(stream); | ||
482 | } | ||
483 | |||
484 | /* piece count */ | ||
485 | count = g3d_stream_read_int32_le(stream); | ||
486 | for(i = 0; i < count; i ++) { | ||
487 | /* load piece */ | ||
488 | leocad_load_lcd_piece(stream, model, library, version); | ||
489 | } | ||
490 | |||
491 | g3d_matrix_identity(rmatrix); | ||
492 | g3d_matrix_rotate_xyz(G_PI * -90.0 / 180, 0.0, 0.0, rmatrix); | ||
493 | g3d_model_transform(model, rmatrix); | ||
494 | |||
495 | return TRUE; | ||
496 | } | ||