/*
glm.c
Nate Robins, 1997
ndr@pobox.com, http://www.pobox.com/~ndr/
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), 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':
fscanf(file, "%f", &model->materials[nummaterials].shininess);
/* wavefront shininess is from [0, 1000], so scale for OpenGL */
model->materials[nummaterials].shininess /= 1000.0;
model->materials[nummaterials].shininess *= 128.0;
break;
case 'K':
switch(buf[1]) {
case 'd':
fscanf(file, "%f %f %f",
&model->materials[nummaterials].diffuse[0],
没有合适的资源?快使用搜索试试~ 我知道了~
opengl加载并渲染obj模型文件(含纹理)
共25个文件
jpg:7个
cpp:4个
h:3个
3星 · 超过75%的资源 需积分: 50 297 下载量 155 浏览量
2016-03-11
11:12:23
上传
评论 7
收藏 3.23MB 7Z 举报
温馨提示
1. 环境win7 + qt5.3.1 WinGW 32bit 2. 使用glm 3. 使用孙启功的方法 4. 网上下载的obj模型文件 5. 我仅仅是用别人的方法和文件进行了简单的实践 6. 因为工作需要,搜索一番不容易找到有用的东西,所以在此留个备份
资源推荐
资源详情
资源评论
收起资源包目录
ObjRender.7z (25个子文件)
modelRender
glwidget.h 3KB
glwidget.cpp 9KB
glm
glm.h 10KB
glm.cpp 53KB
modelRender.pro.user 18KB
main.cpp 2KB
mainwindow.cpp 5KB
mainwindow.h 3KB
modelRender.pro 634B
build
Makefile.Debug 69KB
data
dog
dog.mtl 45B
dog.max 2.97MB
dog.obj 5.36MB
maps
DogEyeC1.jpg 37KB
DogC1.jpg 4.02MB
tail
104d1a3b.jpg 55KB
e0ef839a.jpg 24KB
Tails.JPG 260KB
ed159b47.jpg 172KB
86b0af7b.jpg 11KB
Tails.mtl 1KB
Tails.obj 1.46MB
dragon
dragon.obj 1.74MB
Makefile.Release 69KB
debug
Makefile 19KB
release
共 25 条
- 1
资源评论
- xuexianguang2016-09-29为什么只能读取两张图片,如果纹理图片比较多怎么办?
- nunuhappy2016-09-26改了好多地方没解决,但是只用了里面的代码自己搭建了一个,可以
- lihu64672016-08-07资源配置修改了之后最后有个问题没有解决》》》》》》》》 glwidget.obj:-1: error: LNK2019: 无法解析的外部符号 __imp__glBegin@4,该符号在函数 "private: void __thiscall GLWidget::drawCoordinateSystem(float,float,float)" (?drawCoordinateSystem@GLWidget@@AAEXMMM@Z) 中被引用 glwidget.obj:-1: error: LNK2019: 无法解析的外部符号 __imp__glBlendFunc@8,该符号在
- freezexiao2017-02-09一般吧,不 是很好用
- 妙为2021-06-04一大堆报错,编译不过
咖啡色的思想者
- 粉丝: 11
- 资源: 19
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功