},
{
"bufferView": 1,
"byteOffset": 288,
"componentType": 5126,
"count": 24,
"max": [
0.5,
0.5,
0.5
],
"min": [
-0.5,
-0.5,
-0.5
],
"type": "VEC3"
},
{
"bufferView": 2,
"byteOffset": 0,
"componentType": 5126,
"count": 24,
"max": [
6.0,
1.0
],
"min": [
0.0,
0.0
],
"type": "VEC2"
}
],
"materials": [
{
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0
},
"metallicFactor": 0.0
},
"name": "Texture"
}
],
"textures": [
{
"sampler": 0,
"source": 0
}
],
"images": [
{
"uri": "CesiumLogoFlat.png"
}
],
"samplers": [
{
"magFilter": 9729,
"minFilter": 9986,
"wrapS": 10497,
"wrapT": 10497
}
],
"bufferViews": [
{
"buffer": 0,
"byteOffset": 768,
"byteLength": 72,
"target": 34963
},
{
"buffer": 0,
"byteOffset": 0,
"byteLength": 576,
"byteStride": 12,
"target": 34962
},
{
"buffer": 0,
"byteOffset": 576,
"byteLength": 192,
"byteStride": 8,
"target": 34962
}
],
"buffers": [
{
"byteLength": 840,
"uri": "BoxTextured0.bin"
}
]
}
下面我们来打造一个小型3D引擎来渲染它,其中的类名和作用保持和`glTF`中的一致,主要有`Engine`、`Scene`、`Node`、`Mesh`、`Primitive`、`Material`。
#### glTF模型解析
`glTF`模型的解析有一些开源库可以使用,这里我们使用[tinygltf]( )这个库,这个库挺好用的,很小巧,接入简单,我们先来看一下解析代码:
void Engine::loadGLTF(const std::string &path) {
tinygltf::TinyGLTF loader;
std::string err;
std::string warn;
loader.LoadASCIIFromFile(&model_, &err, &warn, path);
}
解析后会得到一个`tinygltf::Model`,里面的成员变量的名字和层级与`glTF`里的保持一致,用起来非常友好,并且还包括了`bin`数据读取、图片数据读取,而不仅仅是字段的解析,连数据都帮你读好了。
#### 数据加载
有了`model`之后,我们来根据这个`model`里的数据创建相应的`GL`资源备用。
我们先来看`buffer`:
“buffers”: [
{
“byteLength”: 840,
“uri”: “BoxTextured0.bin”
}
]
在这个立方体模型中,只有一个`buffer`,我们来把它加载到`GL buffer`中去,也就是常说的`vbo`:
std::shared_ptr<std::vector>
Engine::buildBuffers(const tinygltf::Model &model) {
auto buffers = std::make_shared<std::vector>(model.buffers.size(), 0);
GL_CHECK(glGenBuffers(buffers->size(), buffers->data()));
for (auto i = 0; i < model.buffers.size(); ++i) {
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, buffers->at(i)));
GL_CHECK(glBufferData(GL_ARRAY_BUFFER, model.buffers[i].data.size(),
model.buffers[i].data.data(), GL_STATIC_DRAW));
}
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0));
return buffers;
}
这里`vbo`里装的就是这个`glTF`模型所有的数值数据了,包括顶点、纹理坐标、法向量、索引等都在这了。
接下来我们来加载纹理:
std::shared_ptr<std::vector>
Engine::buildTextures(const tinygltf::Model &model) {
auto textures = std::make_shared<std::vector>(model.textures.size());
GL_CHECK(glGenTextures(textures->size(), textures->dat