/* * Sample BMF file reader (from view3ds by David Farrell) */ #include #include #include #ifdef WIN32 #include #endif #include "GL/glut.h" #include "bmf.h" #include "ou.h" GLubyte *read_JPEG_file(char *, int *, int *, int *); char modelspath[100] = MODEL_DIR; BMFObject *LoadBMF(char *filename, double radius) { uword MeshType; SparseMesh *MaterialList; StripMesh *StripMaterialList; BMFObject *obj; FILE *in; int i, j; int width, height, components; GLubyte *image; char s[120]; /* openuniverse */ double max = 0.0, d; /* openuniverse */ /* Create the new BMF object */ if (!(obj = (BMFObject *) malloc(sizeof(BMFObject)))) { error("Can't allocate memory for BMFObject\n"); shutdown(1); } sprintf(s, "%s/%s", modelspath, filename); if (!(in = fopen(s, "rb"))) { sprintf(s, "Can't open file %s", filename); error("Can't open file\n"); shutdown(1); } obj->texsize = 0; /* Get number of materials */ fread(&obj->NumMaterials, sizeof(uword), 1, in); /* Get mesh type */ fread(&MeshType, sizeof(uword), 1, in); if (MeshType == 0) { /* Sparse Triangles */ /* Allocate space for the materials */ if (! (MaterialList = (SparseMesh *) malloc(sizeof(SparseMesh) * obj->NumMaterials))) { error("Can't allocate memory for materials\n"); shutdown(1); } obj->sparse = MaterialList; obj->strip = 0; /* Read in each material */ for (i = 0; i < obj->NumMaterials; i++) { /* Get the texture's name length */ fread(&MaterialList[i].texture_name_length, sizeof(uword), 1, in); if (MaterialList[i].texture_name_length == 0) { error("Invalid texture name length\n"); shutdown(1); } /* Get the texture's name */ MaterialList[i].texture_name = (char *) malloc(MaterialList[i].texture_name_length); fread(MaterialList[i].texture_name, MaterialList[i].texture_name_length, 1, in); if (MaterialList[i].texture_name_length > 1) { for (j = 0; j < MaterialList[i].texture_name_length; j++) MaterialList[i].texture_name[j] = (char) tolower(MaterialList[i].texture_name[j]); image = read_JPEG_file(MaterialList[i].texture_name, &width, &height, &components); if (image == NULL) { sprintf(s, "reading image %s", MaterialList[i].texture_name); error(s); shutdown(1); } image = texture_LOD(image, &width, &height, components); if (components == 1) j = 1; else j = color_depth / 8; obj->texsize += (width * height * j); glGenTextures(1, &MaterialList[i].texbind); glBindTexture(GL_TEXTURE_2D, MaterialList[i].texbind); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexImage2D(GL_TEXTURE_2D, 0, components == 3 ? cd_rgb : cd_lum, width, height, 0, components == 3 ? GL_RGB : GL_LUMINANCE, GL_UNSIGNED_BYTE, image); free(image); } /* Read in RGB colors */ fread(&MaterialList[i].ambient, sizeof(BMF_RGBCOLOR), 1, in); fread(&MaterialList[i].diffuse, sizeof(BMF_RGBCOLOR), 1, in); fread(&MaterialList[i].specular, sizeof(BMF_RGBCOLOR), 1, in); /* Get the number of vertices */ fread(&MaterialList[i].number_of_vertices, sizeof(uword), 1, in); /* Allocate space for the vertex list */ MaterialList[i].vertexlist = (BMF_UNVERTEX *) malloc(sizeof(BMF_UNVERTEX) * MaterialList[i].number_of_vertices); if (MaterialList[i].vertexlist == 0) { error("Error allocating memory for vertexlist\n"); shutdown(1); } /* Read in the vertex list */ fread(MaterialList[i].vertexlist, sizeof(BMF_UNVERTEX), MaterialList[i].number_of_vertices, in); for (j = 0; j < MaterialList[i].number_of_vertices; j++) { d = DISTANCE(MaterialList[i].vertexlist[j].x, MaterialList[i].vertexlist[j].y, MaterialList[i].vertexlist[j].z); if (d > max) max = d; } /* Read in the number of polygons */ fread(&MaterialList[i].number_of_triangles, sizeof(uword), 1, in); /* Allocate space for the index list */ MaterialList[i].indexlist = (BMF_SURFACE *) malloc(sizeof(BMF_SURFACE) * MaterialList [i].number_of_triangles); /* Read in the triangle indices */ fread(MaterialList[i].indexlist, sizeof(BMF_SURFACE), MaterialList[i].number_of_triangles, in); } /* Sorta vertex normalization */ for (i = 0; i < obj->NumMaterials; i++) { for (j = 0; j < MaterialList[i].number_of_vertices; j++) { MaterialList[i].vertexlist[j].x /= max / radius; MaterialList[i].vertexlist[j].y /= max / radius; MaterialList[i].vertexlist[j].z /= max / radius; } } } else { /* Triangle Strips */ /* Allocate space for the materials */ if (! (StripMaterialList = (StripMesh *) malloc(sizeof(StripMesh) * obj->NumMaterials))) { error("Can't allocate memory for materials\n"); shutdown(1); } obj->sparse = 0; obj->strip = StripMaterialList; /* Read in each material */ for (i = 0; i < obj->NumMaterials; i++) { /* Get the texture's name length */ fread(&StripMaterialList[i].texture_name_length, sizeof(uword), 1, in); if (StripMaterialList[i].texture_name_length == 0) { error("Invalid texture name length\n"); shutdown(1); } /* Get the texture's name */ StripMaterialList[i].texture_name = (char *) malloc(StripMaterialList[i].texture_name_length); fread(StripMaterialList[i].texture_name, StripMaterialList[i].texture_name_length, 1, in); if (StripMaterialList[i].texture_name_length > 1) { for (j = 0; j < StripMaterialList[i].texture_name_length; j++) StripMaterialList[i].texture_name[j] = (char) tolower(StripMaterialList[i].texture_name[j]); image = read_JPEG_file(StripMaterialList[i].texture_name, &width, &height, &components); if (image == NULL) { sprintf(s, "error reading image %s", StripMaterialList[i].texture_name); error(s); shutdown(1); } image = texture_LOD(image, &width, &height, components); if (components == 1) j = 1; else j = color_depth / 8; obj->texsize += (width * height * j); glGenTextures(1, &StripMaterialList[i].texbind); glBindTexture(GL_TEXTURE_2D, StripMaterialList[i].texbind); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexImage2D(GL_TEXTURE_2D, 0, components == 3 ? cd_rgb : cd_lum, width, height, 0, components == 3 ? GL_RGB : GL_LUMINANCE, GL_UNSIGNED_BYTE, image); free(image); } /* Read in RGB colors */ fread(&StripMaterialList[i].ambient, sizeof(BMF_RGBCOLOR), 1, in); fread(&StripMaterialList[i].diffuse, sizeof(BMF_RGBCOLOR), 1, in); fread(&StripMaterialList[i].specular, sizeof(BMF_RGBCOLOR), 1, in); /* Get the number of vertices */ fread(&StripMaterialList[i].number_of_vertices, sizeof(uword), 1, in); /* Allocate space for the vertex list */ StripMaterialList[i].vertexlist = (BMF_UNVERTEX *) malloc(sizeof(BMF_UNVERTEX) * StripMaterialList [i].number_of_vertices); if (StripMaterialList[i].vertexlist == 0) { error("Error allocating memory for vertexlist\n"); shutdown(1); } /* Read in the vertex list */ fread(StripMaterialList[i].vertexlist, sizeof(BMF_UNVERTEX), StripMaterialList[i].number_of_vertices, in); for (j = 0; j < StripMaterialList[i].number_of_vertices; j++) { d = DISTANCE(StripMaterialList[i].vertexlist[j].x, StripMaterialList[i].vertexlist[j].y, StripMaterialList[i].vertexlist[j].z); if (d > max) max = d; } /* Read in the number of strips */ fread(&StripMaterialList[i].number_of_strips, sizeof(uword), 1, in); /* Allocate space for the strip length list */ StripMaterialList[i].length_of_strip = (uword *) malloc(sizeof(uword) * StripMaterialList[i].number_of_strips); /* Read in the triangle strip lengths */ fread(StripMaterialList[i].length_of_strip, sizeof(uword), StripMaterialList[i].number_of_strips, in); /* Read in the number of strip points */ fread(&StripMaterialList[i].number_of_strip_indices, sizeof(uword), 1, in); /* Allocate space for the strip length list */ StripMaterialList[i].stripindex = (uword *) malloc(sizeof(uword) * StripMaterialList [i].number_of_strip_indices); /* Read in the triangle strip lengths */ fread(StripMaterialList[i].stripindex, sizeof(uword), StripMaterialList[i].number_of_strip_indices, in); } /* Sorta vertex normalization */ for (i = 0; i < obj->NumMaterials; i++) { for (j = 0; j < StripMaterialList[i].number_of_vertices; j++) { StripMaterialList[i].vertexlist[j].x /= max / radius; StripMaterialList[i].vertexlist[j].y /= max / radius; StripMaterialList[i].vertexlist[j].z /= max / radius; } } } fclose(in); obj->radius = radius; return obj; }