/*
glm.c
Nate Robins, 1997, 2000
[email protected], http://www.pobox.com/~nate
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)])
/* _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.0;
model->materials[i].diffuse[0] = 0.8;
model->materials[i].diffuse[1] = 0.8;
model->materials[i].diffuse[2] = 0.8;
model->materials[i].diffuse[3] = 1.0;
model->materials[i].ambient[0] = 0.2;
model->materials[i].ambient[1] = 0.2;
model->materials[i].ambient[2] = 0.2;
model->materials[i].ambient[3] = 1.0;
model->materials[i].specular[0] = 0.0;
model->materials[i].specular[1] = 0.0;
model->materials[i].specular[2] = 0.0;
model->materials[i].specular[3] = 1.0;
}
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),
没有合适的资源?快使用搜索试试~ 我知道了~
opengl 学习的的好东西--明白各种参数意义
共57个文件
dsp:9个
c:8个
obj:7个
需积分: 9 3 下载量 42 浏览量
2008-11-20
16:38:20
上传
评论
收藏 1.25MB ZIP 举报
温馨提示
OpenGl的学习资料 红宝书的一个程序
资源详情
资源评论
资源推荐
收起资源包目录
tutors-win32.zip (57个子文件)
tutors
fog.exe 72KB
lightmaterial.c 41KB
glut32.dll 232KB
transformation.c 19KB
fog.c 12KB
shapes.exe 72KB
lightposition.exe 76KB
projection.c 24KB
tutors.vsnetproj
lightmaterial.vcproj 3KB
fog.vcproj 3KB
transformation.vcproj 3KB
texture.vcproj 3KB
lightposition.vcproj 3KB
tutors.sln 4KB
shapes.vcproj 3KB
projection.vcproj 3KB
tutors.xcodeproj
project.pbxproj 37KB
projection.exe 76KB
glm.h 10KB
materials.h 3KB
lightmaterial.exe 96KB
tutors.vc6
lightposition.dsp 4KB
fog.dsp 4KB
all.dsp 2KB
glm.dsp 3KB
transformation.dsp 4KB
lightmaterial.dsp 4KB
tutors.dsw 3KB
texture.dsp 4KB
shapes.dsp 4KB
projection.dsp 4KB
lightposition.c 20KB
glm.c 65KB
texture.c 35KB
transformation.exe 76KB
shapes.c 55KB
texture.exe 80KB
data
rose+vase.obj 245KB
fishermen.ppm 48KB
soccerball.obj 195KB
f-16.mtl 536B
porsche.mtl 536B
checker.ppm 48KB
rose+vase.mtl 971B
flowers.mtl 401B
opengl.ppm 192KB
al.mtl 2KB
soccerball.mtl 136B
al.obj 182KB
dolphins.mtl 342B
flowers.obj 673KB
marble.ppm 48KB
f-16.obj 278KB
porsche.obj 488KB
dolphins.obj 49KB
train.ppm 192KB
Makefile 2KB
共 57 条
- 1
yufq007
- 粉丝: 0
- 资源: 7
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0