aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_joe/imp_joe.c
diff options
context:
space:
mode:
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.c386
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
36G3DObject *joe_load_object(G3DContext *context, const gchar *filename,
37 G3DModel *model);
38GHashTable *joe_load_car(const gchar *filename);
39void joe_destroy_car(GHashTable *hashtable);
40gboolean joe_parse_vertex(const gchar *text, G3DFloat *x, G3DFloat *y, G3DFloat *z);
41void joe_object_flip_x(G3DObject *object);
42
43/*****************************************************************************/
44/* plugin interface */
45/*****************************************************************************/
46
47EAPI
48gboolean 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
128EAPI
129gchar *plugin_description(void)
130{
131 return g_strdup("VDrift models.");
132}
133
134EAPI
135gchar **plugin_extensions(void)
136{
137 return g_strsplit("joe:car", ":", 0);
138}
139
140/*****************************************************************************/
141
142G3DObject *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
318GHashTable *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
370void joe_destroy_car(GHashTable *hashtable)
371{
372 g_hash_table_destroy(hashtable);
373}
374
375gboolean 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
380void 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}