|
在Runtime模式下读取模型数据,以前做家装时候有出现过这种需求,看现在一些论坛上就是放个视频给很多人眼馋一下,本身传承知识的习惯,博主最近抽空做了个可以实时读取,也可以点击读取的插件,同样的先说下原理和实现,最后放上插件源码。
这个插件照样是使用UE4.19,好了废话不说了。
插件的实现主要有2个函数,如下所示:
UFUNCTION(BlueprintCallable,Category="MeshLoader")
static FReturnedData LoadMesh(FString filepath,EPathType type= EPathType:: Absolute);
UFUNCTION(BlueprintCallable, Category = "MeshLoader")
static TArray<FString> GetAllFilesInDirectory(const FString directory, const bool fullPath, const bool withoutExtention, const FString onlyFilesStartingWith, const FString onlyFilesWithExtension);这两个一个用来读取当前模型顶点,一个用来获取某各路径下的所有文件。
读取模型数据,插件使用了assimpSDK,assimp是一个加载模型数据的库,可以提取模型的定点数据、法线、纹理坐标,assimp的数据会存为一个包,这个包的数据拥有一个比较复杂的数据结构,像Mesh的结构会储存Vertices、Normals、TextureCoords、Faces等。
存储的这些数据,都是以数组方式存在,那么问题来了,怎么去还原这个数据,之前我们的另一个插件Metaballs是用ProceduralMesh实现,那么这里同样是使用ProceduralMesh+CreateMeshSection去还原通过assimp存储的模型数据。
FindMeshInfo函数,是通过assimp创建的结构数据,assimp存储会以结构方式进行,最上面是scene,然后就像脑图一样,有Mesh,有Material等等。所以这里的mesh、mi是将模型数据,存入vertex、mTransformation、uv,可以看到全都是将对应的aiMesh *mesh中去提取Vector、Normal、UV、Tangent等等数据,这些数据都保存在meshInfo里,也就是FMeshInfo &mi = result.meshInfo[meshidx];中的mi,meshInfo其实是个结构体,他里面包含的数据,就是通过assimp获取的模型数据。
然后再来说LoadMesh,LoadMesh里其实没有太多东西,因为数据结构是在FindMeshInfo里已经完成的,所以LoadMesh里一个是查找路径,一个是将meshInfo添加到当前函数,路径的话其实UE4有自己的API,叫FPaths,里面有各种Dir,你可以弄成自己想要的Dir,可以是引擎的Engine目录,也可以是项目的Content目录,或者工程目录,具体可以看FPaths里面的方法,FPaths::ProjectContentDir()很好理解就是项目的Content目录,mScenePtr是用来读取当前的模型文件,然后FindMesh再去根据上面图中的索引路径去查询每个节点数据。
如果是自定义路径,可以使用GetBaseFilename方法。
剩下一个函数GetAllFilesInDirectory就是用来获取目录下所有文件了,这里文件不限制后缀格式,所以使用这个节点可以获取任何类型的对象,图片,xml,反正就是各种数据,你可以自己写个解析xml的配合这个节点来用,也可以写个解析XXX的配合GetAllFilesInDirectory来用。
那么这个节点很好理解,首先获取一个路径,然后遍历路径下的文件,IPlatformFile是UE自带的API,可以用来对文件对象进行操作,方法包含了文件I/O,读取当前平台路径,获取当前文件名字,获取当前文件,获取当前磁盘上一个文件名字,反正具体去看IPlatformFile这个类好了,这里使用了一个GetExtension用来取指定后缀的文件,属于FPaths中的方法,具体可以定义到GetExtension索引,剩下的其实就没有什么了,最后IF里套了一个三元运算符来看GetExtension下的withoutExtention布尔变量是否是自定义路径还是返回一个文件名。
然后来看UE里的实现,首先是生成Mesh,既然是ProceduralMesh,所以需要一个ProceduralMesh组件,然后LoadMesh的逻辑主要是这样的,靠的是LoadMesh节点:
这里用的函数,我的思路是这样的,首先UMG里面用按钮点一下,通过GetAllFilesInDirectory获取路径和文件,然后将路径文件传入这个LoadMeshF函数里,点击函数如下图所示:
上述方法就是通过GetAllFilesInDirectory函数获取路径,这是个String数组,然后遍历一下获取所有该路径下的文件,只查找后缀为FBX的,然后这里有个跨UMG传输数据,我以前讲的一个文章里有这种实现,ScrollBox是一个下拉滚动条,如下图所示:
这个就是UI了,方框里的数据,是通过CreateWidget去Add到这个容器里的,创建的另一个UMG是个button,如下图所示:
这个button的逻辑如下图所示:
调用LoadMeshF那个Actor蓝图里面的函数,FilePath是在主UMG中,传入的FilePath路径,如下图所示:
然后GetAllFilesInDirectory的path变量填写你的电脑绝对路径,最后运行游戏就是如下图所示:
https://www.zhihu.com/video/1134593970997932032
上面视频是实时读取,你可以在主UMG中,断开Tick,把下面的OnClick连接上:
好了,最后附上整个工程,注意了默认运行是没有FBX的,你需要在UMG函数里这个节点,添加你自己的路径,比如C:/test,然后再这个文件夹下放几个FBX或者OBJ文件:
还有一个问题,材质的赋予,到FBX那个Actor蓝图里,的LoadMeshF函数,我目前就只给了所有ProceduralMesh一样的材质,你可以根据路径文件的Index,分别给予不同的材质。
最后附上工程,工程里面的Plugins是插件,带插件源码,请使用UE4.19打开:
链接:https://pan.baidu.com/s/1kXQcJErCw-_6MKqM0AqctA 密码:aiab |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|