openGL GLFW PMX模型 学习笔记 m8w2(d1)
目前UE/Unity都只能靠第三方插件导入Pmx模型,看LearnOpenGL的目的还是想自己实现把MMD模型给导入到游戏引擎中。
PMX格式资料:https://www.cnblogs.com/ifwz/p/17544729.html
PMX载入方法参考(C++):GitHub - benikabocha/saba: OpenGL Viewer (OBJ PMD PMX)
PMX文件读取方式
我这是用fread做的文件读取,fread接收3个参数
- 需要被写入变量的地址;
- 单个值的字节数量;
- 值的数量;
- 需要读取的文件(FILE类型);
// sample
fread(&vertcount, sizeof(vertcount), 1, file);
如上面的例子,fread读取数据的时候,根据第二个参数,读取第三个参数数量的数据,所以总共会读取 sizeof(vertcount) * 1 个字节到vertcount中,这个过程就是非常简单直接的读取。如果想要给glm::vec3类型的变量获取数据,第二个参数用sizeof(float)【因为glm::vec3是三个连续的float类型的数据】,然后第三个参数用3即可;
头部信息
头部信息的获取还是比较容易的,需要注意一下的就是控制台输出编码可能和文件的编码方式不一样,这里我用的是吟霖的Q版模型,控制台输出如下;
Pmx文件大小: 3441418
签名: PMX
version: 2
全局信息数量: 8
全局信息: 0 3 2 1 1 2 2 2
本地模型名: 吟霖Q
通用模型名: New MMD Model
本地语言描述模型: 吟霖Q
请在借物表中注明:
模型:鸣潮/白泽
通用语言描述模型: exported by mmd_tools
顶点信息
顶点这块主要就注意字节数不要读错了,比如骨骼索引大小是2个字节,但是只读了一个字节给变量,那后面读取的值肯定就全错了;
大致画了个PMX文件中头信息和顶点信息的图,所有的字节对应的内容都在上面了,额外vec4的数量N由全局信息的第二个值可知,顶点绑骨信息顺序和字节大小在最开始给的资料中可以知道。
索引信息
PMX中面是根据索引确定的,每三个索引确定一个三角形面片,索引数据组织方式和顶点数据类似,但是内容就简单很多了,顶点索引大小也是由全局信息知道的。
有顶点信息有索引,自此,我们就可以用顶点,法线和索引结合一个简单的BlinnPhong光照模型,把模型在glfw窗口中用openGl绘制出来叻 ^ ^
先前是用了一个结构体去存储模型的每个顶点信息,创建一个PMXVert数组存储全部的顶点数据。
struct PMXVert { glm::vec3 mPos; glm::vec3 mNormal; glm::vec2 mUV; glm::vec4 addiVert[3]; uint8_t weightType; int32_t boneIndices[4]; float boneWeights[4]; glm::vec3 sdefC; glm::vec3 sdefR0; glm::vec3 sdefR1; float edgeMag; };
然后把这个PMXVert数组存到VBO中,只用前8个float(对应位置,法线,UV)传入着色器。索引部分,直接就用一个uint16_t类型的数组fread就好。
Pmx文件大小: 3441418
签名: PMX
version: 2
全局信息数量: 8
全局信息: 0 3 2 1 1 2 2 2
本地模型名: 吟霖Q
通用模型名: New MMD Model
本地语言描述模型: 吟霖Q
请在借物表中注明:
模型:鸣潮/白泽
通用语言描述模型: exported by mmd_tools
顶点数量: 26898
Begin read vertex info...
End read vertex info.
面数量: 104193
Begin read face info...
End read face info.
右上角是光源位置, 模型看起来很正常,那么就说明顶点位置,法线和光照参数都正确读取啦 ^ ^
下一个坑:添加模型纹理和材质 :D