diff options
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_joe/imp_joe.c')
-rw-r--r-- | src/others/mimesh/libg3d-0.0.8/plugins/import/imp_joe/imp_joe.c | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_joe/imp_joe.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_joe/imp_joe.c new file mode 100644 index 0000000..b79447e --- /dev/null +++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_joe/imp_joe.c | |||
@@ -0,0 +1,386 @@ | |||
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 <stdio.h> | ||
24 | #include <string.h> | ||
25 | #include <locale.h> | ||
26 | |||
27 | #include <g3d/types.h> | ||
28 | #include <g3d/stream.h> | ||
29 | #include <g3d/model.h> | ||
30 | #include <g3d/object.h> | ||
31 | #include <g3d/iff.h> | ||
32 | #include <g3d/material.h> | ||
33 | #include <g3d/texture.h> | ||
34 | #include <g3d/matrix.h> | ||
35 | |||
36 | G3DObject *joe_load_object(G3DContext *context, const gchar *filename, | ||
37 | G3DModel *model); | ||
38 | GHashTable *joe_load_car(const gchar *filename); | ||
39 | void joe_destroy_car(GHashTable *hashtable); | ||
40 | gboolean joe_parse_vertex(const gchar *text, G3DFloat *x, G3DFloat *y, G3DFloat *z); | ||
41 | void joe_object_flip_x(G3DObject *object); | ||
42 | |||
43 | /*****************************************************************************/ | ||
44 | /* plugin interface */ | ||
45 | /*****************************************************************************/ | ||
46 | |||
47 | EAPI | ||
48 | gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream, | ||
49 | G3DModel *model, gpointer plugin_data) | ||
50 | { | ||
51 | G3DObject *object; | ||
52 | GHashTable *cardata; | ||
53 | gchar *value; | ||
54 | G3DFloat x, y, z; | ||
55 | G3DMatrix matrix[16]; | ||
56 | gboolean rval = FALSE; | ||
57 | |||
58 | if(g_strcasecmp(stream->uri + strlen(stream->uri) - 3, "car") == 0) | ||
59 | { | ||
60 | /* .car file */ | ||
61 | setlocale(LC_NUMERIC, "C"); | ||
62 | |||
63 | cardata = joe_load_car(stream->uri); | ||
64 | |||
65 | joe_load_object(context, "body.joe", model); | ||
66 | joe_load_object(context, "interior.joe", model); | ||
67 | joe_load_object(context, "glass.joe", model); | ||
68 | |||
69 | /* wheels */ | ||
70 | object = joe_load_object(context, "wheel_front.joe", model); | ||
71 | joe_object_flip_x(object); | ||
72 | value = g_hash_table_lookup(cardata, "wheel-FL.position"); | ||
73 | if(value != NULL) | ||
74 | { | ||
75 | joe_parse_vertex(value, &x, &y, &z); | ||
76 | g3d_matrix_identity(matrix); | ||
77 | g3d_matrix_translate(y, x, z, matrix); | ||
78 | g3d_object_transform(object, matrix); | ||
79 | } | ||
80 | |||
81 | object = joe_load_object(context, "wheel_front.joe", model); | ||
82 | value = g_hash_table_lookup(cardata, "wheel-FR.position"); | ||
83 | if(value != NULL) | ||
84 | { | ||
85 | joe_parse_vertex(value, &x, &y, &z); | ||
86 | g3d_matrix_identity(matrix); | ||
87 | g3d_matrix_translate(y, x, z, matrix); | ||
88 | g3d_object_transform(object, matrix); | ||
89 | } | ||
90 | |||
91 | object = joe_load_object(context, "wheel_rear.joe", model); | ||
92 | joe_object_flip_x(object); | ||
93 | value = g_hash_table_lookup(cardata, "wheel-RL.position"); | ||
94 | if(value != NULL) | ||
95 | { | ||
96 | joe_parse_vertex(value, &x, &y, &z); | ||
97 | g3d_matrix_identity(matrix); | ||
98 | g3d_matrix_translate(y, x, z, matrix); | ||
99 | g3d_object_transform(object, matrix); | ||
100 | } | ||
101 | |||
102 | object = joe_load_object(context, "wheel_rear.joe", model); | ||
103 | value = g_hash_table_lookup(cardata, "wheel-RR.position"); | ||
104 | if(value != NULL) | ||
105 | { | ||
106 | joe_parse_vertex(value, &x, &y, &z); | ||
107 | g3d_matrix_identity(matrix); | ||
108 | g3d_matrix_translate(y, x, z, matrix); | ||
109 | g3d_object_transform(object, matrix); | ||
110 | } | ||
111 | |||
112 | joe_destroy_car(cardata); | ||
113 | rval = TRUE; | ||
114 | } | ||
115 | else | ||
116 | { | ||
117 | /* .joe file */ | ||
118 | rval = (joe_load_object(context, stream->uri, model) != NULL); | ||
119 | } | ||
120 | |||
121 | g3d_matrix_identity(matrix); | ||
122 | g3d_matrix_rotate_xyz(G_PI * -90.0 / 180, 0.0, 0.0, matrix); | ||
123 | g3d_model_transform(model, matrix); | ||
124 | |||
125 | return rval; | ||
126 | } | ||
127 | |||
128 | EAPI | ||
129 | gchar *plugin_description(void) | ||
130 | { | ||
131 | return g_strdup("VDrift models."); | ||
132 | } | ||
133 | |||
134 | EAPI | ||
135 | gchar **plugin_extensions(void) | ||
136 | { | ||
137 | return g_strsplit("joe:car", ":", 0); | ||
138 | } | ||
139 | |||
140 | /*****************************************************************************/ | ||
141 | |||
142 | G3DObject *joe_load_object(G3DContext *context, const gchar *filename, | ||
143 | G3DModel *model) | ||
144 | { | ||
145 | G3DStream *stream; | ||
146 | gchar *basename, *texname; | ||
147 | G3DObject *object; | ||
148 | G3DMaterial *material; | ||
149 | G3DFace *face; | ||
150 | G3DImage *image; | ||
151 | GSList *item; | ||
152 | guint32 magic, version; | ||
153 | guint32 num_faces, num_frames, num_verts, num_texcoords, num_normals; | ||
154 | gint32 frame, i, j, index; | ||
155 | guint16 *tex_indices, *normal_indices; | ||
156 | G3DFloat *normals = NULL, *texcoords = NULL; | ||
157 | |||
158 | stream = g3d_stream_open_file(filename, "rb"); | ||
159 | if(stream == NULL) { | ||
160 | g_critical("JOE: failed to read '%s'", filename); | ||
161 | return NULL; | ||
162 | } | ||
163 | |||
164 | magic = g3d_stream_read_int32_be(stream); | ||
165 | if(magic != G3D_IFF_MKID('I','D','P','2')) { | ||
166 | g_critical("JOE: wrong magic in '%s'", filename); | ||
167 | g3d_stream_close(stream); | ||
168 | return NULL; | ||
169 | } | ||
170 | |||
171 | /* base file name for object name & texture loading */ | ||
172 | basename = g_path_get_basename(filename); | ||
173 | |||
174 | /* version 3 */ | ||
175 | |||
176 | version = g3d_stream_read_int32_le(stream); | ||
177 | num_faces = g3d_stream_read_int32_le(stream); | ||
178 | num_frames = g3d_stream_read_int32_le(stream); | ||
179 | |||
180 | printf("JOE: faces: %d, frames: %d\n", num_faces, num_frames); | ||
181 | |||
182 | /* create object */ | ||
183 | object = g_new0(G3DObject, 1); | ||
184 | object->name = g_strdup(basename); | ||
185 | model->objects = g_slist_append(model->objects, object); | ||
186 | |||
187 | /* load texture image */ | ||
188 | memcpy(basename + strlen(basename) - 3, "png", 3); | ||
189 | texname = g_strdup_printf("textures/%s", basename); | ||
190 | image = g3d_texture_load_cached(context, model, texname); | ||
191 | if(image == NULL) | ||
192 | g_warning("JOE: failed to load texture '%s'\n", texname); | ||
193 | else | ||
194 | image->tex_id = g_str_hash(texname); | ||
195 | g_free(texname); | ||
196 | |||
197 | /* create default material */ | ||
198 | material = g3d_material_new(); | ||
199 | material->name = g_strdup("default material"); | ||
200 | material->tex_image = image; | ||
201 | object->materials = g_slist_append(object->materials, material); | ||
202 | |||
203 | /* frames */ | ||
204 | for(frame = 0; frame < 1; frame ++) { | ||
205 | /* create temporary storage */ | ||
206 | tex_indices = g_new0(guint16, num_faces * 3 * 3); | ||
207 | normal_indices = g_new0(guint16, num_faces * 3 * 2); | ||
208 | |||
209 | /* faces blob */ | ||
210 | for(i = 0; i < num_faces; i ++) { | ||
211 | face = g_new0(G3DFace, 1); | ||
212 | face->material = material; | ||
213 | face->vertex_count = 3; | ||
214 | face->vertex_indices = g_new0(guint32, 3); | ||
215 | |||
216 | for(j = 0; j < 3; j ++) | ||
217 | face->vertex_indices[j] = g3d_stream_read_int16_le(stream); | ||
218 | |||
219 | /* normalIndex */ | ||
220 | for(j = 0; j < 3; j ++) | ||
221 | normal_indices[i * 3 + j] = g3d_stream_read_int16_le(stream); | ||
222 | |||
223 | /* textureIndex */ | ||
224 | /* JOE_MAX_TEXTURES times, 1x for version 3 */ | ||
225 | for(j = 0; j < 3; j ++) | ||
226 | tex_indices[i * 3 + j] = g3d_stream_read_int16_le(stream); | ||
227 | |||
228 | object->faces = g_slist_append(object->faces, face); | ||
229 | } | ||
230 | |||
231 | /* num_verts */ | ||
232 | num_verts = g3d_stream_read_int32_le(stream); | ||
233 | |||
234 | /* num_texcoords */ | ||
235 | num_texcoords = g3d_stream_read_int32_le(stream); | ||
236 | if(num_texcoords != 0) | ||
237 | texcoords = g_new0(G3DFloat, num_texcoords * 2); | ||
238 | |||
239 | /* num_normals */ | ||
240 | num_normals = g3d_stream_read_int32_le(stream); | ||
241 | if(num_normals != 0) | ||
242 | normals = g_new0(G3DFloat, num_normals * 3); | ||
243 | |||
244 | g_debug("JOE: verts: %d, texcoords: %d, normals: %d\n", | ||
245 | num_verts, num_texcoords, num_normals); | ||
246 | |||
247 | /* verts blob */ | ||
248 | object->vertex_count = num_verts; | ||
249 | object->vertex_data = g_new0(G3DFloat, num_verts * 3); | ||
250 | for(i = 0; i < num_verts; i ++) { | ||
251 | object->vertex_data[i * 3 + 0] = g3d_stream_read_float_le(stream); | ||
252 | object->vertex_data[i * 3 + 1] = g3d_stream_read_float_le(stream); | ||
253 | object->vertex_data[i * 3 + 2] = g3d_stream_read_float_le(stream); | ||
254 | } | ||
255 | |||
256 | /* normals blob */ | ||
257 | for(i = 0; i < num_normals; i ++) { | ||
258 | normals[i * 3 + 0] = - g3d_stream_read_float_le(stream); | ||
259 | normals[i * 3 + 1] = - g3d_stream_read_float_le(stream); | ||
260 | normals[i * 3 + 2] = - g3d_stream_read_float_le(stream); | ||
261 | } | ||
262 | |||
263 | /* texcoords blob */ | ||
264 | for(i = 0; i < num_texcoords; i ++) { | ||
265 | texcoords[i * 2 + 0] = g3d_stream_read_float_le(stream); | ||
266 | texcoords[i * 2 + 1] = g3d_stream_read_float_le(stream); | ||
267 | } | ||
268 | |||
269 | /* fix faces */ | ||
270 | for(item = object->faces, i = 0; item != NULL; item = item->next, i ++) | ||
271 | { | ||
272 | face = (G3DFace *)item->data; | ||
273 | |||
274 | face->flags |= G3D_FLAG_FAC_NORMALS; | ||
275 | if(image != NULL) face->flags |= G3D_FLAG_FAC_TEXMAP; | ||
276 | |||
277 | face->normals = g_new0(G3DFloat, 3 * 3); | ||
278 | face->tex_image = image; | ||
279 | face->tex_vertex_count = 3; | ||
280 | face->tex_vertex_data = g_new0(G3DFloat, 3 * 2); | ||
281 | for(j = 0; j < 3; j ++) | ||
282 | { | ||
283 | index = normal_indices[i * 3 + j]; | ||
284 | face->normals[j * 3 + 0] = normals[index * 3 + 0]; | ||
285 | face->normals[j * 3 + 1] = normals[index * 3 + 1]; | ||
286 | face->normals[j * 3 + 2] = normals[index * 3 + 2]; | ||
287 | |||
288 | index = tex_indices[i * 3 + j]; | ||
289 | face->tex_vertex_data[j * 2 + 0] = texcoords[index * 2 + 0]; | ||
290 | face->tex_vertex_data[j * 2 + 1] = texcoords[index * 2 + 1]; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | /* clear temporary storage */ | ||
295 | g_free(normal_indices); | ||
296 | g_free(tex_indices); | ||
297 | |||
298 | if(normals != NULL) | ||
299 | { | ||
300 | g_free(normals); | ||
301 | normals = NULL; | ||
302 | } | ||
303 | |||
304 | if(texcoords != NULL) | ||
305 | { | ||
306 | g_free(texcoords); | ||
307 | texcoords = NULL; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /* clean up */ | ||
312 | g_free(basename); | ||
313 | g3d_stream_close(stream); | ||
314 | |||
315 | return object; | ||
316 | } | ||
317 | |||
318 | GHashTable *joe_load_car(const gchar *filename) | ||
319 | { | ||
320 | G3DStream *stream; | ||
321 | GHashTable *ht; | ||
322 | gchar buffer[2048 + 1], section[256], varname[256], value[256]; | ||
323 | gchar *ep; | ||
324 | |||
325 | stream = g3d_stream_open_file(filename, "r"); | ||
326 | if(stream == NULL) { | ||
327 | g_critical("JOE: failed to read '%s'", filename); | ||
328 | return NULL; | ||
329 | } | ||
330 | |||
331 | ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | ||
332 | |||
333 | memset(section, 0, 256); | ||
334 | |||
335 | while(!g3d_stream_eof(stream)) { | ||
336 | g3d_stream_read_line(stream, buffer, 2048); | ||
337 | if((buffer[0] == '\0') || (buffer[0] == '\n')) | ||
338 | continue; | ||
339 | |||
340 | if(buffer[0] == '[') { | ||
341 | /* section title */ | ||
342 | if(sscanf(buffer, "[ %s ]", section) != 1) { | ||
343 | g_warning("JOE: CAR: failed to read section title '%s'\n", | ||
344 | buffer); | ||
345 | } | ||
346 | } else { | ||
347 | /* property */ | ||
348 | ep = strchr(buffer, '='); | ||
349 | if(ep != NULL) | ||
350 | { | ||
351 | memset(varname, 0, 256); | ||
352 | strncpy(varname, buffer, (ep - buffer)); | ||
353 | g_strstrip(varname); | ||
354 | |||
355 | strcpy(value, ep + 1); | ||
356 | g_strstrip(value); | ||
357 | #if DEBUG > 0 | ||
358 | g_debug("JOE: %s.%s = %s", section, varname, value); | ||
359 | #endif | ||
360 | g_hash_table_insert(ht, | ||
361 | g_strdup_printf("%s.%s", section, varname), | ||
362 | g_strdup(value)); | ||
363 | } | ||
364 | } | ||
365 | } | ||
366 | |||
367 | return ht; | ||
368 | } | ||
369 | |||
370 | void joe_destroy_car(GHashTable *hashtable) | ||
371 | { | ||
372 | g_hash_table_destroy(hashtable); | ||
373 | } | ||
374 | |||
375 | gboolean joe_parse_vertex(const gchar *text, G3DFloat *x, G3DFloat *y, G3DFloat *z) | ||
376 | { | ||
377 | return (sscanf(text, G3D_SCANF_FLOAT ", " G3D_SCANF_FLOAT ", " G3D_SCANF_FLOAT, x, y, z) == 3); | ||
378 | } | ||
379 | |||
380 | void joe_object_flip_x(G3DObject *object) | ||
381 | { | ||
382 | guint32 i; | ||
383 | |||
384 | for(i = 0; i < object->vertex_count; i ++) | ||
385 | object->vertex_data[i * 3 + 0] *= -1; | ||
386 | } | ||