diff options
Diffstat (limited to 'obj.c')
-rw-r--r-- | obj.c | 206 |
1 files changed, 154 insertions, 52 deletions
@@ -12,6 +12,7 @@ * */ +#include <GL/glew.h> #include <stdlib.h> #include <stdio.h> #include <memory.h> @@ -19,18 +20,24 @@ ObjModel* ObjLoadModel(char *memory, size_t size) { - char *p = NULL, *e = NULL; - ObjModel *ret = (ObjModel *) calloc(1, sizeof(ObjModel)); - /* initialize to zero */ - memset(ret, 0, sizeof(ObjModel)); - /* if size is 0, meaning file was not loaded correctly, return null */ if (!size) - return ret; + return NULL; + char *p = NULL, *e = NULL; + ObjModel *ret = (ObjModel *) malloc(sizeof(ObjModel)); + if (!ret) + { + fprintf(stderr, "ObjLoadModel() failed, %s:%d\n", __FILE__, __LINE__); + perror("malloc"); + exit(-1); + } + + /* initialize to zero */ + memset(ret, 0, sizeof(ObjModel)); p = memory; e = memory + size; - + /* count the number of normals, texcoords, vertices, and faces, line by line */ while (p != e) { @@ -39,87 +46,114 @@ ObjModel* ObjLoadModel(char *memory, size_t size) else if (memcmp(p, "v", 1) == 0) ret->nVertex++; else if (memcmp(p, "f", 1) == 0) ret->nFace++; - while (*p++ != (char) 0x0a); + /* seek to new line */ + while (*p++ != (char) 0x0a) + ; } /* allocate memory for arrays */ ret->VertexArray = (ObjVertex *) malloc(sizeof(ObjVertex) * ret->nVertex); ret->NormalArray = (ObjNormal *) malloc(sizeof(ObjNormal) * ret->nNormal); ret->TexCoordArray = (ObjTexCoord *) malloc(sizeof(ObjTexCoord) * ret->nTexCoord); - ret->FaceArray = (ObjFace *) malloc(sizeof(ObjFace) * ret->nFace); - ret->mtllib = (char *) malloc(sizeof(char) * 21); - ret->objectName = (char *) malloc(sizeof(char) * 21); - ret->usemtl = (char *) malloc(sizeof(char) * 21); + ret->FaceArray = (ObjFace *) malloc(sizeof(ObjFace) * ret->nFace); + ret->mtllib = (char *) malloc(sizeof(char) * 21); + ret->objectName = (char *) malloc(sizeof(char) * 21); + ret->usemtl = (char *) malloc(sizeof(char) * 21); + + *ret->mtllib = '\0'; + *ret->objectName = '\0'; + *ret->usemtl = '\0'; + + if (!ret->VertexArray || !ret->NormalArray || !ret->TexCoordArray || + !ret->FaceArray || !ret->mtllib || !ret->objectName || !ret->usemtl) + { + fprintf(stderr, "ObjLoadModel() failed, %s:%d\n", __FILE__, __LINE__); + perror("malloc"); + exit(-1); + } + +#if 0 /* already done by memset */ memset(ret->mtllib, 0, 21); memset(ret->objectName, 0, 21); memset(ret->usemtl, 0, 21); +#endif p = memory; - - int nV = 0, nN = 0, nT = 0, nF = 0; - int nread = 0; - + + unsigned int nV = 0, nN = 0, nT = 0, nF = 0; + unsigned int nread = 0; + while (p != e) { /* check for mtl file */ if (memcmp(p, "mtllib", 6) == 0) sscanf(p, "mtllib %s", ret->mtllib); - /* check if mtl file will be used*/ + /* check if mtl file will be used */ if (memcmp(p, "usemtl", 6) == 0) sscanf(p, "usemtl %s", ret->usemtl); if (memcmp(p, "g", 1) == 0) sscanf(p, "g %s", ret->objectName); - + + /* parse a normal */ if (memcmp(p, "vn", 2) == 0) { nread = sscanf(p, "vn %f %f %f", &ret->NormalArray[nN].x, - &ret->NormalArray[nN].y, - &ret->NormalArray[nN].z); + &ret->NormalArray[nN].y, + &ret->NormalArray[nN].z); if (nread != 3) printf("vn: read only %d instead of 3\n", nread); + nN++; } + /* parse a texture coordinates */ else if (memcmp(p, "vt", 2) == 0) { nread = sscanf(p, "vt %f %f", &ret->TexCoordArray[nT].u, - &ret->TexCoordArray[nT].v); + &ret->TexCoordArray[nT].v); if (nread != 2) - printf("vt: read only %d instead of 2\n", nread); + printf("vt: read only %d instead of 2\n", nread); + nT++; } + /* parse a vertex */ else if (memcmp(p, "v", 1) == 0) /* or *p == 'v' */ { nread = sscanf(p, "v %f %f %f", &ret->VertexArray[nV].x, - &ret->VertexArray[nV].y, - &ret->VertexArray[nV].z); + &ret->VertexArray[nV].y, + &ret->VertexArray[nV].z); if (nread != 3) printf("v: read only %d instead of 3\n", nread); + nV++; } /* quad */ else if (memcmp(p, "f", 1) == 0) /* or *p == 'f' */ { nread = sscanf(p, "f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d", - &ret->FaceArray[nF].Vertex[0], - &ret->FaceArray[nF].TexCoord[0], - &ret->FaceArray[nF].Normal[0], - &ret->FaceArray[nF].Vertex[1], - &ret->FaceArray[nF].TexCoord[1], - &ret->FaceArray[nF].Normal[1], - &ret->FaceArray[nF].Vertex[2], - &ret->FaceArray[nF].TexCoord[2], - &ret->FaceArray[nF].Normal[2], - &ret->FaceArray[nF].Vertex[3], - &ret->FaceArray[nF].TexCoord[3], - &ret->FaceArray[nF].Normal[3]); + &ret->FaceArray[nF].Vertex[0], + &ret->FaceArray[nF].TexCoord[0], + &ret->FaceArray[nF].Normal[0], + &ret->FaceArray[nF].Vertex[1], + &ret->FaceArray[nF].TexCoord[1], + &ret->FaceArray[nF].Normal[1], + &ret->FaceArray[nF].Vertex[2], + &ret->FaceArray[nF].TexCoord[2], + &ret->FaceArray[nF].Normal[2], + &ret->FaceArray[nF].Vertex[3], + &ret->FaceArray[nF].TexCoord[3], + &ret->FaceArray[nF].Normal[3]); + if (nread != 12) - printf("f: read only %d instead of 12\n", nread); + printf("f: read only %d instead of 12\n", nread); + nF++; } + /* seek to a newline */ - while (*p++ != (char) 0x0a); + while (*p++ != (char) 0x0a) + ; } /* sanity check */ @@ -136,7 +170,7 @@ ObjModel* ObjLoadModel(char *memory, size_t size) if (ret->nFace != nF) fprintf(stdout, "faces: scanned %d, read %d\n", ret->nFace, nF); } - + /* load the mtl file */ if (ret->mtllib != NULL && ret->usemtl) { @@ -149,13 +183,27 @@ ObjModel* ObjLoadModel(char *memory, size_t size) if (mtl_bytes) { - ObjMtl *mtl = (ObjMtl *) calloc(1, sizeof(ObjMtl)); + ObjMtl *mtl = (ObjMtl *) malloc(sizeof(ObjMtl)); + if (!mtl) + { + fprintf(stderr, "ObjLoadModel() failed, %s:%d\n", __FILE__, __LINE__); + perror("malloc"); + exit(-1); + } + /* initialize to zero */ memset(mtl, 0, sizeof(ObjMtl)); /* allocate space for dynamic members */ mtl->map_Ka = (char *) malloc(sizeof(char) * 21); mtl->map_Kd = (char *) malloc(sizeof(char) * 21); + if (!mtl->map_Ka || !mtl->map_Kd) + { + fprintf(stderr, "ObjLoadModel() failed, %s:%d\n", __FILE__, __LINE__); + perror("malloc"); + exit(-1); + } + *mtl->map_Ka = '\0'; *mtl->map_Kd = '\0'; @@ -165,7 +213,8 @@ ObjModel* ObjLoadModel(char *memory, size_t size) while (st != ed) { /* skip spaces */ - while (*st++ == (char) 0x20); + while (*st++ == (char) 0x20) + ; if (memcmp(st, "Ns", 2) == 0) sscanf(st, "Ns %f", &mtl->Ns); @@ -204,16 +253,18 @@ ObjModel* ObjLoadModel(char *memory, size_t size) sscanf(st, "map_Kd %s", mtl->map_Kd); /* go to next line */ - while (*st++ != (char) 0x0a); + while (*st++ != (char) 0x0a) + ; } /* set the mtl */ ret->mtl = mtl; } else - ret->mtl = NULL; + ret->mtl = NULL; /* should already be NULL but what the hell */ - free(fname); - } + if (fname) + free(fname); + } return ret; } @@ -230,13 +281,16 @@ size_t ObjLoadFile(char *szFileName, char **memory) size_t end = ftell(file); fseek(file, 0, SEEK_SET); - *memory = (char *) malloc(end); + *memory = (char *) malloc(sizeof(char) * end); bytes = fread(*memory, sizeof(char), end, file); fclose(file); } else - perror("fopen"); + { + fprintf(stderr, "ObjLoadModel() failed, %s:%d\n", __FILE__, __LINE__); + perror("fopen"); + } return bytes; } @@ -259,7 +313,7 @@ void ObjList(ObjModel *model) for (i = 0; i < model->nTexCoord; i++) printf("v %f %f\n", model->TexCoordArray[i].u, model->TexCoordArray[i].v); - printf("%d faces\n", model->nFace); + printf("%d faces\n", model->nFace); for (i = 0; i < model->nFace; i++) { printf("f %d/%d/%d %d/%d/%d %d/%d/%d %d/%d/%d\n", @@ -283,7 +337,7 @@ char *ObjGetPath(char *fname) if (obj_last_fname == NULL) return NULL; - char *path = (char *) malloc(sizeof(char) * 31); + char *path = (char *) malloc(sizeof(char) * 101); char *delimeter = strrchr(obj_last_fname, '/'); unsigned int offset = delimeter - obj_last_fname; strncpy(path, obj_last_fname, offset + 1); @@ -292,8 +346,53 @@ char *ObjGetPath(char *fname) return path; } +void ObjPutFaceGLCmd(const ObjModel *model, const unsigned i) +{ + if (!model) + return; + + glNormal3f(model->NormalArray[model->FaceArray[i].Normal[0] - 1].x, + model->NormalArray[model->FaceArray[i].Normal[0] - 1].y, + model->NormalArray[model->FaceArray[i].Normal[0] - 1].z ); + glTexCoord2f(model->TexCoordArray[model->FaceArray[i].TexCoord[0] - 1].u, + model->TexCoordArray[model->FaceArray[i].TexCoord[0] - 1].v); + glVertex3f(model->VertexArray[model->FaceArray[i].Vertex[0] - 1].x, + model->VertexArray[model->FaceArray[i].Vertex[0] - 1].y, + model->VertexArray[model->FaceArray[i].Vertex[0] - 1].z ); + + glNormal3f(model->NormalArray[model->FaceArray[i].Normal[1] - 1].x, + model->NormalArray[model->FaceArray[i].Normal[1] - 1].y, + model->NormalArray[model->FaceArray[i].Normal[1] - 1].z ); + glTexCoord2f(model->TexCoordArray[model->FaceArray[i].TexCoord[1] - 1].u, + model->TexCoordArray[model->FaceArray[i].TexCoord[1] - 1].v); + glVertex3f(model->VertexArray[model->FaceArray[i].Vertex[1] - 1].x, + model->VertexArray[model->FaceArray[i].Vertex[1] - 1].y, + model->VertexArray[model->FaceArray[i].Vertex[1] - 1].z ); + + glNormal3f(model->NormalArray[model->FaceArray[i].Normal[2] - 1].x, + model->NormalArray[model->FaceArray[i].Normal[2] - 1].y, + model->NormalArray[model->FaceArray[i].Normal[2] - 1].z ); + glTexCoord2f(model->TexCoordArray[model->FaceArray[i].TexCoord[2] - 1].u, + model->TexCoordArray[model->FaceArray[i].TexCoord[2] - 1].v); + glVertex3f(model->VertexArray[model->FaceArray[i].Vertex[2] - 1].x, + model->VertexArray[model->FaceArray[i].Vertex[2] - 1].y, + model->VertexArray[model->FaceArray[i].Vertex[2] - 1].z ); + + glNormal3f(model->NormalArray[model->FaceArray[i].Normal[3] - 1].x, + model->NormalArray[model->FaceArray[i].Normal[3] - 1].y, + model->NormalArray[model->FaceArray[i].Normal[3] - 1].z ); + glTexCoord2f(model->TexCoordArray[model->FaceArray[i].TexCoord[3] - 1].u, + model->TexCoordArray[model->FaceArray[i].TexCoord[3] - 1].v); + glVertex3f(model->VertexArray[model->FaceArray[i].Vertex[3] - 1].x, + model->VertexArray[model->FaceArray[i].Vertex[3] - 1].y, + model->VertexArray[model->FaceArray[i].Vertex[3] - 1].z ); +} + void ObjFree(ObjModel *model) { + if (model == NULL) + return; + free(model->NormalArray); free(model->TexCoordArray); free(model->FaceArray); @@ -302,9 +401,12 @@ void ObjFree(ObjModel *model) free(model->objectName); free(model->usemtl); - free(model->mtl->map_Ka); - free(model->mtl->map_Kd); - free(model->mtl); + if (model->mtl) + { + free(model->mtl->map_Ka); + free(model->mtl->map_Kd); + free(model->mtl); + } free(model); } |