aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_leocad/imp_leocad_library.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_leocad/imp_leocad_library.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_leocad/imp_leocad_library.c633
1 files changed, 633 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_leocad/imp_leocad_library.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_leocad/imp_leocad_library.c
new file mode 100644
index 0000000..7336336
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_leocad/imp_leocad_library.c
@@ -0,0 +1,633 @@
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 <g3d/config.h>
24
25#include <string.h>
26
27#include <glib.h>
28
29#include <g3d/types.h>
30#include <g3d/object.h>
31#include <g3d/material.h>
32#include <g3d/stream.h>
33#include <g3d/primitive.h>
34#include <g3d/matrix.h>
35
36#include "imp_leocad_library.h"
37
38#define LEOCAD_FLAG_PIECE_COUNT 0x01
39#define LEOCAD_FLAG_PIECE_LONGDATA 0x02
40#define LEOCAD_FLAG_PIECE_CCW 0x04
41#define LEOCAD_FLAG_PIECE_SMALL 0x10
42#define LEOCAD_FLAG_PIECE_MEDIUM 0x20
43#define LEOCAD_FLAG_LONGDATA_RUNTIME 0x40
44#define LEOCAD_FLAG_PIECE_RENAMED 0x80
45
46#define LEOCAD_TYPE_MESH 0x01
47#define LEOCAD_TYPE_STUD 0x02
48#define LEOCAD_TYPE_STUD2 0x03
49#define LEOCAD_TYPE_STUD3 0x04
50#define LEOCAD_TYPE_STUD4 0x05
51
52static gboolean leocad_library_read_pieces_idx(LeoCadLibrary *library,
53 G3DStream *idx);
54static gboolean leocad_create_materials(LeoCadLibrary *library);
55
56struct LeoCadConnection {
57 guint8 type;
58 G3DFloat center[3];
59 G3DFloat normal[3];
60};
61
62LeoCadLibrary *leocad_library_load(const gchar *libdir)
63{
64 LeoCadLibrary *library;
65 gchar filename[1025];
66 G3DStream *idx, *bin;
67
68 library = g_new0(LeoCadLibrary, 1);
69
70 g_snprintf(filename, 1024, "%s/%s", libdir, "pieces.idx");
71 idx = g3d_stream_open_file(filename, "rb");
72 if(idx == NULL) {
73#if DEBUG > 0
74 g_warning("LeoCAD: failed to read '%s'", filename);
75#endif
76 g_free(library);
77 return NULL;
78 }
79
80 g_snprintf(filename, 1024, "%s/%s", libdir, "pieces.bin");
81 bin = g3d_stream_open_file(filename, "rb");
82 if(bin == NULL) {
83#if DEBUG > 0
84 g_debug("LeoCAD: failed to read '%s'", filename);
85#endif
86 g3d_stream_close(idx);
87 g_free(library);
88 return NULL;
89 }
90
91 library->pieces = g_hash_table_new(g_str_hash, g_str_equal);
92 library->pieces_bin = bin;
93
94 leocad_library_read_pieces_idx(library, idx);
95 g3d_stream_close(idx);
96
97 leocad_create_materials(library);
98
99 return library;
100}
101
102static gboolean leocad_free_piece_cb(gpointer key, gpointer value,
103 gpointer user_data)
104{
105 LeoCadPiece *piece;
106
107 piece = (LeoCadPiece *)value;
108
109#if DEBUG > 3
110 g_debug("D: freeing piece %s", piece->name);
111#endif
112
113 if(piece->name) g_free(piece->name);
114 if(piece->description) g_free(piece->description);
115 if(piece->moved_to) g_free(piece->moved_to);
116
117 if(!(piece->flags & LEOCAD_FLAG_PIECE_RENAMED))
118 if(piece->object) g3d_object_free(piece->object);
119
120 g_free(piece);
121
122 return TRUE;
123}
124
125void leocad_library_free(LeoCadLibrary *library)
126{
127 GSList *mlist;
128 G3DMaterial *material;
129
130 /* remove materials */
131 mlist = library->materials;
132 while(mlist)
133 {
134 material = (G3DMaterial *)mlist->data;
135 mlist = g_slist_remove(mlist, material);
136 g3d_material_free(material);
137 }
138
139 /* remove pieces */
140 g_hash_table_foreach_remove(library->pieces, leocad_free_piece_cb, NULL);
141 g_hash_table_destroy(library->pieces);
142
143 /* free library */
144 g_free(library);
145}
146
147static G3DFloat leocad_read_scaled16(G3DStream *stream, G3DFloat scale)
148{
149 gint16 x;
150
151 x = g3d_stream_read_int16_le(stream);
152
153 return (G3DFloat)(x / scale);
154}
155
156static gboolean leocad_create_materials(LeoCadLibrary *library)
157{
158 const guint8 colors[] = {
159 166, 25, 25, 255, /* 0 - Red */
160 255, 127, 51, 255, /* 1 - Orange */
161 25, 102, 25, 255, /* 2 - Green */
162 76, 153, 76, 255, /* 3 - Light Green */
163 0, 51, 178, 255, /* 4 - Blue */
164 51, 102, 229, 255, /* 5 - Light Blue */
165 204, 204, 0, 255, /* 6 - Yellow */
166 242, 242, 242, 255, /* 7 - White */
167 76, 76, 76, 255, /* 8 - Dark Gray */
168 25, 25, 25, 255, /* 9 - Black */
169 102, 51, 51, 255, /* 10 - Brown */
170 178, 76, 153, 255, /* 11 - Pink */
171 153, 51, 153, 255, /* 12 - Purple */
172 229, 178, 51, 255, /* 13 - Gold */
173 153, 25, 25, 153, /* 14 - Clear Red */
174 255, 153, 76, 153, /* 15 - Clear Orange */
175 25, 102, 25, 153, /* 16 - Clear Green */
176 153, 178, 76, 153, /* 17 - Clear Light Green */
177 0, 0, 127, 153, /* 18 - Clear Blue */
178 51, 102, 229, 153, /* 19 - Clear Light Blue */
179 229, 229, 0, 153, /* 20 - Clear Yellow */
180 229, 229, 229, 153, /* 21 - Clear White */
181 127, 127, 127, 255, /* 22 - Light Gray */
182 204, 204, 178, 255, /* 23 - Tan */
183 153, 102, 102, 255, /* 24 - Light Brown */
184 229, 178, 229, 255, /* 25 - Light Pink */
185 25, 178, 204, 255, /* 26 - Turquoise */
186 204, 204, 204, 255, /* 27 - Silver */
187 51, 51, 51, 255, /* 28 - Edges */
188 229, 76, 102, 255, /* 29 - Selected */
189 102, 76, 229, 255}; /* 30 - Focused */
190
191 G3DMaterial *material;
192 guint32 i;
193
194 for(i = 0; i < 31; i ++)
195 {
196 material = g3d_material_new();
197 material->r = (G3DFloat)colors[i * 4 + 0] / 255.0;
198 material->g = (G3DFloat)colors[i * 4 + 1] / 255.0;
199 material->b = (G3DFloat)colors[i * 4 + 2] / 255.0;
200 material->a = (G3DFloat)colors[i * 4 + 3] / 255.0;
201
202 library->materials = g_slist_append(library->materials, material);
203 }
204
205 return TRUE;
206}
207
208guint8 leocad_library_convert_color(guint8 n)
209{
210 static guint8 converted_colors[20] =
211 { 0,2,4,9,7,6,22,8,10,11,14,16,18,9,21,20,22,8,10,11 };
212
213 if(n >= 20)
214 return 0;
215
216 return converted_colors[n];
217}
218
219G3DMaterial *leocad_library_get_nth_material(LeoCadLibrary *library, guint8 n)
220{
221 return g_slist_nth_data(library->materials, n);
222}
223
224G3DObject *leocad_library_get_piece(LeoCadLibrary *library, const gchar *name)
225{
226 LeoCadPiece *piece;
227 G3DObject *stud;
228 G3DFace *face;
229 guint32 i, j, k, nconn, ngrp, ntex, ngrpconn, ncol, nx, color = 0;
230 guint16 grp_type;
231 G3DFloat scale = 100.0;
232 G3DFloat matrix[16];
233 G3DStream *bin;
234 struct LeoCadConnection *connections;
235
236 piece = g_hash_table_lookup(library->pieces, name);
237
238 if(piece == NULL)
239 {
240 g_warning("LeoCAD: failed to load piece '%s'", name);
241 return NULL;
242 }
243
244 bin = library->pieces_bin;
245
246 if(piece->object == NULL)
247 {
248 piece->object = g_new0(G3DObject, 1);
249 piece->object->name = g_strdup(piece->description);
250
251 g3d_stream_seek(bin, piece->offset_bin, G_SEEK_SET);
252 piece->object->vertex_count = g3d_stream_read_int32_le(bin);
253 piece->object->vertex_data = g_new0(G3DFloat,
254 piece->object->vertex_count * 3);
255
256 if(piece->flags & LEOCAD_FLAG_PIECE_SMALL)
257 scale = 10000.0;
258 else if(piece->flags & LEOCAD_FLAG_PIECE_MEDIUM)
259 scale = 1000.0;
260
261 for(i = 0; i < piece->object->vertex_count; i ++)
262 {
263 piece->object->vertex_data[i * 3 + 0] =
264 leocad_read_scaled16(bin, scale);
265 piece->object->vertex_data[i * 3 + 1] =
266 leocad_read_scaled16(bin, scale);
267 piece->object->vertex_data[i * 3 + 2] =
268 leocad_read_scaled16(bin, scale);
269 }
270#if DEBUG > 1
271 g_debug("LeoCAD: piece '%s': flags 0x%02X", name, piece->flags);
272#endif
273
274#if DEBUG > 1
275 g_debug("LeoCAD: piece '%s': %d vertices",
276 name, piece->object->vertex_count);
277#endif
278
279 /* connections */
280 nconn = g3d_stream_read_int16_le(bin);
281#if DEBUG > 1
282 g_debug("LeoCAD: piece '%s': %d connections", name, nconn);
283#endif
284 connections = g_new0(struct LeoCadConnection, nconn);
285 for(i = 0; i < nconn; i ++)
286 {
287 connections[i].type = g3d_stream_read_int8(bin);
288
289 /* center */
290 connections[i].center[0] = leocad_read_scaled16(bin, scale);
291 connections[i].center[1] = leocad_read_scaled16(bin, scale);
292 connections[i].center[2] = leocad_read_scaled16(bin, scale);
293
294 /* normal */
295 connections[i].normal[0] = g3d_stream_read_int16_le(bin) / (1 << 14);
296 connections[i].normal[1] = g3d_stream_read_int16_le(bin) / (1 << 14);
297 connections[i].normal[2] = g3d_stream_read_int16_le(bin) / (1 << 14);
298 }
299
300 /* textures */
301 ntex = g3d_stream_read_int8(bin);
302#if DEBUG > 0
303 if(ntex > 0)
304 g_debug("LeoCAD: piece '%s': %d textures", name, ntex);
305#endif
306 for(i = 0; i < ntex; i ++)
307 {
308 /* TODO: */
309 }
310
311 /* groups */
312 ngrp = g3d_stream_read_int16_le(bin);
313#if DEBUG > 1
314 g_debug("LeoCAD: piece '%s': %d groups @ 0x%08lx",
315 name, ngrp, ftell(bin));
316#endif
317 for(i = 0; i < ngrp; i ++)
318 {
319 /* group connections */
320 ngrpconn = g3d_stream_read_int8(bin);
321 for(j = 0; j < ngrpconn; j ++)
322 {
323 g3d_stream_read_int16_le(bin);
324 }
325
326#if 0
327 while(1)
328 {
329#endif
330 grp_type = g3d_stream_read_int8(bin);
331 if(grp_type == 0)
332 {
333 break;
334 }
335#if DEBUG > 1
336 g_debug("LeoCAD: piece '%s': grp %d: type 0x%02x @ 0x%08lx",
337 name, i, grp_type, ftell(bin));
338#endif
339
340 switch(grp_type)
341 {
342 case LEOCAD_TYPE_MESH:
343 ncol = g3d_stream_read_int16_le(bin);
344#if DEBUG > 1
345 g_debug("LeoCAD: piece '%s': grp %d: %d colors "
346 "(@ 0x%08lx)", name, i, ncol, ftell(bin));
347#endif
348 for(j = 0; j < ncol; j ++)
349 {
350 /* color code */
351 color = g3d_stream_read_int16_le(bin);
352#if DEBUG > 1
353 g_debug("LeoCAD: piece '%s': grp %d: color 0x%04x",
354 name, i, color);
355#endif
356 /* quads? */
357 nx = g3d_stream_read_int16_le(bin);
358 for(k = 0; k < nx / 4; k ++)
359 {
360 face = g_new0(G3DFace, 1);
361 face->material =
362 g_slist_nth_data(
363 library->materials, color);
364 face->vertex_count = 4;
365 face->vertex_indices = g_new0(guint32, 4);
366
367 face->vertex_indices[0] =
368 g3d_stream_read_int16_le(bin);
369 face->vertex_indices[1] =
370 g3d_stream_read_int16_le(bin);
371 face->vertex_indices[2] =
372 g3d_stream_read_int16_le(bin);
373 face->vertex_indices[3] =
374 g3d_stream_read_int16_le(bin);
375
376 piece->object->faces = g_slist_prepend(
377 piece->object->faces, face);
378 }
379#if DEBUG > 1
380 g_debug("LeoCAD: piece '%s': grp %d: "
381 "quads: %d bytes", name, i, nx * 2);
382#endif
383 nx = g3d_stream_read_int16_le(bin);
384 for(k = 0; k < nx / 3; k ++)
385 {
386 face = g_new0(G3DFace, 1);
387 face->material =
388 g_slist_nth_data(
389 library->materials, color);
390 face->vertex_count = 3;
391 face->vertex_indices = g_new0(guint32, 3);
392
393 face->vertex_indices[0] =
394 g3d_stream_read_int16_le(bin);
395 face->vertex_indices[1] =
396 g3d_stream_read_int16_le(bin);
397 face->vertex_indices[2] =
398 g3d_stream_read_int16_le(bin);
399
400 piece->object->faces = g_slist_prepend(
401 piece->object->faces, face);
402 }
403
404#if DEBUG > 1
405 g_debug("LeoCAD: piece '%s': grp %d: "
406 "triangles: %d bytes",
407 name, i, nx * 2);
408#endif
409 nx = g3d_stream_read_int16_le(bin);
410#if DEBUG > 1
411 g_debug("LeoCAD: piece '%s': grp %d: "
412 "skipping %d bytes @ 0x%08lx",
413 name, i, nx * 2, ftell(bin));
414#endif
415 g3d_stream_skip(bin, nx * 2);
416 }
417 break;
418
419 case LEOCAD_TYPE_STUD:
420 case LEOCAD_TYPE_STUD2:
421 case LEOCAD_TYPE_STUD3:
422 case LEOCAD_TYPE_STUD4:
423 stud = NULL;
424 color = g3d_stream_read_int8(bin);
425#if DEBUG > 0
426 g_debug("LeoCAD: piece '%s': stud 0x%02x",
427 name, grp_type);
428#endif
429 if(grp_type == LEOCAD_TYPE_STUD4)
430 stud = g3d_primitive_tube(
431 0.24, /* inner radius */
432 0.32, /* outer radius */
433 0.16, /* height */
434 16, /* sides */
435 TRUE, FALSE, /* top, bottom */
436 leocad_library_get_nth_material(
437 library, color));
438
439 g3d_matrix_identity(matrix);
440 for(j = 0; j < 12; j ++)
441#if 1
442 matrix[(j / 3) * 4 + (j % 3)] =
443 g3d_stream_read_float_le(bin);
444#else
445 matrix[j] = g3d_stream_read_float_le(bin);
446#endif
447 /* g3d_matrix_dump(matrix); */
448
449 if(stud && piece->object)
450 {
451 g3d_object_transform(stud, matrix);
452 g3d_object_merge(piece->object, stud);
453 stud = NULL;
454 }
455
456 break;
457
458 default:
459#if DEBUG > 1
460 g_debug(
461 "LeoCAD: piece '%s': unhandled group type 0x%02x "
462 "@ 0x%08lx",
463 name, grp_type, ftell(bin));
464#endif
465 break;
466 } /* grp_type */
467#if 0
468 } /* grp_type != 0 */
469#endif
470 g3d_stream_read_int8(bin);
471 } /* ngrp */
472
473 /* generate studs */
474 for(i = 0; i < nconn; i ++)
475 {
476#if DEBUG > 4
477 g_debug("LeoCAD: connection %d: type 0x%02x",
478 i, connections[i].type);
479#endif
480
481 switch(connections[i].type)
482 {
483 case 0:
484 stud = g3d_primitive_cylinder(
485 0.24, /* radius */
486 0.16, /* height */
487 16, /* sides */
488 TRUE, FALSE, /* top, bottom */
489 leocad_library_get_nth_material(library, color));
490 break;
491
492 case 2:
493 stud = g3d_primitive_tube(
494 0.24, /* inner radius */
495 0.32, /* outer radius */
496 0.16, /* height */
497 16, /* sides */
498 FALSE, TRUE, /* top, bottom */
499 leocad_library_get_nth_material(library, color));
500 break;
501
502 default:
503 stud = NULL;
504 break;
505 }
506
507 if(stud)
508 {
509#if DEBUG > 5
510 g_debug("LeoCAD: stud");
511#endif
512 /* transform stud */
513 for(j = 0; j < stud->vertex_count; j ++)
514 {
515#if 0
516 g3d_vector_transform(
517 &(stud->vertices[j * 3 + 0]),
518 &(stud->vertices[j * 3 + 1]),
519 &(stud->vertices[j * 3 + 2]),
520 matrix);
521#endif
522
523 stud->vertex_data[j * 3 + 0] += connections[i].center[0];
524 stud->vertex_data[j * 3 + 1] += connections[i].center[1];
525 stud->vertex_data[j * 3 + 2] += connections[i].center[2];
526 }
527
528 /* merge stud */
529 g3d_object_merge(piece->object, stud);
530 } /* stud */
531 } /* nconn */
532
533 if(connections)
534 g_free(connections);
535 }
536
537 return g3d_object_duplicate(piece->object);
538}
539
540static gboolean leocad_library_read_piece(LeoCadLibrary *library,
541 G3DStream *idx)
542{
543 gchar buffer[128];
544 guint32 i;
545 LeoCadPiece *piece;
546
547 piece = g_new0(LeoCadPiece, 1);
548
549 g3d_stream_read(idx, buffer, 8);
550 buffer[8] = '\0';
551 piece->name = g_strdup(buffer);
552
553 g3d_stream_read(idx, buffer, 64);
554 buffer[64] = '\0';
555 piece->description = g_strdup(buffer);
556
557 for(i = 0; i < 6; i ++)
558 piece->bounding_box[i] = g3d_stream_read_int16_le(idx);
559
560 piece->flags = g3d_stream_read_int8(idx);
561 piece->default_group = g3d_stream_read_int32_le(idx);
562 piece->offset_bin = g3d_stream_read_int32_le(idx);
563 piece->info_size = g3d_stream_read_int32_le(idx);
564
565#if DEBUG > 1
566 g_debug("LeoCAD: %-8s: @ 0x%08x, %s",
567 piece->name, piece->offset_bin, piece->description);
568#endif
569
570 g_hash_table_insert(library->pieces, piece->name, piece);
571
572 return TRUE;
573}
574
575static gboolean leocad_library_read_pieces_idx(LeoCadLibrary *library,
576 G3DStream *idx)
577{
578 gchar magic[32], nameold[9], namenew[9];
579 guint8 version, lastupdate;
580 guint32 nmoved, nbinsize, npieces, i;
581 LeoCadPiece *piece, *newpiece;
582
583 g3d_stream_read(idx, magic, 32);
584 if(strncmp(magic, "LeoCAD piece library index file", 31) != 0)
585 {
586 g_debug("LeoCAD: pieces.idx: wrong magic");
587 return FALSE;
588 }
589
590 version = g3d_stream_read_int8(idx);
591 lastupdate = g3d_stream_read_int8(idx);
592
593 g3d_stream_seek(idx, -8, G_SEEK_END);
594 nmoved = g3d_stream_read_int16_le(idx);
595 nbinsize = g3d_stream_read_int32_le(idx);
596 npieces = g3d_stream_read_int16_le(idx);
597
598 g3d_stream_seek(idx, 34, G_SEEK_SET);
599
600#if DEBUG > 0
601 g_debug("LeoCAD: pieces.idx: version %d, last update %d",
602 version, lastupdate);
603 g_debug("LeoCAD: pieces.idx: %d pieces, %d moves, pieces.bin %d bytes",
604 npieces, nmoved, nbinsize);
605#endif
606
607 for(i = 0; i < npieces; i ++)
608 leocad_library_read_piece(library, idx);
609
610 for(i = 0; i < nmoved; i ++) {
611 memset(nameold, 0, 9);
612 memset(namenew, 0, 9);
613
614 g3d_stream_read(idx, nameold, 8);
615 g3d_stream_read(idx, namenew, 8);
616
617 piece = g_hash_table_lookup(library->pieces, namenew);
618 if(piece) {
619 newpiece = g_new0(LeoCadPiece, 1);
620 memcpy(newpiece, piece, sizeof(LeoCadPiece));
621 newpiece->name = g_strdup(nameold);
622 newpiece->description = g_strdup(piece->description);
623 newpiece->moved_to = g_strdup(namenew);
624 newpiece->object = piece->object;
625 newpiece->flags |= LEOCAD_FLAG_PIECE_RENAMED;
626
627 g_hash_table_insert(library->pieces, piece->name, newpiece);
628 }
629 }
630
631 return TRUE;
632}
633