obj文件解读

我们先制作一个同时具有三边面和四边面的几何体,保存为obj格式后用记事本打开。

打开后记事本内容如下:

# This file uses centimeters as units for non-parametric coordinates.mtllib 1.mtl
g default
v -0.500000 -0.500000 0.500000
v 0.500000 -0.500000 0.500000
v -0.500000 0.500000 0.500000
v 0.500000 0.500000 0.500000
v -0.500000 0.500000 -0.500000
v 0.500000 0.500000 -0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 -0.500000
v 0.000000 0.867287 0.000000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.375000 0.500000
vt 0.625000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 1.000000
vt 0.625000 1.000000
vt 0.875000 0.000000
vt 0.875000 0.250000
vt 0.125000 0.000000
vt 0.125000 0.250000
vt 0.500000 0.375000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.805928 -0.592014
vn 0.000000 0.805928 -0.592014
vn 0.000000 0.805928 -0.592014
vn 0.000000 0.000000 -1.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn 0.592014 0.805928 0.000000
vn 0.592014 0.805928 0.000000
vn 0.592014 0.805928 0.000000
vn -0.592014 0.805928 0.000000
vn -0.592014 0.805928 0.000000
vn -0.592014 0.805928 0.000000
vn 0.000000 0.805928 0.592014
vn 0.000000 0.805928 0.592014
vn 0.000000 0.805928 0.592014
s off
g pCube1
usemtl initialShadingGroup
f 1/1/1 2/2/2 4/4/3 3/3/4
f 5/5/5 9/15/6 6/6/7
f 5/5/8 6/6/9 8/8/10 7/7/11
f 7/7/12 8/8/13 2/10/14 1/9/15
f 2/2/16 8/11/17 6/12/18 4/4/19
f 7/13/20 1/1/21 3/3/22 5/14/23
f 9/15/24 4/4/25 6/6/26
f 3/3/27 9/15/28 5/5/29
f 3/3/30 4/4/31 9/15/32

展示的文档第一行是注释;
第二行mtllib 1.mtl表示引用随obj文件一同创建的材质文件,这里不做过多讨论;
g default表示模型组;
v开头行都表示顶点的信息:
v -0.500000 -0.500000 0.500000表示一个位置信息;
vt 0.375000 0.000000表示一个uv坐标信息;
vn 0.000000 0.000000 1.000000表示一个法线信息;
在顶点索引的时候,以上三个信息都有可能会被引用多次。
s off表示文件没有光滑组;
usemtl initialShadingGroup表示在刚才的mtl文件中引用的材质;
f 1/1/1 2/2/2 4/4/3 3/3/4f开头的行表示面的顶点索引,这个面共有4个顶点,顶点的信息索引又以/隔开:位置索引/UV索引/法线索引
更多的obj文件前缀可以查看这篇文章

C++实现obj格式文件读取

我的方法是先将文件全部行遍历一遍,记录各种信息的总个数。由于,我想在这里将四边形处理为两个三角形,因此增加了一个iNum计数。事实上,DirectX会在曲面细分阶段更加高效的处理这些四边形。因此不必这么处理。

while (getline(infile1, sline)) {//从指定文件逐行读取if (sline[0] == 'v') {if (sline[1] == 'n') {//vnvnNum++;}else if (sline[1] == 't') {//vtvtNum++;}else {//vvNum++;}}if (sline[0] == 'f') {istringstream ins(sline);s4.clear();ins >> s0 >> s1 >> s2 >> s3 >> s4;if (!s4.empty()) {fNum++;iNum++;}s4.clear();fNum++;iNum += 3;}
}
infile1.close();

完成计数后,再次进行一次遍历,储存所有顶点信息及索引信息。

