#include #include #include #include #include #include #include #include /*****************************************************************************/ /* plugin interface */ /*****************************************************************************/ #define NFF_SEC_NOSECTION 0 #define NFF_SEC_VIEWPOINT 1 #define NFF_SEC_BGCOLOR 2 #define NFF_SEC_POSLIGHT 3 #define NFF_SEC_MATERIAL 4 #define NFF_SEC_CONECYL 5 #define NFF_SEC_SPHERE 6 #define NFF_SEC_POLYGON 7 #define NFF_SEC_POLPATCH 8 int nff_readline(FILE *f, char *line, int maxlen); int plugin_load(const char *filename, G3DModel *model) { FILE *f; char line[1024]; G3DObject *object; G3DMaterial *material = NULL; int section = NFF_SEC_NOSECTION; GLfloat r,g,b, Kd, Ks, Sh, T, refr; GLfloat v1,v2,v3, n1,n2,n3; int i, num; 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; } object = g_new0(G3DObject, 1); object->name = g_strdup("NFF Object"); model->objects = g_slist_append(model->objects, object); while(nff_readline(f, line, 1024) == EXIT_SUCCESS) { #if DEBUG > 3 g_printerr("DEBUG: %s\n", line); #endif if(strcmp(line, "v") == 0) { section = NFF_SEC_VIEWPOINT; } else if(sscanf(line, "b %g %g %g", &r, &g, &b) == 3) { model->bgcolor[0] = r; model->bgcolor[1] = g; model->bgcolor[2] = b; } else if(sscanf(line, "f %g %g %g %g %g %g %g %g", &r, &g, &b, &Kd, &Ks, &Sh, &T, &refr) == 8) { char name[128]; material = g3d_new_G3DMaterial(); material->r = r; material->g = g; material->b = b; material->a = 1.0 - T; material->shininess = Sh; material->specular[0] = r * Ks; material->specular[1] = g * Ks; material->specular[2] = b * Ks; if(T > 0) material->flags |= G3D_FLAG_MAT_TWOSIDE; object->materials = g_slist_append(object->materials, material); g_snprintf(name, 128, "material #%d", g_slist_length(object->materials)); material->name = g_strdup(name); } else if((sscanf(line, "pp %d", &num) == 1) || (sscanf(line, "p %d", &num) == 1)) { G3DFace *face = g_new0(G3DFace, 1); if(strncmp(line, "pp", 2) == 0) section = NFF_SEC_POLPATCH; else section = NFF_SEC_POLYGON; object->vertex_count += num; object->vertices = g_realloc(object->vertices, object->vertex_count * 3 * sizeof(GLfloat)); face->material = material; face->num_vertices = num; face->index_vertex = g_malloc0(num * sizeof(int)); object->faces = g_slist_prepend(object->faces, face); if(section == NFF_SEC_POLPATCH) { face->flags |= G3D_FLAG_FAC_NORMALS; face->normals = g_malloc0(num * 3 * sizeof(GLfloat)); } /* most faces are in this direction, but there are wrong models */ for(i=num-1; i>=0; i--) { if(nff_readline(f, line, 1024) != EXIT_SUCCESS) { fclose(f); g_printerr("reading vertices failed\n"); return EXIT_FAILURE; } if((section == NFF_SEC_POLPATCH) && (sscanf(line, "%g %g %g %g %g %g", &v1,&v2,&v3, &n1,&n2,&n3) == 6)) { int index = object->vertex_count - num + i; object->vertices[index*3+0] = v1; object->vertices[index*3+1] = v2; object->vertices[index*3+2] = v3; face->index_vertex[i] = index; face->normals[i*3+0] = -n1; face->normals[i*3+1] = -n2; face->normals[i*3+2] = -n3; } else if(sscanf(line, "%g %g %g", &v1,&v2,&v3) == 3) { int index = object->vertex_count - num + i; object->vertices[index*3+0] = v1; object->vertices[index*3+1] = v2; object->vertices[index*3+2] = v3; face->index_vertex[i] = index; } else g_printerr("error in line '%s'\n", line); } } } fclose(f); return EXIT_SUCCESS; } char *plugin_description(void) { return g_strdup( "Neutral File Format import plugin\n"); } char **plugin_extensions(void) { return g_strsplit("nff", ":", 0); } /*****************************************************************************/ /* private functions */ /*****************************************************************************/ int nff_readline(FILE *f, char *line, int maxlen) { if(fgets(line, maxlen, f) == NULL) return EXIT_FAILURE; g_strstrip(line); if((strlen(line) == 0) || (line[0] == '#')) { /* get next line if empty or comment */ return nff_readline(f, line, maxlen); } return EXIT_SUCCESS; }