在经过查阅各种资料以及各种bug之后,终于成功的实现了导入基本的obj模型。
首相介绍一下什么是obj模型
一.什么是OBJ模型
obj文件实际上是一个文本文档,主要有以下数据,一般可以通过blender软件导出模型的obj文件。
在3d图形处理中,一个模型(model)通常由一个或者多个Mesh(网格)组成,一个Mesh是可绘制的独立实体。例如复杂的人物模型,可以分别划分为头部,四肢等各个部分来建模,这些Mesh组合在一起最终形成人物模型。
obj的文本内容一般包括以下数据
usemtl和mtllib表示的材质相关数据,解析材质数据稍微繁琐,本节我们只是为了说明加载模型的原理,不做讨论。
o 引入一个新的object
v 表示顶点位置
vt 表示顶点纹理坐标
vn 表示顶点法向量
f 表示一个面,面使用1/2/8这样格式,表示顶点位置/纹理坐标/法向量的索引,这里索引的是前面用v,vt,vn定义的数据 注意这里Obj的索引是从1开始的,而不是0
二 利用opengl导入obj模型
新建一个ObjLoader
类
class ObjLoader{
public:
ObjLoader(string filename);//构造函数
void Draw();//绘制函数
private:
vector<vector<GLfloat>>vSets;//存放顶点(x,y,z)坐标
vector<vector<GLint>>fSets;//存放面的三个顶点索引
};
一个构造函数ObjLoader::ObjLoader用于导入obj文本内容
Draw用于在opengl中绘制模型
vector<vector<GLfloat>>vSets;//存放顶点(x,y,z)坐标
vector<vector<GLint>>fSets;//存放面的三个顶点索引
ObjLoader::ObjLoader(string filename)
{
std::ifstream file(filename);
std::string line;
while (getline(file, line))
{
if (line.substr(, ) == "vt")
{ }
else if (line.substr(, ) == "vn")
{ }
else if (line.substr(, ) == "v")
{
vector<GLfloat> Point;
GLfloat x, y, z;
std::istringstream s(line.substr());
s >> x; s >> y; s >> z;
Point.push_back(x);
Point.push_back(y);
Point.push_back(z);
vSets.push_back(Point); }
else if (line.substr(, ) == "f")
{
vector<GLint> vIndexSets;
GLint u, v, w;
std::istringstream vtns(line.substr());
vtns >> u; vtns >> v; vtns>> w;
vIndexSets.push_back(u-);
vIndexSets.push_back(v-);
vIndexSets.push_back(w-);
fSets.push_back(vIndexSets);
}
else if (line.substr(, ) == "#")
{ }
else
{ }
}
file.close();
} void ObjLoader::Draw(){ glBegin(GL_TRIANGLES);//开始绘制
for (int i = ; i < fSets.size(); i++) {
GLfloat VN[];
//三个顶点
GLfloat SV1[];
GLfloat SV2[];
GLfloat SV3[]; if ((fSets[i]).size() != ) {
cout << "the fSetsets_Size is not correct" << endl;
}
else {
GLint firstVertexIndex = (fSets[i])[];//取出顶点索引
GLint secondVertexIndex = (fSets[i])[];
GLint thirdVertexIndex = (fSets[i])[]; SV1[] = (vSets[firstVertexIndex])[];//第一个顶点
SV1[] = (vSets[firstVertexIndex])[];
SV1[] = (vSets[firstVertexIndex])[]; SV2[] = (vSets[secondVertexIndex])[]; //第二个顶点
SV2[] = (vSets[secondVertexIndex])[];
SV2[] = (vSets[secondVertexIndex])[]; SV3[] = (vSets[thirdVertexIndex])[]; //第三个顶点
SV3[] = (vSets[thirdVertexIndex])[];
SV3[] = (vSets[thirdVertexIndex])[]; GLfloat vec1[], vec2[], vec3[];//计算法向量
//(x2-x1,y2-y1,z2-z1)
vec1[] = SV1[] - SV2[];
vec1[] = SV1[] - SV2[];
vec1[] = SV1[] - SV2[]; //(x3-x2,y3-y2,z3-z2)
vec2[] = SV1[] - SV3[];
vec2[] = SV1[] - SV3[];
vec2[] = SV1[] - SV3[]; //(x3-x1,y3-y1,z3-z1)
vec3[] = vec1[] * vec2[] - vec1[] * vec2[];
vec3[] = vec2[] * vec1[] - vec2[] * vec1[];
vec3[] = vec2[] * vec1[] - vec2[] * vec1[]; GLfloat D = sqrt(pow(vec3[], ) + pow(vec3[], ) + pow(vec3[], )); VN[] = vec3[] / D;
VN[] = vec3[] / D;
VN[] = vec3[] / D; glNormal3f(VN[], VN[], VN[]);//绘制法向量 glVertex3f(SV1[], SV1[], SV1[]);//绘制三角面片
glVertex3f(SV2[], SV2[], SV2[]);
glVertex3f(SV3[], SV3[], SV3[]);
}
}
glEnd();
}
然后我们写一个主函数
//模型路径
string filePath = "../data/monkey.obj"; ObjLoader objModel = ObjLoader(filePath);
//实现移动鼠标观察模型所需变量
static float c = 3.1415926 / 180.0f;
static float r = 1.0f;
static int degree = ;
static int oldPosY = -;
static int oldPosX = -; //安置光源
void setLightRes() {
GLfloat lightPosition[] = { 0.0f, 0.0f, 1.0f, 0.0f };
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glEnable(GL_LIGHTING); //启用光源
glEnable(GL_LIGHT0); //使用指定灯光
} //初始化
void init() {
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(, );
glutCreateWindow("ObjLoader");
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
setLightRes();
glEnable(GL_DEPTH_TEST);
} void display()
{
glColor3f(1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -5.0f);
setLightRes();
glPushMatrix(); gluLookAt(r*cos(c*degree), , r*sin(c*degree), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); objModel.Draw();//绘制obj模型
glPopMatrix();
glutSwapBuffers();
} void reshape(int width, int height)
{
glViewport(, , width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, (GLdouble)width / (GLdouble)height, 1.0f, 200.0f);
glMatrixMode(GL_MODELVIEW);
} //移动鼠标360观察模型
void moseMove(int button, int state, int x, int y)
{
if (state == GLUT_DOWN) {
oldPosX = x; oldPosY = y;
}
}
void changeViewPoint(int x, int y)
{
int temp = x - oldPosX;
degree += temp;
oldPosX = x;
oldPosY = y;
} void myIdle()
{
glutPostRedisplay();
} int main(int argc, char* argv[])
{
glutInit(&argc, argv);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMouseFunc(moseMove);
glutMotionFunc(changeViewPoint);
glutIdleFunc(myIdle);
glutMainLoop();
return ;
}
这份代码只适合比较简单的obj文件,针对更为复杂的obj文件读取,比如说顶点法向量和纹理的载入等,可在这基础上进行改进。
运行效果:
opengl导入obj模型的更多相关文章
-
三维引擎导入obj模型不可见总结
最近有客户试用我们的三维平台,在导入模型的时候,会出现模型全黑和不可见的情况.上一篇文章说了全黑的情况.此文说下不可见的情况. 经过测试,发现可能有如下两种情况. 导入的模型不在镜头视野内 导入的模型 ...
-
三维引擎导入obj模型全黑总结
最近有客户试用我们的三维平台,在导入模型的时候,会出现模型全黑和不可见的情况.本文说下全黑的情况. 经过测试,发现可能有如下几种情况. obj 模型没有法线向量 如果obj模型导出的时候没有导出法线向 ...
-
Windows下Qt开发环境:OpenGL导入3DMax模型(.3DS)
参考:http://blog.csdn.net/cq361106306/article/details/41876541 效果: 源代码: 解释: CLoad3DS.h为加载3DMax模型的头文件,C ...
-
bullet物理引擎与OpenGL结合 导入3D模型进行碰撞检测 以及画三角网格的坑
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/11681069.html 一.初始化世界以及模型 /// 冲突配置包含内存的默认设置,冲突设置. ...
-
OpenGL OBJ模型加载.
在我们前面绘制一个屋,我们可以看到,需要每个立方体一个一个的自己来推并且还要处理位置信息.代码量大并且要时间.现在我们通过加载模型文件的方法来生成模型文件,比较流行的3D模型文件有OBJ,FBX,da ...
-
OpenGl读取导入3D模型并且添加鼠标移动旋转显示
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/11543828.html 最近实习要用到opengl库就是跟opencv 有点像的那个,然后下了 ...
-
OpenGl 导入读取多个3D模型 并且添加鼠标控制移动旋转
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/11627508.html 前言: 因为接下来的项目需求是要读取多个3D模型,并且移动拼接,那么我 ...
-
three.js加载obj模型
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...
-
[计算机图形学] OpenGL读取obj文件并显示其3D效果
读取三维网格模型(Wavefront OBJ文件) 无法向立方体:cube.obj 有法向兔子模型:bunny.obj 有法向有纹理八字模型:Eight.obj OBJ文件的格式可参考:http: ...
随机推荐
-
MAC下 mysql不能插入中文和中文乱码的问题总结
MAC下 mysql不能插入中文和中文乱码的问题总结 前言 本文中所提到的问题解决方案,都是基于mac环境下的,但其他环境,比如windows应该也适用. 问题描述 本文解决下边两个问题: 往mysq ...
-
Cas 介绍及使用
CAS(Central Authentication Service)是Yale大学发起的一个企业级的.开源的项目,旨在为web应用系统提供一种可靠的单点登录解决方法(属于 web sso). 主要特 ...
-
discuz ucenter无法连接数据库
discuz ucenter无法连接数据库 - discuz搬家后 ucenter无法连接数据库 论坛换了个空间,把密码和数据库名称都改了,点击ucenter时候出现了: UCenter info: ...
-
cocos2d-x 2.2 wp8 开发手记
最近有朋友问我有没有搞过 wp8 的cocos2dx开发 回复:额,没有.(感觉超没面子对方是妹子 = = ) 本着帮妹子试试的态度 就开始了 今天工作 第一我印象中wp8 开发必须要用 vs20 ...
-
(多对象)Json转换成List
写的不好,请大家见谅. 1.Json 格式{"packages":[{“type”:”aaa”}],"zone_packages":[{"ticket ...
-
html5 app图片预加载
function Laimgload(){} //图片预加载JS Laimgload.prototype.winHeight = function(){ //计算页面高度 var winHeight ...
-
1.配置vsftp服务器
1.安装 vsftp yum -y install ftp vsftpd 2.查看配置文件所在路径 rpm -qc vsftpd 3.备份vsftpd文件 cp vsftpd.conf vsftpd. ...
-
zzw原创_非root安装fastDFS
zzw原创_非root安装fastDFS fastDFS 想要非root安装,没找到资料,分析了一下安装脚本,原来作者是留了安装路径的,但没有放出来. 1.解包 [bdc@svr001 setup]$ ...
-
Java学习笔记之——循环语句
一.for循环 语法: for(变量初始化:条件判断:更新循环变量){ 循环体: } 案例: 二.while循环 语法: while(条件){ 循环体: } 如果条件为true,执行循环体,false ...
-
Universal-Image-Loader源码分析(一)——ImageLoaderConfiguration分析
UIl与Volley一样是非常古老的框架,UIL实现了从网络获取图片,对图片进行缓存,以及根据个性化的设置来将图片加载到ImageView上. 这篇文章 主要分析UIl在初始化配置的源码 UIL初始化 ...