aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md3/imp_md3.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md3/imp_md3.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md3/imp_md3.c396
1 files changed, 396 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md3/imp_md3.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md3/imp_md3.c
new file mode 100644
index 0000000..360a568
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md3/imp_md3.c
@@ -0,0 +1,396 @@
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 <string.h>
24#include <math.h>
25
26#ifndef M_PI
27# define M_PI 3.14159265358979323846
28#endif
29
30#include <g3d/types.h>
31#include <g3d/object.h>
32#include <g3d/stream.h>
33#include <g3d/iff.h>
34#include <g3d/material.h>
35#include <g3d/texture.h>
36#include <g3d/vector.h>
37
38#define MD3_TYPE_MD3 0x01
39#define MD3_TYPE_MDC 0x02
40
41gboolean md3_load_skin(G3DContext *context, G3DModel *model,
42 const gchar *filename);
43gboolean md3_read_tag(G3DStream *stream, G3DContext *context, G3DModel *model);
44gboolean md3_read_mesh(G3DStream *stream, G3DContext *context, G3DModel *model);
45
46
47EAPI
48gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream,
49 G3DModel *model, gpointer user_data)
50{
51 guint32 magic, version, nboneframes, ntags, nmeshes, nskins;
52 guint32 off_bfs, off_tags, off_meshes, filesize, i, flags;
53
54 magic = g3d_stream_read_int32_be(stream);
55 if((magic != G3D_IFF_MKID('I', 'D', 'P', '3')) &&
56 (magic != G3D_IFF_MKID('I', 'D', 'P', 'C'))) {
57 g_warning("MD3: %s is not a valid md3 file", stream->uri);
58 return FALSE;
59 }
60
61 version = g3d_stream_read_int32_le(stream);
62 g3d_stream_skip(stream, 64);
63
64 flags = g3d_stream_read_int32_le(stream);
65 nboneframes = g3d_stream_read_int32_le(stream);
66 ntags = g3d_stream_read_int32_le(stream);
67 nmeshes = g3d_stream_read_int32_le(stream);
68 nskins = g3d_stream_read_int32_le(stream);
69 off_bfs = g3d_stream_read_int32_le(stream);
70 off_tags = g3d_stream_read_int32_le(stream);
71 off_meshes = g3d_stream_read_int32_le(stream);
72 filesize = g3d_stream_read_int32_le(stream);
73
74 /* try to load skin */
75 md3_load_skin(context, model, stream->uri);
76
77 g_debug("MD3: version: %u, file size: %u bytes", version, filesize);
78 g_debug("MD3: tags @ 0x%08x, meshes @ 0x%08x", off_tags, off_meshes);
79
80 g3d_stream_seek(stream, off_tags, G_SEEK_SET);
81 if(magic == G3D_IFF_MKID('I', 'D', 'P', '3'))
82 for(i = 0; i < nboneframes * ntags; i ++)
83 md3_read_tag(stream, context, model);
84
85 /* read meshes */
86 g3d_stream_seek(stream, off_meshes, G_SEEK_SET);
87 for(i = 0; i < nmeshes; i ++)
88 md3_read_mesh(stream, context, model);
89
90 return TRUE;
91}
92
93EAPI
94gchar *plugin_description(G3DContext *context)
95{
96 return g_strdup("Quake 3 models.");
97}
98
99EAPI
100gchar **plugin_extensions(G3DContext *context)
101{
102 return g_strsplit("md3:mdc", ":", 0);
103}
104
105/*
106 * MD3 specific
107 */
108
109gboolean md3_load_skin(G3DContext *context, G3DModel *model,
110 const gchar *filename)
111{
112 gchar *basename, *skinname, **parts;
113 gchar line[256];
114 G3DStream *stream;
115 G3DMaterial *material;
116
117 basename = g_path_get_basename(filename);
118 skinname = g_strdup_printf("%.*s_default.skin",
119 ((int) strlen(basename)) - 4, basename);
120
121 g_debug("MD3: trying to open skin file %s", skinname);
122
123 stream = g3d_stream_open_file(skinname, "r");
124
125 g_free(basename);
126 g_free(skinname);
127
128 /* no skin */
129 if(stream == NULL)
130 return FALSE;
131
132 while(g3d_stream_read_line(stream, line, 255) != NULL) {
133 parts = g_strsplit(line, ",", 2);
134 if(parts[0] && parts[1]) {
135 g_strchomp(parts[1]);
136 if(strlen(parts[1]) > 0)
137 {
138 g_debug("MD3: skin texture for %s: %s",
139 parts[0], parts[1]);
140
141 material = g3d_material_new();
142 material->name = g_strdup(parts[0]);
143 material->tex_image = g3d_texture_load_cached(context, model,
144 parts[1]);
145
146 model->materials = g_slist_append(model->materials,
147 material);
148 }
149 }
150 g_strfreev(parts);
151 }
152
153 g3d_stream_close(stream);
154
155 return TRUE;
156}
157
158gboolean md3_read_tag(G3DStream *stream, G3DContext *context, G3DModel *model)
159{
160 gchar name[65];
161
162 g3d_stream_read(stream, name, 64);
163 name[64] = '\0';
164
165 g_debug("MD3: tag: %s", name);
166
167 /* position */
168 g3d_stream_read_float_le(stream);
169 g3d_stream_read_float_le(stream);
170 g3d_stream_read_float_le(stream);
171
172 /* rotation */
173 g3d_stream_read_float_le(stream);
174 g3d_stream_read_float_le(stream);
175 g3d_stream_read_float_le(stream);
176
177 g3d_stream_read_float_le(stream);
178 g3d_stream_read_float_le(stream);
179 g3d_stream_read_float_le(stream);
180
181 g3d_stream_read_float_le(stream);
182 g3d_stream_read_float_le(stream);
183 g3d_stream_read_float_le(stream);
184
185 return TRUE;
186}
187
188gboolean md3_read_mesh(G3DStream *stream, G3DContext *context, G3DModel *model)
189{
190 G3DObject *object;
191 G3DImage *image = NULL;
192 G3DMaterial *material, *mat;
193 G3DFace *face;
194 GSList *mitem;
195 guint32 magic, i, j;
196 guint8 type = 0, r, s;
197 G3DFloat rho, sigma, *normals;
198 gchar name[64], *strp;
199 guint32 nmeshframe, nskin, nvertex, ntris, mlength, flags;
200 goffset off_tris, off_texvec, off_vertex, off_start, off_skins;
201
202 off_start = g3d_stream_tell(stream);
203
204 magic = g3d_stream_read_int32_be(stream);
205
206 if(magic == G3D_IFF_MKID('I', 'D', 'P', '3'))
207 type = MD3_TYPE_MD3;
208 else /* if(magic == 0x07000000)*/
209 type = MD3_TYPE_MDC;
210#if 0
211 else
212 {
213 g_warning("MD3: mesh magic unknown (%02x%02x%02x%02x)\n",
214 (magic >> 24) & 0xFF,
215 (magic >> 16) & 0xFF,
216 (magic >> 8) & 0xFF,
217 magic & 0xFF);
218 return FALSE;
219 }
220#endif
221
222 object = g_new0(G3DObject, 1);
223
224 /* read name */
225 g3d_stream_read(stream, name, 64);
226 object->name = g_strndup(name, 64);
227
228 flags = g3d_stream_read_int32_le(stream);
229
230 if(type == MD3_TYPE_MD3) {
231 nmeshframe = g3d_stream_read_int32_le(stream);
232 nskin = g3d_stream_read_int32_le(stream);
233 } else if(type == MD3_TYPE_MDC) {
234 g3d_stream_read_int32_le(stream); /* ncompframes */
235 g3d_stream_read_int32_le(stream); /* nbaseframes */
236 g3d_stream_read_int32_le(stream); /* nshaders */
237 }
238
239 nvertex = g3d_stream_read_int32_le(stream);
240 ntris = g3d_stream_read_int32_le(stream);
241
242 off_tris = g3d_stream_read_int32_le(stream);
243 off_skins = g3d_stream_read_int32_le(stream);
244
245 off_texvec = g3d_stream_read_int32_le(stream);
246 off_vertex = g3d_stream_read_int32_le(stream);
247
248 if(type == MD3_TYPE_MDC) {
249 g3d_stream_read_int32_le(stream); /* off_compvert */
250 g3d_stream_read_int32_le(stream); /* off_fbasef */
251 g3d_stream_read_int32_le(stream); /* off_fcompf */
252 }
253
254 mlength = g3d_stream_read_int32_le(stream);
255
256 if((nvertex == 0) || (ntris == 0)) {
257 g_warning("MD3: %u vertices, %u triangles", nvertex, ntris);
258 g3d_stream_seek(stream, off_start + mlength, G_SEEK_SET);
259 return FALSE;
260 }
261
262 /* default material */
263 material = g3d_material_new();
264 material->name = g_strdup("default material");
265 object->materials = g_slist_append(object->materials, material);
266
267 /* skins */
268 g3d_stream_seek(stream, off_start + off_skins, G_SEEK_SET);
269 g3d_stream_read(stream, name, 64);
270 g_debug("MD3: skin name: %s", name);
271
272 /* read texture image */
273 if(strlen(name) > 0) {
274 image = g3d_texture_load_cached(context, model, name);
275 if(image == NULL) {
276 /* try jpeg */
277 strp = strrchr(name, '.');
278 if(strp) {
279 strcpy(strp, ".jpg");
280 image = g3d_texture_load_cached(context, model, name);
281 }
282 }
283 }
284
285 if(image == NULL) {
286 mitem = model->materials;
287 while(mitem) {
288 mat = (G3DMaterial *)mitem->data;
289 if(strcmp(mat->name, object->name) == 0) {
290 image = mat->tex_image;
291 break;
292 }
293 mitem = mitem->next;
294 }
295 }
296
297 /* read vertex data */
298 g3d_stream_seek(stream, off_start + off_vertex, G_SEEK_SET);
299 object->vertex_count = nvertex;
300 object->vertex_data = g_new0(G3DFloat, nvertex * 3);
301 normals = g_new0(G3DFloat, nvertex * 3);
302 for(i = 0; i < nvertex; i ++) {
303 gint16 d;
304
305 d = g3d_stream_read_int16_le(stream);
306 object->vertex_data[i * 3 + 0] = d;
307 d = g3d_stream_read_int16_le(stream);
308 object->vertex_data[i * 3 + 1] = d;
309 d = g3d_stream_read_int16_le(stream);
310 object->vertex_data[i * 3 + 2] = d;
311
312 /* compressed normal */
313 /* FIXME: the normals don't look right... */
314 r = g3d_stream_read_int8(stream); /* rho */
315 s = g3d_stream_read_int8(stream); /* sigma */
316 rho = r * 2 * M_PI / 256.0;
317 sigma = s * 2 * M_PI / 256.0;
318
319 normals[i * 3 + 0] = - cos(sigma) * sin(rho);
320 normals[i * 3 + 1] = - cos(sigma) * sin(rho);
321 normals[i * 3 + 2] = - cos(rho);
322
323 g3d_vector_unify(
324 &(normals[i * 3 + 0]),
325 &(normals[i * 3 + 1]),
326 &(normals[i * 3 + 2]));
327 }
328
329 /* read texture vertex data */
330 g3d_stream_seek(stream, off_start + off_texvec, G_SEEK_SET);
331 object->tex_vertex_data = g_new0(G3DFloat, nvertex * 2);
332 for(i = 0; i < nvertex; i ++) {
333 object->tex_vertex_data[i * 2 + 0] = g3d_stream_read_float_le(stream);
334 object->tex_vertex_data[i * 2 + 1] = g3d_stream_read_float_le(stream);
335 }
336
337 /* read triangles */
338 g3d_stream_seek(stream, off_start + off_tris, G_SEEK_SET);
339 for(i = 0; i < ntris; i ++)
340 {
341 face = g_new0(G3DFace, 1);
342 face->vertex_count = 3;
343 face->vertex_indices = g_new0(guint32, 3);
344 face->material = material;
345
346 face->flags |= G3D_FLAG_FAC_NORMALS;
347 face->normals = g_new0(G3DFloat, 3 * 3);
348
349 face->tex_image = image;
350 if(face->tex_image)
351 {
352 face->tex_vertex_data = g_new0(G3DFloat, 3 * 2);
353 face->flags |= G3D_FLAG_FAC_TEXMAP;
354 }
355
356 for(j = 0; j < 3; j ++)
357 {
358 face->vertex_indices[j] = g3d_stream_read_int32_le(stream);
359
360 /* copy normals */
361 face->normals[j * 3 + 0] =
362 normals[face->vertex_indices[j] * 3 + 0];
363 face->normals[j * 3 + 1] =
364 normals[face->vertex_indices[j] * 3 + 1];
365 face->normals[j * 3 + 2] =
366 normals[face->vertex_indices[j] * 3 + 2];
367
368 /* texture stuff */
369 if(face->tex_image)
370 {
371 face->tex_vertex_data[j * 2 + 0] =
372 object->tex_vertex_data[face->vertex_indices[j] * 2 + 0];
373 face->tex_vertex_data[j * 2 + 1] =
374 object->tex_vertex_data[face->vertex_indices[j] * 2 + 1];
375 }
376 }
377
378 object->faces = g_slist_append(object->faces, face);
379 }
380
381 /* free unused data */
382 if(object->tex_vertex_data)
383 {
384 g_free(object->tex_vertex_data);
385 object->tex_vertex_data = NULL;
386 }
387 if(normals)
388 g_free(normals);
389
390 model->objects = g_slist_append(model->objects, object);
391
392 g3d_stream_seek(stream, off_start + mlength, G_SEEK_SET);
393
394 return TRUE;
395}
396