while (getline(infile2, sline)) {if (sline[0] == 'v') {if (sline[1] == 'n') {istringstream ins(sline);ins >> s0 >> normals[nn].x >> normals[nn].y >> normals[nn].z;//cout << "normal:" << s0.c_str() << normals[nn].x << normals[nn].y << normals[nn].z << endl;nn++;}else if (sline[1] == 't') {istringstream ins(sline);ins >> s0 >> uvs[tt].x >> uvs[tt].y >> uvs[tt].z;uvs[tt].y = 1 - uvs[tt].y;//cout << "uv:" << s0.c_str() << uvs[tt].x << uvs[tt].y << uvs[tt].z << endl;tt++;}else {istringstream ins(sline);ins >> s0 >> positions[vv].x >> positions[vv].y >> positions[vv].z;//cout << "pos:" << s0.c_str() << positions[vv].x << positions[vv].y << positions[vv].z << endl;vv++;}}if (sline[0] == 'f') {istringstream in(sline);float a;in >> s0;//去掉fUINT i, k;for (i = 0; i < 4; i++) {s0.clear();in >> s0;if (i == 3) {//第四项为空则跳过if (s0.empty()) {//第四项存在则复制前两项然后读入本行第四项(四边形分为三角形)b = false;break;}else {b = true;indices[ii] = indices[ii - 3];indices[ii+1] = indices[ii - 1];ii += 2;}}a = 0;for (k = 0; s0[k] != '/'; k++)a = a * 10 + (s0[k] - 48); //0在ASCII码中为48vertices[ff].Pos = positions[a-1];indices[ii] = ff;a = 0;for (k = k + 1; s0[k] != '/'; k++)a = a * 10 + (s0[k] - 48);vertices[ff].Tex0 = XMFLOAT4(uvs[a-1].x, uvs[a-1].y, uvs[a-1].z, 1.0f);a = 0;for (k = k + 1; s0[k]; k++)a = a * 10 + (s0[k] - 48);vertices[ff].Normal = normals[a-1];ff++;ii++;}}
}

同时,我在读取模型数据的时候又做一次计算切线的过程。CPU又一次抢走了GPU的活:

//计算切线【Q − P0 = (u − u0)T + (v − v0)B】
FLOAT s1 = vertices[ff - 2].Tex0.x - vertices[ff - 3].Tex0.x;
FLOAT s2 = vertices[ff - 1].Tex0.x - vertices[ff - 3].Tex0.x;
FLOAT t1 = vertices[ff - 2].Tex0.y - vertices[ff - 3].Tex0.y;
FLOAT t2 = vertices[ff - 1].Tex0.y - vertices[ff - 3].Tex0.y;
FLOAT c = s1 * t2 - s2 * t1;
XMFLOAT3 Q1 = minusFloat3(vertices[ff - 2].Pos, vertices[ff - 3].Pos);
XMFLOAT3 Q2 = minusFloat3(vertices[ff - 1].Pos, vertices[ff - 3].Pos);
XMFLOAT3 T = addFloat3(mul(t2 / c, Q1), mul(-t1 / c, Q2));
//XMFLOAT3 B = addFloat3(mul(-s2 / c, Q1), mul(s1 / c, Q2));
//float t = dot(T,B);
XMFLOAT3 T1 = minusFloat3(T, mul(dot(T, vertices[ff - 1].Normal), vertices[ff - 1].Normal));
XMFLOAT3 T2 = minusFloat3(T, mul(dot(T, vertices[ff - 2].Normal), vertices[ff - 2].Normal));
XMFLOAT3 T3 = minusFloat3(T, mul(dot(T, vertices[ff - 3].Normal), vertices[ff - 3].Normal));normalized(T1);
normalized(T2);
normalized(T3);vertices[ff - 1].Tangent = T1;
vertices[ff - 2].Tangent = T2;
vertices[ff - 3].Tangent = T3;
if (b == true) {vertices[ff-4].Tangent = minusFloat3(T, mul(dot(T, vertices[ff - 4].Normal), vertices[ff - 4].Normal));normalized(vertices[ff - 4].Tangent);//vertices[ff-4].Normal = N;
}

读取后在DriectX12中的效果:

C++实现简单读取Obj格式文件相关推荐

  1. php生成vcf,php简单读取.vcf格式文件的方法示例

    本文实例讲述了php简单读取.vcf格式文件的方法.分享给大家供大家参考,具体如下: /** * 读取.vcf格式文件 * @param $filename */ function readCvf($ ...

  2. php vcf,php简单读取.vcf格式文件的方法示例

    本文实例讲述了php简单读取.vcf格式文件的方法.分享给大家供大家参考,具体如下: /** * 读取.vcf格式文件 * @param $filename */ function readCvf($ ...

  3. nodejs json转对象_nodejs读取xlsx格式文件

    # nodejs读取xlsx格式文件 安装 npm i node-xlsx -D // 或者 yarn add node-xlsx -D 使用 读取表格数据,并生成json对象 /*** @auth ...

  4. OSG仿真案例(8)——读取FBX格式文件并显示(无动画)

    包含的头 #include <iostream> #include <Windows.h> #include <osgDB/ReadFile> #include & ...

  5. nodejs读取xlsx格式文件

    nodejs读取xlsx格式文件 安装 npm i node-xlsx -D // 或者 yarn add node-xlsx -D 使用 读取表格数据,并生成json对象 /*** @author ...

  6. 如何读取DXF格式文件?

    9 楼ryan_www(点1) 如何读取DXF格式文件?           http://tech.sina.com.cn   2000/05/22     软件世界       OpenGL是美国 ...

  7. 读取DXF格式文件 (转)

    读取DXF格式文件 (转)[@more@] 读取DXF格式文件 OpenGL是美国SGI公司最新推出的一套开放式的三维图形软件接口,适用于广泛的计算机环境,从个人计算机到工作站,OpenGL都能实现高 ...

  8. Python——读取raw格式文件

    Python--读取raw格式文件 文章目录 Python--读取raw格式文件 前言 一.直接上代码 前言 简单记录一下python读取raw格式图像,因为reshape来来回回还交换轴搞得人头大, ...

  9. python用os.system打开wav文件_使用python读取wav格式文件

    ** 使用python读取wav格式文件 ** - 基本概念 [采样频率] 即取样频率, 指每秒钟取得声音样本的次数.采样频率越高,声音的质量也就越好,声音的还原也就越真实,但同时它占的资源比较多.由 ...

  10. python xlrd读取excel-使用Python xlrd模块读取Excel格式文件的方法

    这是一篇关于如何使用Python xlrd模块读取Excel格式文件的方法的文章,下面的python代码中使用 了xlrd模块的方法,这样就能够很方便的读取 excel 文件内容.同是这个xlrd模块 ...

最新文章

  1. 【转】微信公共号开发,提示“该公众号暂时无法提供服务,请稍后再试”,如何解决?...
  2. JAVA中经过nginx反向代理获取客户端ip并获取相关坐标等信息
  3. SharePoint Online 创建用户和组
  4. 面向对象简单原则(转)
  5. mysql为什么表大了要重建_为什么MySQL分库分表后总存储大小变大了?
  6. 被文献坑是一种什么样的体验?
  7. bitherj java_比太钱包为什么从 Bitcoinj 切换到了 Bitherj ?比太钱包从 Bitcoinj 切换到了 Bitherj原因是什么?...
  8. 《越狱》完结 米帅迷应小心纹身网站挂马
  9. ajax 购物车 c#,c#购物车功能实现及收藏功能实现
  10. 珍惜吧,这届世界杯之后,怕是再也看不到他们了
  11. Linux php5 curl 扩展
  12. STM8S103K3和STM8S105K4原理图
  13. pdf转换成jpg python_Python Wand将PDF转换为JPG background
  14. java开发深圳平均工资_深圳2017平均工资100173元!!这次你又又又拖后腿了吗!?...
  15. 华为p10关闭更新_华为P10怎么取消系统更新提醒
  16. json c语言开发,JSON c语言开发指南
  17. Mac的日历事件如何同步更新到iphone手机中?
  18. c语言编写可乐瓶游戏,可乐瓶游戏二十则
  19. 《10人以下小团队管理手册》读书摘记
  20. Qt之QTableView、QTableWidget

热门文章

  1. 视频相似度检测算法软件,视频相似度检测算法图
  2. 【FICO】SAP中的银行
  3. php微信聊天机器人_使用图灵机器人api搭建微信聊天机器人php实现
  4. 微信公众号调用扫一扫
  5. dplayer安装php_Dplayer播放器集成p2p加速源码分享
  6. 星星之火-34:傅里叶分析的9大步骤
  7. 利用51单片机输出PWM波
  8. 中科大高级软件工程课程心得
  9. 哈夫曼树及哈夫曼编码例题
  10. SCI 计算机 数学相关期刊