aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md2/imp_md2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md2/imp_md2.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md2/imp_md2.c292
1 files changed, 292 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md2/imp_md2.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md2/imp_md2.c
new file mode 100644
index 0000000..4c9d4c6
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_md2/imp_md2.c
@@ -0,0 +1,292 @@
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
26#include <g3d/types.h>
27#include <g3d/material.h>
28#include <g3d/texture.h>
29#include <g3d/stream.h>
30#include <g3d/iff.h>
31
32#include "imp_md2_normals.h"
33
34#define MD2_SKINNAMELEN 64
35
36static const char *textureExtensions[] = {
37 ".pcx", ".bmp", ".jpg", ".tga", ".png", NULL };
38
39EAPI
40gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream,
41 G3DModel *model, gpointer user_data)
42{
43 guint32 idid, idver, skinwidth, skinheight, framesize;
44 guint32 numskins, numverts, numtexs, numfaces, numglcmds, numframes;
45 guint32 offskins, offtexs, offfaces, offframes, offglcmds, offend;
46 G3DFloat *texco = NULL, *normals;
47 gchar **skinnames = NULL;
48 gint i, j;
49 G3DObject *object;
50 G3DMaterial *material;
51 G3DImage *image = NULL;
52
53 idid = g3d_stream_read_int32_be(stream);
54 if(idid != G3D_IFF_MKID('I','D','P','2')) {
55 g_critical("file '%s' is not a .md2 file", stream->uri);
56 return FALSE;
57 }
58
59 idver = g3d_stream_read_int32_le(stream);
60 if(idver != 8) {
61 g_warning("file '%s' has wrong version (%d)", stream->uri, idver);
62#define CLOSE_ON_WRONG_VERSION
63#ifdef CLOSE_ON_WRONG_VERSION
64 return FALSE;
65#endif
66 }
67
68 object = g_new0(G3DObject, 1);
69 object->name = g_strdup("Q2Object");
70 material = g3d_material_new();
71 object->materials = g_slist_append(object->materials, material);
72 model->objects = g_slist_append(model->objects, object);
73
74 skinwidth = g3d_stream_read_int32_le(stream);
75 skinheight = g3d_stream_read_int32_le(stream);
76 framesize = g3d_stream_read_int32_le(stream);
77 numskins = g3d_stream_read_int32_le(stream);
78 numverts = g3d_stream_read_int32_le(stream);
79 numtexs = g3d_stream_read_int32_le(stream);
80 numfaces = g3d_stream_read_int32_le(stream);
81 numglcmds = g3d_stream_read_int32_le(stream);
82 numframes = g3d_stream_read_int32_le(stream);
83
84 object->vertex_count = numverts;
85 object->vertex_data = g_new0(G3DFloat, numverts * 3);
86 normals = g_new0(G3DFloat, numverts * 3);
87
88 offskins = g3d_stream_read_int32_le(stream);
89 offtexs = g3d_stream_read_int32_le(stream);
90 offfaces = g3d_stream_read_int32_le(stream);
91 offframes = g3d_stream_read_int32_le(stream);
92 offglcmds = g3d_stream_read_int32_le(stream);
93 offend = g3d_stream_read_int32_le(stream);
94
95 if(numskins > 0) {
96 skinnames = g_new0(gchar *, numskins);
97 for(i = 0; i < numskins; i ++) {
98 skinnames[i] = g_new0(gchar, MD2_SKINNAMELEN);
99 g3d_stream_read(stream, skinnames[i], MD2_SKINNAMELEN);
100
101 /* some md2 models have a dot as first character to tell the engine
102 * load the texture from the dir where the model is located */
103 if(skinnames[i][0] == '.')
104 memmove(skinnames[i], skinnames[i] + 1, MD2_SKINNAMELEN - 1);
105#if DEBUG > 0
106 g_debug("skin #%d: %s", i + 1, skinnames[i]);
107#endif
108 }
109
110 /* not every skin has a texture assigned, the engines will search
111 * a list of supported images to get the texture */
112 for(j = 0; j < numskins; j++) {
113 gchar skinname[MD2_SKINNAMELEN];
114 gchar *basename;
115
116 /* real filename */
117 if(g_file_test(skinnames[j], G_FILE_TEST_EXISTS))
118 image = g3d_texture_load_cached(context, model, skinnames[j]);
119 if(image)
120 break;
121 basename = g_path_get_basename(skinnames[j]);
122 if(g_file_test(basename, G_FILE_TEST_EXISTS))
123 image = g3d_texture_load_cached(context, model, skinnames[j]);
124 g_free(basename);
125 if(image)
126 break;
127
128 /* without extension */
129 for(i = 0; textureExtensions[i] != NULL; i ++) {
130 g_snprintf(skinname, sizeof(skinname), "%s%s", skinnames[j],
131 textureExtensions[i]);
132 if(g_file_test(skinname, G_FILE_TEST_EXISTS))
133 image = g3d_texture_load_cached(context, model, skinname);
134 if(image)
135 break;
136 basename = g_path_get_basename(skinname);
137 if(g_file_test(basename, G_FILE_TEST_EXISTS))
138 image = g3d_texture_load_cached(context, model, skinname);
139 g_free(basename);
140 if(image)
141 break;
142 }
143
144 /* replace extension */
145 for(i = 0; textureExtensions[i] != NULL; i ++) {
146 g_snprintf(skinname, sizeof(skinname), "%.*s%s",
147 ((int) strlen(skinnames[j])) - 4, skinnames[j],
148 textureExtensions[i]);
149 if(g_file_test(skinname, G_FILE_TEST_EXISTS))
150 image = g3d_texture_load_cached(context, model, skinname);
151 if(image)
152 break;
153 basename = g_path_get_basename(skinname);
154 if(g_file_test(basename, G_FILE_TEST_EXISTS))
155 image = g3d_texture_load_cached(context, model, skinname);
156 g_free(basename);
157 if(image)
158 break;
159 }
160 if(image)
161 break;
162 }
163
164 /* fallback skin name */
165 if(image == NULL)
166 image = g3d_texture_load_cached(context, model, "tris0.bmp");
167 if(image)
168 image->tex_env = G3D_TEXENV_REPLACE;
169 }
170
171 g3d_stream_seek(stream, offframes, G_SEEK_SET);
172 /* vertices per frame */
173#if DEBUG > 0
174 g_debug("numframes: %d", numframes);
175#endif
176 for(i = 0; i < numframes; i ++) {
177 G3DFloat s0,s1,s2, t0,t1,t2;
178 gchar fname[16];
179 guint32 j;
180
181 s0 = g3d_stream_read_float_le(stream); /* scale */
182 s1 = g3d_stream_read_float_le(stream);
183 s2 = g3d_stream_read_float_le(stream);
184 t0 = g3d_stream_read_float_le(stream); /* translate */
185 t1 = g3d_stream_read_float_le(stream);
186 t2 = g3d_stream_read_float_le(stream);
187 g3d_stream_read(stream, fname, 16); /* frame name*/
188
189 for(j = 0; j < numverts; j ++) {
190 G3DFloat x,y,z;
191 guint32 v,n;
192
193 v = g3d_stream_read_int8(stream);
194 x = (G3DFloat)v * s0 + t0;
195 v = g3d_stream_read_int8(stream);
196 y = (G3DFloat)v * s1 + t1;
197 v = g3d_stream_read_int8(stream);
198 z = (G3DFloat)v * s2 + t2;
199 n = g3d_stream_read_int8(stream);
200 if(i == 0) {
201 object->vertex_data[j * 3 + 0] = x;
202 object->vertex_data[j * 3 + 1] = y;
203 object->vertex_data[j * 3 + 2] = z;
204
205 normals[j * 3 + 0] = md2_normals[n * 3 + 0];
206 normals[j * 3 + 1] = md2_normals[n * 3 + 1];
207 normals[j * 3 + 2] = md2_normals[n * 3 + 2];
208 }
209 }
210 }
211
212 g3d_stream_seek(stream, offtexs, G_SEEK_SET);
213 /* texture coordinates */
214 if(numtexs > 0) {
215 texco = g_new0(G3DFloat, numtexs * 2);
216 for(i = 0; i < numtexs; i ++) {
217 texco[i * 2 + 0] = g3d_stream_read_int16_le(stream) /
218 (G3DFloat)skinwidth;
219 texco[i * 2 + 1] = g3d_stream_read_int16_le(stream) /
220 (G3DFloat)skinheight;
221 }
222 }
223
224 /* faces */
225 for(i = 0; i < numfaces; i ++) {
226 G3DFace *face;
227 guint32 i;
228 guint16 index;
229
230 face = g_new0(G3DFace, 1);
231 object->faces = g_slist_append(object->faces, face);
232 face->material = material;
233 face->vertex_count = 3;
234 face->vertex_indices = g_new0(guint32, 3);
235 face->tex_vertex_data = g_new0(G3DFloat, 3 * 2);
236 face->normals = g_new0(G3DFloat, 3 * 3);
237 face->flags |= G3D_FLAG_FAC_NORMALS;
238
239 if(image)
240 {
241 face->flags |= G3D_FLAG_FAC_TEXMAP;
242 face->tex_image = image;
243 }
244
245 for(i = 0; i < 3; i ++)
246 {
247 face->vertex_indices[i] = g3d_stream_read_int16_le(stream);
248 face->normals[i * 3 + 0] =
249 - normals[face->vertex_indices[i] * 3 + 0];
250 face->normals[i * 3 + 1] =
251 - normals[face->vertex_indices[i] * 3 + 1];
252 face->normals[i * 3 + 2] =
253 - normals[face->vertex_indices[i] * 3 + 2];
254 }
255
256 for(i = 0; i < 3; i ++)
257 {
258 index = g3d_stream_read_int16_le(stream);
259 face->tex_vertex_data[i * 2 + 0] = texco[index * 2 + 0];
260 face->tex_vertex_data[i * 2 + 1] = texco[index * 2 + 1];
261 }
262 }
263
264
265 /* free skin names */
266 if(skinnames)
267 {
268 for(i = 0; i < numskins; i ++)
269 g_free(skinnames[i]);
270 g_free(skinnames);
271 }
272
273 if(texco)
274 g_free(texco);
275 if(normals)
276 g_free(normals);
277
278 return TRUE;
279}
280
281EAPI
282gchar *plugin_description(G3DContext *context)
283{
284 return g_strdup("ID Software's Quake II models.");
285}
286
287EAPI
288gchar **plugin_extensions(G3DContext *context)
289{
290 return g_strsplit("md2", ":", 0);
291}
292