虚幻4内实时加载OBJ模型。游戏时加载

[复制链接]
查看11919 | 回复27 | 2016-12-4 13:08:41 | 显示全部楼层 |阅读模式
最近刚好在研究虚幻4的渲染流程,于是想把OBJ文件信息加载到虚幻4里面。
首先咋们先捋一下思路
第一:   既然我们要加载OBJ文件,那么我们就要知道OBJ里面到底存了些什么东西,我先在max里创建了一个简单的box然后导出成obj文件,然后用文本打开就会看到如下信息
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 04.12.2016 11:55:04

mtllib Box.mtl

#
# object Box001
#

v  -37.4557 0.0000 37.1487
v  -37.4557 0.0000 -37.1487
v  37.4557 0.0000 -37.1487
v  37.4557 0.0000 37.1487
v  -37.4557 71.9826 37.1487
v  37.4557 71.9826 37.1487
v  37.4557 71.9826 -37.1487
v  -37.4557 71.9826 -37.1487
# 8 vertices

vn 0.0000 -1.0000 -0.0000
vn 0.0000 1.0000 -0.0000
vn 0.0000 0.0000 1.0000
vn 1.0000 0.0000 -0.0000
vn 0.0000 0.0000 -1.0000
vn -1.0000 0.0000 -0.0000
# 6 vertex normals

vt 1.0000 0.0000 0.0000
vt 1.0000 1.0000 0.0000
vt 0.0000 1.0000 0.0000
vt 0.0000 0.0000 0.0000
# 4 texture coords

g Box001
usemtl wire_228214153
s 2
f 1/1/1 2/2/1 3/3/1 4/4/1
s 4
f 5/4/2 6/1/2 7/2/2 8/3/2
s 8
f 1/4/3 4/1/3 6/2/3 5/3/3
s 16
f 4/4/4 3/1/4 7/2/4 6/3/4
s 32
f 3/4/5 2/1/5 8/2/5 7/3/5
s 64
f 2/4/6 1/1/6 5/2/6 8/3/6
# 6 polygons

前几行#部分是一些创建信息什么的 每行v开头的就是顶点的信息啦 (X ,Y ,Z)。vn开头的是顶点法线方向  vt开头的是模型的uv坐标  最后f开头的是模型的indexbuffer信息绕序。
第二: 搞清楚了OBJ里面到底保存了啥之后我们下一步就是要把OBJ的信息读取到虚幻4里面才行啦,当然虚幻4这种强大的引擎当然有文件读取的方法啦。
FFileHelper:oadFileToString(LoadedString, *(FPaths::GameDir() + FilePathAndName + TEXT(".txt")));
这个函数就可以读取一个txt文件的信息。并把信息全部储存在一个Fstring里面。这里要注意了。如果txt文件里面的信息量超出了fstring的最大储存量是会出问题的。不过FString储存一个几万面的obj文件的信息还是没问题的。

