#include #include #include #include #include #include #include G3DObject *obj_createobject(G3DModel *model, const char *name); int obj_tryloadmat(G3DModel *model, const char *filename); int plugin_load(const char *filename, G3DModel *model) { FILE *f; char line[2048], oname[128], matname[128], matfile[1024]; G3DObject *object = NULL; G3DMaterial *material = NULL; double x,y,z; #if 0 unsigned int v1,v2,v3,v4, vd; #endif int num_v, v_off = 1, v_cnt = 0; setlocale(LC_NUMERIC, "C"); g_return_val_if_fail(model != NULL, EXIT_FAILURE); f = fopen(filename, "r"); if(f == NULL) { g_warning("can't open file '%s'", filename); return EXIT_FAILURE; } strncpy(matfile, filename, strlen(filename) - 3); matfile[strlen(filename)-3] = '\0'; strcat(matfile, "mtl"); obj_tryloadmat(model, matfile); object = obj_createobject(model, "(default)"); while(!feof(f)) { fgets(line, 2048, f); g_strchomp(line); if(strlen(line) > 0) { switch(line[0]) { case '#': case '\n': continue; break; case 'g': /* object */ if(strlen(line) == 1) { } else if(sscanf(line, "g %s", oname) == 1) { #if 0 object = obj_createobject(model, oname); v_off += v_cnt; v_cnt = 1; #endif } else g_printerr("parse error in line: %s\n", line); break; case 'v': /* vertex */ if(strncmp(line, "vn ", 3) == 0) { /* normal ? */ } else if(strncmp(line, "vt ", 3) == 0) { /* ?? */ } else if(sscanf(line, "v %lf %lf %lf", &x, &y, &z) == 3) { if(object == NULL) { object = obj_createobject(model, "(noname)"); } object->vertex_count++; object->vertices = g_realloc(object->vertices, object->vertex_count * 3 * sizeof(GLfloat)); object->vertices[v_cnt*3+0] = x; object->vertices[v_cnt*3+1] = y; object->vertices[v_cnt*3+2] = z; v_cnt++; } else g_printerr("parse error in line: %s\n", line); break; case 'f': /* face */ if(strncmp("f ", line, 2) == 0) { G3DFace *face; gchar **vertex, **vstrs = g_strsplit(line, " ", 0); int i; num_v = 0; if(object == NULL) { g_printerr("error: face before object\n"); fclose(f); return EXIT_FAILURE; } face = g_new0(G3DFace, 1); if(material != NULL) face->material = material; else face->material = g_slist_nth_data(object->materials, 0); /* find number of vertices in line */ vertex = vstrs; while(*vertex != NULL) { num_v++; vertex++; } face->num_vertices = num_v - 1; /* next one if # of vertices < 3 */ if(face->num_vertices < 3) continue; /* read vertices */ face->index_vertex = g_malloc((num_v-1) * sizeof(int)); for(i=1; iindex_vertex[i-1] = index - v_off; } g_strfreev(vstrs); object->faces = g_slist_prepend(object->faces, face); } else g_printerr("parse error in line: %s\n", line); break; case 'u': /* usemat? */ case 'm': case 's': if(sscanf(line, "usemtl %s", matname) == 1) { /* sets new active material from named list */ GSList *mlist = model->materials; while(mlist != NULL) { G3DMaterial *mat = (G3DMaterial*)mlist->data; if(strcmp(matname, mat->name) == 0) { material = mat; break; } mlist = mlist->next; } } else if(sscanf(line, "mtllib %s", matfile) == 1) { /* loads external material library */ if(obj_tryloadmat(model, matfile) != EXIT_SUCCESS) { g_printerr("error loading material library '%s'\n", matfile); } } break; default: g_printerr("unknown type of line: %s\n", line); } } } fclose(f); return EXIT_SUCCESS; } char *plugin_description(void) { return g_strdup( "Import plugin for Maya .obj files\n"); } char **plugin_extensions(void) { return g_strsplit("obj", ":", 0); } /*****************************************************************************/ G3DObject *obj_createobject(G3DModel *model, const char *name) { G3DObject *object; G3DMaterial *material = g3d_new_G3DMaterial(); object = g_new0(G3DObject, 1); object->name = g_strdup(name); model->objects = g_slist_append(model->objects, object); object->materials = g_slist_append(object->materials, material); return object; } /*****************************************************************************/ /* material file ops */ /*****************************************************************************/ int obj_tryloadmat(G3DModel *model, const char *filename) { FILE *f; G3DMaterial *material = NULL; f = fopen(filename, "r"); if(f == NULL) { #if DEBUG > 1 g_printerr("obj_tryloadmat: loading '%s' failed: %s\n", filename, strerror(errno)); #endif return EXIT_FAILURE; } #if DEBUG > 0 g_printerr("loading material library %s\n", filename); #endif while(!feof(f)) { char line[2048]; float r,g,b, t1,t2, ni; int tf, ns, il; fgets(line, 2048, f); if(strlen(line)) { char mname[128]; if(line[0] == '#') continue; /* comments */ if(line[0] == '\n') continue; /* empty lines */ if(sscanf(line, "newmtl %s", mname) == 1) { /* new material */ material = g3d_new_G3DMaterial(); material->name = g_strdup(mname); model->materials = g_slist_append(model->materials, material); } else if(sscanf(line, " Kd %f %f %f", &r, &g, &b) == 3) { /* material color? */ if(material != NULL) { material->r = r; material->g = g; material->b = b; } } else if(sscanf(line, " Ks %f %f %f", &r, &g, &b) == 3) { /* ?? */ } else if(sscanf(line, " Tf %f %f %d", &t1, &t2, &tf) == 3) { /* transparency ?? */ if(material != NULL) { if(tf == 1) material->a = 1.0 - t1; } } else if(sscanf(line, " Ns %d Ni %f", &ns, &ni) == 2) { /* ?? */ } else if(sscanf(line, " illum %d", &il) == 1) { /* ?? */ } else { g_printerr("unknown type of line: %s", line); } } } return EXIT_SUCCESS; }