aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_obj/imp_obj.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/mimesh/libg3d-0.0.8/plugins/import/imp_obj/imp_obj.c')
-rw-r--r--src/others/mimesh/libg3d-0.0.8/plugins/import/imp_obj/imp_obj.c403
1 files changed, 403 insertions, 0 deletions
diff --git a/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_obj/imp_obj.c b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_obj/imp_obj.c
new file mode 100644
index 0000000..7c2ce37
--- /dev/null
+++ b/src/others/mimesh/libg3d-0.0.8/plugins/import/imp_obj/imp_obj.c
@@ -0,0 +1,403 @@
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 <stdlib.h>
25#include <string.h>
26#include <errno.h>
27#include <locale.h>
28
29#include <g3d/context.h>
30#include <g3d/types.h>
31#include <g3d/material.h>
32#include <g3d/stream.h>
33
34#define OBJ_USE_GROUPING 0
35
36typedef struct {
37 goffset goff;
38 goffset ooff;
39 G3DObject *object;
40} ObjGroupOffset;
41
42static gboolean obj_tryloadmat(G3DModel *model, const gchar *filename);
43static G3DMaterial *obj_usemat(G3DModel *model, const gchar *matname);
44
45static G3DObject *obj_object_by_name(G3DModel *model, const gchar *name);
46#if OBJ_USE_GROUPING
47static G3DObject *obj_get_offset(GSList *group_list, guint32 *voffp,
48 guint32 index, G3DObject *defobj);
49#endif
50
51EAPI
52gboolean plugin_load_model_from_stream(G3DContext *context, G3DStream *stream,
53 G3DModel *model, gpointer user_data)
54{
55 gchar line[2048], matname[128], matfile[1024];
56 gchar *filename;
57 G3DObject *object = NULL;
58 G3DMaterial *material = NULL;
59 G3DFloat pcnt, prev_pcnt = 0.0;
60 gdouble x,y,z;
61 guint32 num_v, v_off = 1, v_cnt = 0;
62#if OBJ_USE_GROUPING
63 gchar oname[128];
64 ObjGroupOffset *grpoff;
65 GSList *group_list = NULL;
66#endif
67 goffset global_vertex_count = 0;
68
69 setlocale(LC_NUMERIC, "C");
70 filename = g3d_stream_get_uri(stream);
71
72 strncpy(matfile, filename, strlen(filename) - 3);
73 matfile[strlen(filename)-3] = '\0';
74 strcat(matfile, "mtl");
75 obj_tryloadmat(model, matfile);
76
77 object = obj_object_by_name(model, "(default)");
78
79 while(!g3d_stream_eof(stream))
80 {
81 memset(line, 0, 2048);
82 g3d_stream_read_line(stream, line, 2048);
83 /* remove leading and trailing whitespace characters */
84 g_strstrip(line);
85 if(strlen(line) > 0) {
86 switch(line[0]) {
87 case '#':
88 continue;
89 break;
90
91 case 'g': /* group */
92#if OBJ_USE_GROUPING
93 if(strlen(line) == 1)
94 strcpy(oname, "(default)");
95 else
96 sscanf(line, "g %s", oname);
97
98 material = obj_usemat(model, oname);
99
100 grpoff = g_new0(ObjGroupOffset, 1);
101 grpoff->object = obj_object_by_name(model, oname);
102 grpoff->goff = global_vertex_count;
103 grpoff->ooff = grpoff->object->vertex_count;
104 group_list = g_slist_append(group_list, grpoff);
105#if DEBUG > 0
106 g_debug("[g] 0x%08x / 0x%08x: \"%s\"",
107 (guint32)grpoff->goff,
108 (guint32)grpoff->ooff, grpoff->object->name);
109#endif
110 object = grpoff->object;
111 v_cnt = grpoff->ooff;
112#endif
113 break;
114
115 case 'l': /* line */
116 break;
117
118 case 'o': /* object */
119 break;
120
121 case 'v': /* vertex */
122 if(strncmp(line, "vn ", 3) == 0)
123 {
124 /* normal ? */
125 }
126 else if(strncmp(line, "vt ", 3) == 0)
127 {
128 /* ?? */
129 }
130 else if(sscanf(line, "v %lf %lf %lf", &x, &y, &z) == 3)
131 {
132 object->vertex_count ++;
133 object->vertex_data = g_realloc(object->vertex_data,
134 object->vertex_count * 3 * sizeof(G3DFloat));
135 object->vertex_data[v_cnt * 3 + 0] = x;
136 object->vertex_data[v_cnt * 3 + 1] = y;
137 object->vertex_data[v_cnt * 3 + 2] = z;
138
139 v_cnt ++;
140 global_vertex_count ++;
141 }
142 else g_warning("parse error in line: %s", line);
143 break;
144
145 case 'f': /* face */
146 if(strncmp("f ", line, 2) == 0)
147 {
148 G3DFace *face;
149 gchar **vertex, **vstrs = g_strsplit(line, " ", 0);
150 int i;
151
152 num_v = 0;
153 face = g_new0(G3DFace, 1);
154 if(material != NULL)
155 face->material = material;
156 else face->material =
157 g_slist_nth_data(object->materials, 0);
158
159 /* find number of vertices in line */
160 vertex = vstrs;
161 while(*vertex != NULL) { num_v++; vertex++; }
162 face->vertex_count = num_v - 1;
163
164 /* next one if # of vertices < 3 */
165 if(face->vertex_count < 3)
166 continue;
167
168 /* calculate object-local vertex offset, indices
169 * in .obj files are absolute */
170 i = strtol(vstrs[1], NULL, 10);
171#if OBJ_USE_GROUPING
172 object = obj_get_offset(group_list, &v_off,
173 (i < 0) ? global_vertex_count - i - 1 : i,
174 object);
175#else
176 v_off = 0;
177#endif
178 if(object == NULL) {
179 g_warning("error: face before object");
180 return FALSE;
181 }
182
183 /* read vertices */
184 face->vertex_indices = g_new0(guint32, num_v - 1);
185 for(i = 1; i < num_v; i ++) {
186 gint32 index = strtol(vstrs[i], NULL, 10);
187
188 if(index < 0)
189 face->vertex_indices[i - 1] =
190 global_vertex_count + index + v_off - 1;
191 else
192 face->vertex_indices[i - 1] = MIN(
193 (index - 1) + v_off,
194 object->vertex_count - 1);
195 }
196 g_strfreev(vstrs);
197 object->faces = g_slist_prepend(object->faces, face);
198 }
199 else
200 g_warning("parse error in line: %s", line);
201 break;
202
203 case 'u': /* usemat? */
204 case 'm':
205 case 's':
206 if(sscanf(line, "usemtl %s", matname) == 1) {
207 material = obj_usemat(model, matname);
208 } else if(sscanf(line, "mtllib %s", matfile) == 1) {
209 /* loads external material library */
210 if(obj_tryloadmat(model, matfile) != TRUE)
211 g_warning("error loading material library '%s'",
212 matfile);
213 }
214 break;
215 default:
216#if DEBUG > 0
217 g_debug("unknown type of line: %s", line);
218#endif
219 break;
220 }
221 }
222
223#if 1
224 pcnt = (G3DFloat)g3d_stream_tell(stream) /
225 (G3DFloat)g3d_stream_size(stream);
226 if((pcnt - prev_pcnt) > 0.01) {
227 prev_pcnt = pcnt;
228 g3d_context_update_progress_bar(context, pcnt, TRUE);
229 }
230#endif
231 g3d_context_update_interface(context);
232 } /* !eof(stream) */
233 return TRUE;
234}
235
236EAPI
237gchar *plugin_description(void)
238{
239 return g_strdup("Maya .obj models.");
240}
241
242EAPI
243gchar **plugin_extensions(void)
244{
245 return g_strsplit("obj", ":", 0);
246}
247
248/*****************************************************************************/
249
250/*****************************************************************************/
251/* material file ops */
252/*****************************************************************************/
253
254int obj_tryloadmat(G3DModel *model, const char *filename)
255{
256 FILE *f;
257 G3DMaterial *material = NULL;
258
259 f = fopen(filename, "r");
260 if(f == NULL) {
261#if DEBUG > 1
262 g_warning("obj_tryloadmat: loading '%s' failed: %s", filename,
263 strerror(errno));
264#endif
265 return FALSE;
266 }
267#if DEBUG > 0
268 g_debug("loading material library %s", filename);
269#endif
270 while(!feof(f)) {
271 char line[2048];
272 float r,g,b, t1,t2, ni;
273 int tf, ns, il;
274
275 fgets(line, 2048, f);
276 g_strstrip(line);
277 if(strlen(line))
278 {
279 char mname[128];
280
281 if(line[0] == '#') continue; /* comments */
282 if(line[0] == '\n') continue; /* empty lines */
283
284 if(sscanf(line, "newmtl %s", mname) == 1)
285 {
286 /* new material */
287 material = g3d_material_new();
288 material->name = g_strdup(mname);
289 model->materials = g_slist_append(model->materials, material);
290 }
291 else if(sscanf(line, " Kd %f %f %f", &r, &g, &b) == 3)
292 {
293 /* material color? */
294 if(material != NULL)
295 {
296 material->r = r;
297 material->g = g;
298 material->b = b;
299 }
300 }
301 else if(sscanf(line, " Ks %f %f %f", &r, &g, &b) == 3)
302 {
303 /* ?? */
304 }
305 else if(sscanf(line, " Tf %f %f %d", &t1, &t2, &tf) == 3)
306 {
307 /* transparency ?? */
308 if(material != NULL)
309 {
310 if(tf == 1) material->a = 1.0 - t1;
311 }
312 }
313 else if(sscanf(line, " Ns %d Ni %f", &ns, &ni) == 2)
314 {
315 /* ?? */
316 }
317 else if(sscanf(line, " illum %d", &il) == 1)
318 {
319 /* ?? */
320 }
321 else {
322#if DEBUG > 0
323 g_warning("unknown type of line: %s", line);
324#endif
325 }
326 }
327 } /* !feof */
328 return TRUE;
329}
330
331G3DMaterial *obj_usemat(G3DModel *model, const gchar *matname)
332{
333 /* sets new active material from named list */
334 GSList *mlist = model->materials;
335 while(mlist != NULL)
336 {
337 G3DMaterial *mat = (G3DMaterial*)mlist->data;
338 if(strcmp(matname, mat->name) == 0)
339 {
340 return mat;
341 }
342 mlist = mlist->next;
343 }
344
345 return NULL;
346}
347
348static G3DObject *obj_object_by_name(G3DModel *model, const gchar *name)
349{
350 G3DObject *object;
351 G3DMaterial *material;
352 GSList *oitem;
353
354#if DEBUG > 4
355 g_debug("looking for object '%s'", name);
356#endif
357
358 for(oitem = model->objects; oitem != NULL; oitem = oitem->next) {
359 object = oitem->data;
360 if(strcmp(object->name, name) == 0)
361 return object;
362 }
363
364 material = g3d_material_new();
365 material->name = g_strdup("(default material)");
366
367 object = g_new0(G3DObject, 1);
368 object->name = g_strdup(name);
369 object->materials = g_slist_append(object->materials, material);
370 model->objects = g_slist_append(model->objects, object);
371
372 return object;
373}
374
375#if OBJ_USE_GROUPING
376static G3DObject *obj_get_offset(GSList *group_list, guint32 *voffp,
377 guint32 index, G3DObject *defobj)
378{
379 GSList *leitem, *gitem;
380 ObjGroupOffset *grpoff;
381
382 for(leitem = gitem = group_list; gitem != NULL; gitem = gitem->next) {
383 grpoff = gitem->data;
384
385 /* this one is too big */
386 if(grpoff->goff > index) {
387 grpoff = leitem->data;
388 *voffp = grpoff->ooff - grpoff->goff;
389#if DEBUG > 0
390 g_debug("[o]: i=%-6d, go=%-6d, oo=%-6d, vo=%-6d (%s, %d vtxs)",
391 index, (guint32)grpoff->goff, (guint32)grpoff->ooff, *voffp,
392 grpoff->object->name, grpoff->object->vertex_count);
393#endif
394 return grpoff->object;
395 }
396 leitem = gitem;
397 }
398
399 *voffp = 0;
400 return defobj;
401}
402#endif
403