第三:经过FFileHelper:oadFileToString(LoadedString, *(FPaths::GameDir() + FilePathAndName + TEXT(".txt")));函数处理后。OBJ文件信息会全部储存到Fstring里面,就我这段代码而言,txt文件的全部信息就储存到了(LoadedString里面。这个时候你可以通过蓝图的printstring或者c++的 addmessagetoscreen就能在游戏窗口里面看到打印信息了。

第四步:现在已经把OBJ文件信息加载进了虚幻。但是现在有两个问题。第一个问题就是,现在的信息是FString储存的一大串字符串信息,是原始的无法被我们直接使用,因为你可以清楚地看到这个字符串里面甚至还包含了#3d max 。。。。这些注释解释信息。我们需要把这一大串数据加工分类,把顶点信息这些数据提取出来然后保存到顶点数组里面,当然这个数组的数据类型必须是float什么的,不能是字符串类型。只有这样我们才能使用这些数据进行运算。而现在这些数据只是一大串字符。第二个问题,假设我们成功处理了那一大串字符串,并且把里面的顶点数据  法线数据  index绕序数据全部提取出来并且储存在了一个数组里面(缓冲区),之后我们要做的是如何在虚幻4里面用这些数据来绘制三维模型。

我们先来解决第一个问题,对Fstring里面的原始数据进行处理,让它变成能被我们使用的数据。
再来观察一下我们的obj文件,发现它都是一行一行地罗列顶点法线什么的信息的。所以我们可以对它进行切割。把它切成一行一行的Fstring数据。然后把每一行作为一个元素保存在一个FString的TArray里面
LoadedString.ParseIntoArrayLines(LineArray, true);
这样我们就得到了一个LineArray
我们访问LineArray里第一行 可以看到它的值是  # 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware。就是我们OBJ文件的第一行。也是LoadedString的第一行
现在我们成功将LoadedString以每一行切成一个小的FString并把这些小的FString保存在了LineArray里面
我访问LineArray保存顶点数据的一行   v  -37.4557 0.0000 37.1487。但这个还不是我想要的。我想要里面的数字。所以我们可以再对这些FString再次进行切割。
LineArray[0].ParseIntoArray(PartsStringArray, TEXT(" "), true);
这样将一行字符串切成了4部分 第一部分是“v” 第二部分是“-37.4557” 第三部分是“0.0000” 第四部分是“37.1487”这样就成功拿到了数据。最后我们把FString转换成float即可。
用上面的方法,我提取出了TArray<FVector>Vertexbuffer   TArray<FVector>Indexbuffer  TArray<FVerctor>NormalArray  TArray<Vector2D>uvArray

成功提取了资源之后我们就可以用上面的资源进行绘制了。
虚幻引擎里面有两个自定义模型组件 一个是custommeshcomponent 一个是ProcedureMeshComponent。CustomMeshComponent是没有UV的。所以我们使用ProcedureMeshComponent来绘制图形。为什么不像directX3d或者OpenGl那样直接绘制图形而是要借助一个组件呢。原因是ProcedureMeshComponent已经搭建好了一个自定义模型框架了。我们可以直接使用这个框架。如果你不想使用这个框架那么可以去看一下staticmeshcomponent的绘图流程。其实原理都是一样的。为了简便我这里使用现成的一个绘图框架来绘制

ProcedureMeshComponent里面有一个CreateMeshSection函数。我们把我们刚才提取到的资源了TArray<FVector>Vertexbuffer   TArray<FVector>Indexbuffer  TArray<FVerctor>NormalArray  TArray<Vector2D>uvArray全部提交给这个函数就可以了。
这样就可以成功加载一个OBJ文件啦。

额打了这么多字手好累,去建个模型放松一下
d53f8794a4c27d1e45123d8213d5ad6eddc438bb.jpg
我是狼 | 2016-12-4 14:00:26 | 显示全部楼层
牛逼 66666666666666666
回复 支持 反对

使用道具 举报

__________ | 2016-12-4 14:21:32 | 显示全部楼层
当初看focus on 3d models搞过一次导入,太折腾人了,佩服楼主
回复 支持 反对

使用道具 举报

堕落的牧羊人 | 2016-12-4 16:36:44 | 显示全部楼层
谢谢分享
回复

使用道具 举报

yuqinggame | 2016-12-4 18:47:22 | 显示全部楼层
谢谢分享
回复

使用道具 举报

默认名 | 2016-12-4 23:00:44 | 显示全部楼层
大感谢!!!
回复

使用道具 举报

mbskyshuai | 2016-12-5 09:30:22 | 显示全部楼层
谢谢分享
回复

使用道具 举报

zjmlife | 2016-12-5 11:10:21 | 显示全部楼层
好牛的样子
回复 支持 反对

使用道具 举报

madrid10 | 2016-12-5 12:32:35 | 显示全部楼层
多谢分享~~~~
回复

使用道具 举报

shenzhen_lx800 | 2016-12-5 12:58:21 | 显示全部楼层
感谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

7

主题

21

回帖

23

积分

初始化成员

积分
23