/*
glm.cpp
Wavefront OBJ model file format reader/writer/manipulator.
Includes routines for generating smooth normals with
preservation of edges, welding redundant vertices & texture
coordinate generation (spheremap and planar projections) + more.
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "glm.h"
#define T(x) (model->triangles[(x)])
#define fsin(x) (float)sin(x)
#define fcos(x) (float)cos(x)
#define fasin(x) (float)asin(x)
#define facos(x) (float)acos(x)
#define fsqrt(x) (float)sqrt(x)
/* _GLMnode: general purpose node
*/
typedef struct _GLMnode {
GLuint index;
GLboolean averaged;
struct _GLMnode* next;
} GLMnode;
/* glmMax: returns the maximum of two floats */
static GLfloat glmMax(GLfloat a, GLfloat b)
{
if (b > a)
return b;
return a;
}
/* glmAbs: returns the absolute value of a float */
static GLfloat glmAbs(GLfloat f)
{
if (f < 0)
return -f;
return f;
}
/* glmDot: compute the dot product of two vectors
*
* u - array of 3 GLfloats (GLfloat u[3])
* v - array of 3 GLfloats (GLfloat v[3])
*/
static GLfloat glmDot(GLfloat* u, GLfloat* v)
{
assert(u); assert(v);
return u[0]*v[0] + u[1]*v[1] + u[2]*v[2];
}
/* glmCross: compute the cross product of two vectors
*
* u - array of 3 GLfloats (GLfloat u[3])
* v - array of 3 GLfloats (GLfloat v[3])
* n - array of 3 GLfloats (GLfloat n[3]) to return the cross product in
*/
static GLvoid glmCross(GLfloat* u, GLfloat* v, GLfloat* n)
{
assert(u); assert(v); assert(n);
n[0] = u[1]*v[2] - u[2]*v[1];
n[1] = u[2]*v[0] - u[0]*v[2];
n[2] = u[0]*v[1] - u[1]*v[0];
}
/* glmNormalize: normalize a vector
*
* v - array of 3 GLfloats (GLfloat v[3]) to be normalized
*/
static GLvoid glmNormalize(GLfloat* v)
{
GLfloat l;
assert(v);
l = (GLfloat)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] /= l;
v[1] /= l;
v[2] /= l;
}
/* glmEqual: compares two vectors and returns GL_TRUE if they are
* equal (within a certain threshold) or GL_FALSE if not. An epsilon
* that works fairly well is 0.000001.
*
* u - array of 3 GLfloats (GLfloat u[3])
* v - array of 3 GLfloats (GLfloat v[3])
*/
static GLboolean glmEqual(GLfloat* u, GLfloat* v, GLfloat epsilon)
{
if (glmAbs(u[0] - v[0]) < epsilon &&
glmAbs(u[1] - v[1]) < epsilon &&
glmAbs(u[2] - v[2]) < epsilon)
{
return GL_TRUE;
}
return GL_FALSE;
}
/* glmWeldVectors: eliminate (weld) vectors that are within an
* epsilon of each other.
*
* vectors - array of GLfloat[3]'s to be welded
* numvectors - number of GLfloat[3]'s in vectors
* epsilon - maximum difference between vectors
*
*/
GLfloat* glmWeldVectors(GLfloat* vectors, GLuint* numvectors, GLfloat epsilon)
{
GLfloat* copies;
GLuint copied;
GLuint i, j;
copies = (GLfloat*)malloc(sizeof(GLfloat) * 3 * (*numvectors + 1));
memcpy(copies, vectors, (sizeof(GLfloat) * 3 * (*numvectors + 1)));
copied = 1;
for (i = 1; i <= *numvectors; i++) {
for (j = 1; j <= copied; j++) {
if (glmEqual(&vectors[3 * i], &copies[3 * j], epsilon)) {
goto duplicate;
}
}
/* must not be any duplicates -- add to the copies array */
copies[3 * copied + 0] = vectors[3 * i + 0];
copies[3 * copied + 1] = vectors[3 * i + 1];
copies[3 * copied + 2] = vectors[3 * i + 2];
j = copied; /* pass this along for below */
copied++;
duplicate:
/* set the first component of this vector to point at the correct
index into the new copies array */
vectors[3 * i + 0] = (GLfloat)j;
}
*numvectors = copied-1;
return copies;
}
/* glmFindGroup: Find a group in the model
*/
GLMgroup* glmFindGroup(GLMmodel* model, char* name)
{
GLMgroup* group;
assert(model);
group = model->groups;
while(group) {
if (!strcmp(name, group->name))
break;
group = group->next;
}
return group;
}
/* glmAddGroup: Add a group to the model
*/
GLMgroup* glmAddGroup(GLMmodel* model, char* name)
{
GLMgroup* group;
group = glmFindGroup(model, name);
if (!group) {
group = (GLMgroup*)malloc(sizeof(GLMgroup));
group->name = strdup(name);
group->material = 0;
group->numtriangles = 0;
group->triangles = NULL;
group->next = model->groups;
model->groups = group;
model->numgroups++;
}
return group;
}
/* glmFindGroup: Find a material in the model
*/
GLuint glmFindMaterial(GLMmodel* model, char* name)
{
GLuint i;
/* XXX doing a linear search on a string key'd list is pretty lame,
but it works and is fast enough for now. */
for (i = 0; i < model->nummaterials; i++) {
if (!strcmp(model->materials[i].name, name))
goto found;
}
/* didn't find the name, so print a warning and return the default
material (0). */
printf("glmFindMaterial(): can't find material \"%s\".\n", name);
i = 0;
found:
return i;
}
/* glmDirName: return the directory given a path
*
* path - filesystem path
*
* NOTE: the return value should be free'd.
*/
static char* glmDirName(char* path)
{
char* dir;
char* s;
dir = strdup(path);
s = strrchr(dir, '/');
if (s)
s[1] = '\0';
else
dir[0] = '\0';
return dir;
}
/* glmReadMTL: read a wavefront material library file
*
* model - properly initialized GLMmodel structure
* name - name of the material library
*/
static GLvoid glmReadMTL(GLMmodel* model, char* name)
{
FILE* file;
char* dir;
char* filename;
char buf[128];
GLuint nummaterials, i;
dir = glmDirName(model->pathname);
filename = (char*)malloc(sizeof(char) * (strlen(dir) + strlen(name) + 1));
strcpy(filename, dir);
strcat(filename, name);
free(dir);
file = fopen(filename, "r");
if (!file) {
fprintf(stderr, "glmReadMTL() failed: can't open material file \"%s\".\n",
filename);
exit(1);
}
free(filename);
/* count the number of materials in the file */
nummaterials = 1;
while(fscanf(file, "%s", buf) != EOF) {
switch(buf[0]) {
case '#': /* comment */
/* eat up rest of line */
fgets(buf, sizeof(buf), file);
break;
case 'n': /* newmtl */
fgets(buf, sizeof(buf), file);
nummaterials++;
sscanf(buf, "%s %s", buf, buf);
break;
default:
/* eat up rest of line */
fgets(buf, sizeof(buf), file);
break;
}
}
rewind(file);
model->materials = (GLMmaterial*)malloc(sizeof(GLMmaterial) * nummaterials);
model->nummaterials = nummaterials;
/* set the default material */
for (i = 0; i < nummaterials; i++) {
model->materials[i].name = NULL;
model->materials[i].shininess = 65.0f;
model->materials[i].diffuse[0] = 0.8f;
model->materials[i].diffuse[1] = 0.8f;
model->materials[i].diffuse[2] = 0.8f;
model->materials[i].diffuse[3] = 1.0f;
model->materials[i].ambient[0] = 0.2f;
model->materials[i].ambient[1] = 0.2f;
model->materials[i].ambient[2] = 0.2f;
model->materials[i].ambient[3] = 1.0f;
model->materials[i].specular[0] = 0.0f;
model->materials[i].specular[1] = 0.0f;
model->materials[i].specular[2] = 0.0f;
model->materials[i].specular[3] = 1.0f;
}
model->materials[0].name = strdup("default");
/* now, read in the data */
nummaterials = 0;
while(fscanf(file, "%s", buf) != EOF) {
switch(buf[0]) {
case '#': /* comment */
/* eat up rest of line */
fgets(buf, sizeof(buf), file);
break;
case 'n': /* newmtl */
fgets(buf, sizeof(buf), file);
sscanf(buf, "%s %s", buf, buf);
nummaterials++;
model->materials[nummaterials].name = strdup(buf);
break;
case 'N':
opengl读入obj文件源码
5星 · 超过95%的资源 需积分: 9 48 浏览量
2010-11-28
16:48:57
上传
评论 4
收藏 3.65MB RAR 举报
Margaret_加油
- 粉丝: 42
- 资源: 6
- 1
- 2
- 3
- 4
- 5
- 6
前往页