summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--obj.c232
-rw-r--r--obj.h10
-rw-r--r--objloader.c7
3 files changed, 177 insertions, 72 deletions
diff --git a/obj.c b/obj.c
index 576f89f..5ca1d4e 100644
--- a/obj.c
+++ b/obj.c
@@ -18,7 +18,7 @@
#include <memory.h>
#include "obj.h"
-char obj_last_fname[101];
+char ObjLastFname[101];
ObjModel* ObjLoadModel(char *memory, size_t size)
{
@@ -26,7 +26,6 @@ ObjModel* ObjLoadModel(char *memory, size_t size)
if (!size)
return NULL;
- char *p = NULL, *e = NULL;
ObjModel *ret = (ObjModel *) malloc(sizeof(ObjModel));
if (!ret)
{
@@ -37,16 +36,26 @@ ObjModel* ObjLoadModel(char *memory, size_t size)
/* initialize to zero */
memset(ret, 0, sizeof(ObjModel));
+
+ char *p = NULL, *e = NULL;
+ unsigned int line = 1;
p = memory;
e = memory + size;
/* count the number of normals, texcoords, vertices, and faces, line by line */
while (p != e)
{
- if (memcmp(p, "vn", 2) == 0) ret->nNormal++;
- else if (memcmp(p, "vt", 2) == 0) ret->nTexCoord++;
- else if (memcmp(p, "v", 1) == 0) ret->nVertex++;
- else if (memcmp(p, "f", 1) == 0) ret->nFace++;
+ /* skip commented lines */
+ if (memcmp(p, "#", 1) == 0)
+ ;
+ else if (memcmp(p, "vn", 2) == 0)
+ ret->nNormal++;
+ else if (memcmp(p, "vt", 2) == 0)
+ ret->nTexCoord++;
+ else if (memcmp(p, "v", 1) == 0)
+ ret->nVertex++;
+ else if (memcmp(p, "f", 1) == 0)
+ ret->nFace++;
/* seek to new line */
while (*p++ != (char) 0x0a)
@@ -54,10 +63,10 @@ ObjModel* ObjLoadModel(char *memory, size_t size)
}
/* allocate memory for arrays */
- ret->VertexArray = (ObjVertex *) malloc(sizeof(ObjVertex) * ret->nVertex);
- ret->NormalArray = (ObjNormal *) malloc(sizeof(ObjNormal) * ret->nNormal);
+ 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->FaceArray = (ObjFace *) malloc(sizeof(ObjFace) * ret->nFace);
ret->mtllib = (char *) malloc(sizeof(char) * 31);
ret->objectName = (char *) malloc(sizeof(char) * 31);
ret->usemtl = (char *) malloc(sizeof(char) * 31);
@@ -81,19 +90,19 @@ ObjModel* ObjLoadModel(char *memory, size_t size)
while (p != e)
{
+ /* skip commented lines */
+ if (memcmp(p, "#", 1) == 0)
+ ;
/* check for mtl file */
- if (memcmp(p, "mtllib", 6) == 0)
+ else if (memcmp(p, "mtllib", 6) == 0)
sscanf(p, "mtllib %s", ret->mtllib); /* valgrind reports this as false positive */
-
/* check if mtl file will be used */
- if (memcmp(p, "usemtl", 6) == 0)
+ else if (memcmp(p, "usemtl", 6) == 0)
sscanf(p, "usemtl %s", ret->usemtl);
-
- if (memcmp(p, "g", 1) == 0)
+ else if (memcmp(p, "g", 1) == 0)
sscanf(p, "g %s", ret->objectName);
-
/* parse a normal */
- if (memcmp(p, "vn", 2) == 0)
+ else if (memcmp(p, "vn", 2) == 0)
{
nread = sscanf(p, "vn %f %f %f", &ret->NormalArray[nN].x,
&ret->NormalArray[nN].y,
@@ -106,12 +115,13 @@ ObjModel* ObjLoadModel(char *memory, size_t size)
/* 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);
+ nread = sscanf(p, "vt %f %f", &ret->TexCoordArray[nT].s,
+ &ret->TexCoordArray[nT].t);
if (nread != 2)
printf("vt: read only %d instead of 2\n", nread);
- ret->TexCoordArray[nT].w = 0.0f;
+ ret->TexCoordArray[nT].r = 0.0f;
+ ret->TexCoordArray[nT].q = 1.0f;
nT++;
}
/* parse a vertex */
@@ -123,7 +133,7 @@ ObjModel* ObjLoadModel(char *memory, size_t size)
if (nread != 3)
printf("v: read only %d instead of 3\n", nread);
- ret->VertexArray[nV].w = 0.0f;
+ ret->VertexArray[nV].w = 1.0f;
nV++;
}
/* quad */
@@ -143,6 +153,20 @@ ObjModel* ObjLoadModel(char *memory, size_t size)
&ret->FaceArray[nF].TexCoord[3],
&ret->FaceArray[nF].Normal[3]);
+ /* obj file counts from 1, I want to count from 0 */
+ 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);
@@ -152,13 +176,15 @@ ObjModel* ObjLoadModel(char *memory, size_t size)
/* seek to a newline */
while (*p++ != (char) 0x0a)
;
+
+ line++;
}
/* sanity check */
if ((ret->nVertex != nV) || (ret->nNormal != nN) || (ret->nTexCoord != nT)
|| (ret->nFace != nF))
{
- fprintf(stdout, "ObjLoadModel: warning, the number of scanned items does not equal to number of read\n");
+ fprintf(stdout, "ObjLoadModel(): warning, the number of scanned items does not equal to number of read\n");
if (ret->nVertex != nV)
fprintf(stdout, "vertices: scanned %d, read %d\n", ret->nVertex, nV);
if (ret->nNormal != nN)
@@ -250,7 +276,7 @@ ObjModel* ObjLoadModel(char *memory, size_t size)
if (memcmp(st, "map_Kd", 6) == 0)
sscanf(st, "map_Kd %s", mtl->map_Kd);
- /* go to next line */
+ /* go to the next line */
while (*st++ != (char) 0x0a)
;
}
@@ -275,7 +301,7 @@ ObjModel* ObjLoadModel(char *memory, size_t size)
size_t ObjLoadFile(char *szFileName, char **memory)
{
- strcpy(obj_last_fname, szFileName); /* seems useful for tracking */
+ strcpy(ObjLastFname, szFileName); /* seems useful for tracking */
size_t bytes = 0;
FILE *file = fopen(szFileName, "rt");
@@ -323,7 +349,7 @@ void ObjList(ObjModel *model)
printf("%d texture coordinates\n", model->nTexCoord);
for (i = 0; i < model->nTexCoord; i++)
- printf("v %f %f\n", model->TexCoordArray[i].u, model->TexCoordArray[i].v);
+ printf("v %f %f\n", model->TexCoordArray[i].s, model->TexCoordArray[i].t);
printf("%d faces\n", model->nFace);
for (i = 0; i < model->nFace; i++)
@@ -346,7 +372,7 @@ void ObjList(ObjModel *model)
char *ObjGetPath(const char *fname)
{
- if (fname == NULL || obj_last_fname == NULL)
+ if (fname == NULL || ObjLastFname == NULL)
return NULL;
char *path = (char *) malloc(sizeof(char) * 101);
@@ -357,61 +383,137 @@ char *ObjGetPath(const char *fname)
exit(-1);
}
- char *delimeter = strrchr(obj_last_fname, '/');
- unsigned int offset = delimeter - obj_last_fname;
+ char *delimeter = strrchr(ObjLastFname, '/');
+ unsigned int offset = delimeter - ObjLastFname;
#if 0
fprintf(stdout, "ObjGetPath(): fname = \"%s\", delim = \"%s\", offset = %u"
- ", obj_last_fname = \"%s\"\n", fname, delimeter, offset, obj_last_fname);
+ ", ObjLastFname = \"%s\"\n", fname, delimeter, offset, ObjLastFname);
#endif
- strncpy(path, obj_last_fname, offset + 1);
+ strncpy(path, ObjLastFname, offset + 1);
strcpy(path + offset + 1, fname);
/* strcat(path, fname); */
return path;
}
-void ObjPutFaceGLCmd(const ObjModel *model, const unsigned i)
+void ObjSubmitIndexedVertexArrayQuad(const ObjModel *model)
+{
+ int i;
+
+ glVertexPointer(4, GL_FLOAT, 0, model->VertexArray);
+ glNormalPointer(GL_FLOAT, 0, model->NormalArray);
+
+ /* XXX: why aren't textcoords working :/ ? */
+ glTexCoordPointer(4, GL_FLOAT, 0, model->TexCoordArray);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ /* vertices */
+ for (i = 0; i < model->nFace; i++)
+ glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, model->FaceArray[i].Vertex);
+
+ /* normals */
+ for (i = 0; i < model->nFace; i++)
+ glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, model->FaceArray[i].Normal);
+
+ /* texture coordinates */
+ for (i = 0; i < model->nFace; i++)
+ glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, model->FaceArray[i].TexCoord);
+
+#if 0
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+#endif
+}
+
+/* OpenGL immediate command generator for quads */
+void ObjSubmitGLCommandsQuad(const ObjModel *model)
+{
+ if (!model)
+ return;
+
+ int i;
+ for (i = 0; i < model->nFace; i++)
+ {
+ glNormal3f(model->NormalArray[model->FaceArray[i].Normal[0]].x,
+ model->NormalArray[model->FaceArray[i].Normal[0]].y,
+ model->NormalArray[model->FaceArray[i].Normal[0]].z );
+ glTexCoord2f(model->TexCoordArray[model->FaceArray[i].TexCoord[0]].s,
+ model->TexCoordArray[model->FaceArray[i].TexCoord[0]].t);
+ glVertex3f(model->VertexArray[model->FaceArray[i].Vertex[0]].x,
+ model->VertexArray[model->FaceArray[i].Vertex[0]].y,
+ model->VertexArray[model->FaceArray[i].Vertex[0]].z );
+
+ glNormal3f(model->NormalArray[model->FaceArray[i].Normal[1]].x,
+ model->NormalArray[model->FaceArray[i].Normal[1]].y,
+ model->NormalArray[model->FaceArray[i].Normal[1]].z );
+ glTexCoord2f(model->TexCoordArray[model->FaceArray[i].TexCoord[1]].s,
+ model->TexCoordArray[model->FaceArray[i].TexCoord[1]].t);
+ glVertex3f(model->VertexArray[model->FaceArray[i].Vertex[1]].x,
+ model->VertexArray[model->FaceArray[i].Vertex[1]].y,
+ model->VertexArray[model->FaceArray[i].Vertex[1]].z );
+
+ glNormal3f(model->NormalArray[model->FaceArray[i].Normal[2]].x,
+ model->NormalArray[model->FaceArray[i].Normal[2]].y,
+ model->NormalArray[model->FaceArray[i].Normal[2]].z );
+ glTexCoord2f(model->TexCoordArray[model->FaceArray[i].TexCoord[2]].s,
+ model->TexCoordArray[model->FaceArray[i].TexCoord[2]].t);
+ glVertex3f(model->VertexArray[model->FaceArray[i].Vertex[2]].x,
+ model->VertexArray[model->FaceArray[i].Vertex[2]].y,
+ model->VertexArray[model->FaceArray[i].Vertex[2]].z );
+
+ glNormal3f(model->NormalArray[model->FaceArray[i].Normal[3]].x,
+ model->NormalArray[model->FaceArray[i].Normal[3]].y,
+ model->NormalArray[model->FaceArray[i].Normal[3]].z );
+ glTexCoord2f(model->TexCoordArray[model->FaceArray[i].TexCoord[3]].s,
+ model->TexCoordArray[model->FaceArray[i].TexCoord[3]].t);
+ glVertex3f(model->VertexArray[model->FaceArray[i].Vertex[3]].x,
+ model->VertexArray[model->FaceArray[i].Vertex[3]].y,
+ model->VertexArray[model->FaceArray[i].Vertex[3]].z );
+ }
+}
+
+/* OpenGL immediate command generator for triangles */
+void ObjSubmitGLCommandsTriangle(const ObjModel *model)
{
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 );
+ int i;
+ for (i = 0; i < model->nFace; i++)
+ {
+ glNormal3f(model->NormalArray[model->FaceArray[i].Normal[0]].x,
+ model->NormalArray[model->FaceArray[i].Normal[0]].y,
+ model->NormalArray[model->FaceArray[i].Normal[0]].z );
+ glTexCoord2f(model->TexCoordArray[model->FaceArray[i].TexCoord[0]].s,
+ model->TexCoordArray[model->FaceArray[i].TexCoord[0]].t);
+ glVertex3f(model->VertexArray[model->FaceArray[i].Vertex[0]].x,
+ model->VertexArray[model->FaceArray[i].Vertex[0]].y,
+ model->VertexArray[model->FaceArray[i].Vertex[0]].z );
+
+ glNormal3f(model->NormalArray[model->FaceArray[i].Normal[1]].x,
+ model->NormalArray[model->FaceArray[i].Normal[1]].y,
+ model->NormalArray[model->FaceArray[i].Normal[1]].z );
+ glTexCoord2f(model->TexCoordArray[model->FaceArray[i].TexCoord[1]].s,
+ model->TexCoordArray[model->FaceArray[i].TexCoord[1]].t);
+ glVertex3f(model->VertexArray[model->FaceArray[i].Vertex[1]].x,
+ model->VertexArray[model->FaceArray[i].Vertex[1]].y,
+ model->VertexArray[model->FaceArray[i].Vertex[1]].z );
+
+ glNormal3f(model->NormalArray[model->FaceArray[i].Normal[2]].x,
+ model->NormalArray[model->FaceArray[i].Normal[2]].y,
+ model->NormalArray[model->FaceArray[i].Normal[2]].z );
+ glTexCoord2f(model->TexCoordArray[model->FaceArray[i].TexCoord[2]].s,
+ model->TexCoordArray[model->FaceArray[i].TexCoord[2]].t);
+ glVertex3f(model->VertexArray[model->FaceArray[i].Vertex[2]].x,
+ model->VertexArray[model->FaceArray[i].Vertex[2]].y,
+ model->VertexArray[model->FaceArray[i].Vertex[2]].z );
+ }
}
void ObjFree(ObjModel *model)
diff --git a/obj.h b/obj.h
index d0ba3b5..6451b18 100644
--- a/obj.h
+++ b/obj.h
@@ -1,9 +1,8 @@
#ifndef _OBJLOADER_H_
#define _OBJLOADER_H_
-extern char obj_last_fname[101];
+extern char ObjLastFname[101];
-#pragma pack(1)
typedef struct
{
float x, y, z, w;
@@ -16,7 +15,7 @@ typedef struct
typedef struct
{
- float u, v, w;
+ float s, t, r, q;
} ObjTexCoord;
typedef struct
@@ -68,7 +67,10 @@ void ObjList(ObjModel *);
* mtl or texture that resides in the same folder */
char *ObjGetPath(const char *);
-void ObjPutFaceGLCmd(const ObjModel *, const unsigned);
+void ObjSubmitIndexedVertexArrayQuad(const ObjModel *);
+
+void ObjSubmitGLCommandsQuad(const ObjModel *);
+void ObjSubmitGLCommandsTriangle(const ObjModel *);
void ObjFree(ObjModel *);
static inline ObjNormal *ObjGetNormal(const ObjModel *model, const unsigned i,
diff --git a/objloader.c b/objloader.c
index 699efdd..162e5b9 100644
--- a/objloader.c
+++ b/objloader.c
@@ -108,6 +108,7 @@ static void setup_opengl(ObjModel *model)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glEnable(GL_TEXTURE_2D);
@@ -166,11 +167,11 @@ static void render(ObjModel *model)
glTranslatef(5.0f, 0.0f, -150.0f);
glBegin(GL_QUADS);
- int i;
- for (i = 0; i < model->nFace; i++)
- ObjPutFaceGLCmd(model, i);
+ ObjSubmitGLCommandsQuad(model);
glEnd();
+ /* ObjSubmitIndexedVertexArrayQuad(model); */
+
glPopMatrix();
/* buffer swap */