diff options
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ldraw/imp_ldraw_part.c')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ldraw/imp_ldraw_part.c | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ldraw/imp_ldraw_part.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ldraw/imp_ldraw_part.c new file mode 100644 index 0000000..9f7f608 --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_ldraw/imp_ldraw_part.c | |||
@@ -0,0 +1,291 @@ | |||
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 | #include <stdio.h> | ||
23 | #include <string.h> | ||
24 | |||
25 | #include <g3d/types.h> | ||
26 | #include <g3d/context.h> | ||
27 | #include <g3d/stream.h> | ||
28 | #include <g3d/material.h> | ||
29 | #include <g3d/matrix.h> | ||
30 | #include <g3d/object.h> | ||
31 | |||
32 | #include "imp_ldraw_types.h" | ||
33 | #include "imp_ldraw_part.h" | ||
34 | #include "imp_ldraw_library.h" | ||
35 | #include "imp_ldraw_color.h" | ||
36 | #include "imp_ldraw_misc.h" | ||
37 | |||
38 | static gboolean ldraw_part_parse_meta(G3DObject *object, gchar *buffer) | ||
39 | { | ||
40 | if(object->name == NULL) { | ||
41 | object->name = g_strdup(buffer); | ||
42 | return TRUE; | ||
43 | } | ||
44 | #if DEBUG > 2 | ||
45 | g_debug("META: %s", buffer); | ||
46 | #endif | ||
47 | return TRUE; | ||
48 | } | ||
49 | |||
50 | static void ldraw_part_replace_material(G3DObject *object, | ||
51 | G3DMaterial *material) | ||
52 | { | ||
53 | GSList *item; | ||
54 | G3DObject *sub; | ||
55 | G3DFace *face; | ||
56 | |||
57 | for(item = object->faces; item != NULL; item = item->next) { | ||
58 | face = item->data; | ||
59 | if(face->material == NULL) | ||
60 | face->material = material; | ||
61 | } | ||
62 | for(item = object->objects; item != NULL; item = item->next) { | ||
63 | sub = item->data; | ||
64 | ldraw_part_replace_material(sub, material); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | static gboolean ldraw_part_parse_ref(G3DObject *object, gchar *buffer, | ||
69 | LDrawLibrary *lib) | ||
70 | { | ||
71 | G3DObject *subobj; | ||
72 | G3DMaterial *material; | ||
73 | G3DFloat m[16], x, y, z; | ||
74 | guint32 colid; | ||
75 | gchar fname[256], *strp; | ||
76 | |||
77 | g3d_matrix_identity(m); | ||
78 | memset(fname, 0, 256); | ||
79 | |||
80 | if(sscanf(buffer, "%u " | ||
81 | G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " | ||
82 | G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " | ||
83 | G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " %255s", | ||
84 | &colid, &x, &y, &z, | ||
85 | m + 0 * 4 + 0, m + 1 * 4 + 0, m + 2 * 4 + 0, | ||
86 | m + 0 * 4 + 1, m + 1 * 4 + 1, m + 2 * 4 + 1, | ||
87 | m + 0 * 4 + 2, m + 1 * 4 + 2, m + 2 * 4 + 2, | ||
88 | fname) == 14) { | ||
89 | |||
90 | strp = path_sep(fname); | ||
91 | if(strp != NULL) | ||
92 | strp[0] = G_DIR_SEPARATOR; | ||
93 | |||
94 | subobj = ldraw_part_from_file(lib, fname); | ||
95 | if(!subobj) | ||
96 | subobj = ldraw_library_lookup(lib, fname); | ||
97 | if(subobj != NULL) { | ||
98 | g3d_object_transform(subobj, m); | ||
99 | g3d_matrix_identity(m); | ||
100 | g3d_matrix_translate(x, y, z, m); | ||
101 | g3d_object_transform(subobj, m); | ||
102 | if(colid != 16) { | ||
103 | material = ldraw_color_lookup(lib, colid); | ||
104 | ldraw_part_replace_material(subobj, material); | ||
105 | } | ||
106 | object->objects = g_slist_append(object->objects, subobj); | ||
107 | return TRUE; | ||
108 | } | ||
109 | } | ||
110 | #if DEBUG > 1 | ||
111 | g_warning("LDraw: failed to parse/process reference: %s", buffer); | ||
112 | #endif | ||
113 | return FALSE; | ||
114 | } | ||
115 | |||
116 | static gboolean ldraw_part_parse_tri(G3DObject *object, gchar *buffer, | ||
117 | LDrawLibrary *lib) | ||
118 | { | ||
119 | guint32 off, colid; | ||
120 | G3DFace *face; | ||
121 | |||
122 | off = object->vertex_count; | ||
123 | object->vertex_count += 3; | ||
124 | object->vertex_data = g_realloc(object->vertex_data, | ||
125 | object->vertex_count * 3 * sizeof(G3DFloat)); | ||
126 | if(sscanf(buffer, "%u " | ||
127 | G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " | ||
128 | G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " | ||
129 | G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT, | ||
130 | &colid, | ||
131 | object->vertex_data + (off + 0) * 3 + 0, | ||
132 | object->vertex_data + (off + 0) * 3 + 1, | ||
133 | object->vertex_data + (off + 0) * 3 + 2, | ||
134 | object->vertex_data + (off + 1) * 3 + 0, | ||
135 | object->vertex_data + (off + 1) * 3 + 1, | ||
136 | object->vertex_data + (off + 1) * 3 + 2, | ||
137 | object->vertex_data + (off + 2) * 3 + 0, | ||
138 | object->vertex_data + (off + 2) * 3 + 1, | ||
139 | object->vertex_data + (off + 2) * 3 + 2) == 10) { | ||
140 | |||
141 | face = g_new0(G3DFace, 1); | ||
142 | face->material = ldraw_color_lookup(lib, colid); | ||
143 | face->vertex_count = 3; | ||
144 | face->vertex_indices = g_new0(guint32, 3); | ||
145 | face->vertex_indices[0] = off + 0; | ||
146 | face->vertex_indices[1] = off + 1; | ||
147 | face->vertex_indices[2] = off + 2; | ||
148 | object->faces = g_slist_append(object->faces, face); | ||
149 | return TRUE; | ||
150 | } | ||
151 | return FALSE; | ||
152 | } | ||
153 | |||
154 | static gboolean ldraw_part_parse_quad(G3DObject *object, gchar *buffer, | ||
155 | LDrawLibrary *lib) | ||
156 | { | ||
157 | guint32 off, colid; | ||
158 | G3DFace *face; | ||
159 | |||
160 | off = object->vertex_count; | ||
161 | object->vertex_count += 4; | ||
162 | object->vertex_data = g_realloc(object->vertex_data, | ||
163 | object->vertex_count * 3 * sizeof(G3DFloat)); | ||
164 | if(sscanf(buffer, "%u " | ||
165 | G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " | ||
166 | G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " | ||
167 | G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT " " G3D_SCANF_FLOAT, | ||
168 | &colid, | ||
169 | object->vertex_data + (off + 0) * 3 + 0, | ||
170 | object->vertex_data + (off + 0) * 3 + 1, | ||
171 | object->vertex_data + (off + 0) * 3 + 2, | ||
172 | object->vertex_data + (off + 1) * 3 + 0, | ||
173 | object->vertex_data + (off + 1) * 3 + 1, | ||
174 | object->vertex_data + (off + 1) * 3 + 2, | ||
175 | object->vertex_data + (off + 2) * 3 + 0, | ||
176 | object->vertex_data + (off + 2) * 3 + 1, | ||
177 | object->vertex_data + (off + 2) * 3 + 2, | ||
178 | object->vertex_data + (off + 3) * 3 + 0, | ||
179 | object->vertex_data + (off + 3) * 3 + 1, | ||
180 | object->vertex_data + (off + 3) * 3 + 2) == 13) { | ||
181 | |||
182 | face = g_new0(G3DFace, 1); | ||
183 | face->material = ldraw_color_lookup(lib, colid); | ||
184 | face->vertex_count = 4; | ||
185 | face->vertex_indices = g_new0(guint32, 4); | ||
186 | face->vertex_indices[0] = off + 0; | ||
187 | face->vertex_indices[1] = off + 1; | ||
188 | face->vertex_indices[2] = off + 2; | ||
189 | face->vertex_indices[3] = off + 3; | ||
190 | object->faces = g_slist_append(object->faces, face); | ||
191 | return TRUE; | ||
192 | } | ||
193 | return FALSE; | ||
194 | } | ||
195 | |||
196 | static inline G3DObject *ldraw_part_open_file(LDrawLibrary *lib, | ||
197 | const gchar *filename) | ||
198 | { | ||
199 | LDrawPart *part; | ||
200 | |||
201 | part = g_new0(LDrawPart, 1); | ||
202 | part->name = g_strdup(filename); | ||
203 | part->stream = g3d_stream_open_file(filename, "r"); | ||
204 | if(part->stream == NULL) { | ||
205 | g_free(part); | ||
206 | return NULL; | ||
207 | } | ||
208 | part->object = ldraw_part_get_object(part, lib); | ||
209 | g3d_stream_close(part->stream); | ||
210 | part->stream = NULL; | ||
211 | |||
212 | ldraw_library_insert(lib, part->name, part); | ||
213 | |||
214 | return part->object; | ||
215 | } | ||
216 | |||
217 | G3DObject *ldraw_part_from_file(LDrawLibrary *lib, const gchar *filename) | ||
218 | { | ||
219 | G3DObject *object; | ||
220 | gchar *path; | ||
221 | |||
222 | if(g_file_test(filename, G_FILE_TEST_EXISTS)) | ||
223 | return ldraw_part_open_file(lib, filename); | ||
224 | path = g_ascii_strdown(filename, -1); | ||
225 | if(g_file_test(path, G_FILE_TEST_EXISTS)) { | ||
226 | object = ldraw_part_open_file(lib, path); | ||
227 | g_free(path); | ||
228 | return object; | ||
229 | } | ||
230 | g_free(path); | ||
231 | return NULL; | ||
232 | } | ||
233 | |||
234 | G3DObject *ldraw_part_get_object(LDrawPart *part, LDrawLibrary *lib) | ||
235 | { | ||
236 | G3DObject *object; | ||
237 | G3DMaterial *material; | ||
238 | gchar buffer[1024]; | ||
239 | |||
240 | object = g_new0(G3DObject, 1); | ||
241 | material = g3d_material_new(); | ||
242 | material->name = g_strdup("default material"); | ||
243 | object->materials = g_slist_append(object->materials, material); | ||
244 | |||
245 | while(!g3d_stream_eof(part->stream)) { | ||
246 | memset(buffer, 0, 1024); | ||
247 | g3d_stream_read_line(part->stream, buffer, 1023); | ||
248 | g_strstrip(buffer); | ||
249 | if(strlen(buffer) == 0) | ||
250 | continue; | ||
251 | switch(buffer[0] - 0x30) { | ||
252 | case 0: /* meta data */ | ||
253 | ldraw_part_parse_meta(object, buffer + 2); | ||
254 | break; | ||
255 | case 1: /* sub-file reference */ | ||
256 | ldraw_part_parse_ref(object, buffer + 2, lib); | ||
257 | break; | ||
258 | case 2: /* line */ | ||
259 | break; | ||
260 | case 3: /* triangle */ | ||
261 | ldraw_part_parse_tri(object, buffer + 2, lib); | ||
262 | break; | ||
263 | case 4: /* quadrilateral */ | ||
264 | ldraw_part_parse_quad(object, buffer + 2, lib); | ||
265 | break; | ||
266 | case 5: /* optional line */ | ||
267 | break; | ||
268 | default: | ||
269 | g_warning("LDraw: unknown type of line: %s", buffer); | ||
270 | break; | ||
271 | } | ||
272 | if(part->master) { | ||
273 | g3d_context_update_progress_bar(lib->context, | ||
274 | (G3DFloat)g3d_stream_tell(part->stream) / | ||
275 | (G3DFloat)g3d_stream_size(part->stream), TRUE); | ||
276 | g3d_context_update_interface(lib->context); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | return object; | ||
281 | } | ||
282 | |||
283 | void ldraw_part_free(LDrawPart *part) | ||
284 | { | ||
285 | if(part->stream) | ||
286 | g3d_stream_close(part->stream); | ||
287 | if(part->filename) | ||
288 | g_free(part->filename); | ||
289 | g_free(part->name); | ||
290 | g_free(part); | ||
291 | } | ||