• 正文概述
  • 【C++】tinygltf基本使用方法加载glb/gltf格式

    一、前言
    网上的教程均为搭配opengl使用,如果单纯想读取模型数据,资料就比较少了。先放出相关链接
    1、gltf规范文档:glTF™ 2.0 Specification (khronos.org)
    2、gltf在线模型查看器 :glTF Viewer (donmccurdy.com)
    3、tinygltf:GitHub – syoyo/tinygltf: Header only C++11 tiny glTF 2.0 library
    4、vulkan使用tinygltf官方示例:GitHub – SaschaWillems/Vulkan-glTF-PBR: Physical based rendering with Vulkan using glTF 2.0 models
    二、使用
    1、初始
    首先引入头文件:
    #define TINYGLTF_IMPLEMENTATION #include <tiny_gltf.h>
    再加载文件,注意glb格式和gltf格式调用的函数不同:
    tinygltf::Model model; tinygltf::TinyGLTF loader; std::string err; std::string warn;bool load_ok; if(is_glb)load_ok = loader.LoadBinaryFromFile(&model, &err, &warn, std::string{ path_name }); elseload_ok = loader.LoadASCIIFromFile(&model, &err, &warn, std::string{ path_name });if (!warn.empty()) log_warn(“{}”, warn);if (!err.empty())log_err(“{}”, err);if (!load_ok) {log_err(“解析gltf格式失败:{}”, err);return {}; }
    二、读取材质
    其中 mo_material是我们自定义结构,用于接收读取到的数据。由于之前的光照模型是 Blinn-Phong,而现在更通用的是pbr,以下代码可能不适用你的需求。
    之所以我将纹理导出、因为我要进行二次处理,生成自定义的模型格式。你可以不保存到文件,而是直接使用。
    通过查看 tinygltf::PbrMetallicRoughness类型的定义,可以知道提供哪些纹理和材质数据。
    //——————获取材质——————- mo_material.resize(model.materials.size()); for (size_t i = 0; i < model.materials.size(); ++i) {tinygltf::Material& m = model.materials[i];log_info(“材质:{},{}”, i, m.name);tinygltf::PbrMetallicRoughness& pbr = m.pbrMetallicRoughness;ModelObjectMaterial& material = mo_material[i];material._materialName = m.name;material._material._diffuseAlbedo = { (float)pbr.baseColorFactor[0],(float)pbr.baseColorFactor[1],(float)pbr.baseColorFactor[2], 1.0f };material._material._fresnelR0 = { (float)pbr.metallicFactor, (float)pbr.metallicFactor, (float)pbr.metallicFactor };material._material._roughness = (float)pbr.roughnessFactor;// 纹理导出auto fn_texture = [&](int index, std::string_view tag) {if (index == -1)return std::string{};tinygltf::Image& img = model.images[index];if (!img.uri.empty())return img.uri;std::string path_name = fmt::format(“{}{}{}#{}.png”,File::PathTemp(), res_name, tag, i);stbi_write_png(CodeCvt::Utf8ToMultiByte(path_name).c_str(),img.width, img.height,4, img.image.data(), 0);return path_name;};material._pathTexDiffuse = fn_texture(pbr.baseColorTexture.index, “”);material._pathTexNormal = fn_texture(m.normalTexture.index, “_normal”); }
    我的做法是按材质合并网格(不知道会不会影响骨骼动画,后面再说),你也可以简单处理,按 tinygltf::Primitive为单位为绘制。prim里不直接存数据,而是通过 Accessor访问,然后通过 Accessor取得 BufferView,然后通过 BufferView取得真正的顶点数据。
    注意数据首地址为 buf.data.data() + buf_view.byteOffset + accessor.byteOffset,单个顶点偏移为 int byte_stride = accessor.ByteStride(buf_view)。
    注意我这里没有过多的 assert的检查,这里的代码还需要尝试更多模型,才能具有可靠性
    for (tinygltf::Mesh& mesh : model.meshes){for (tinygltf::Primitive& prim : mesh.primitives){PrimData& prim_data = map_material[prim.material];size_t vertex_offset = prim_data._allVertex.size();// 索引{tinygltf::Accessor accessor = model.accessors[prim.indices];tinygltf::BufferView buf_view = model.bufferViews[accessor.bufferView];tinygltf::Buffer& buf = model.buffers[buf_view.buffer];int byte_stride = accessor.ByteStride(buf_view);unsigned char* p = buf.data.data() + buf_view.byteOffset + accessor.byteOffset;assert(byte_stride == 4);for (size_t i = 0; i < accessor.count; ++i){uint32_t index = *(uint32_t*)p; prim_data._allIndex.push_back(vertex_offset + index);p += byte_stride;}}// 位置auto iter_pos = prim.attributes.find(“POSITION”);if(iter_pos != prim.attributes.end()){tinygltf::Accessor accessor = model.accessors[iter_pos->second];tinygltf::BufferView buf_view = model.bufferViews[accessor.bufferView];tinygltf::Buffer& buf = model.buffers[buf_view.buffer];prim_data._allVertex.resize(vertex_offset + accessor.count);int byte_stride = accessor.ByteStride(buf_view);unsigned char* p = buf.data.data() + buf_view.byteOffset + accessor.byteOffset;for (size_t i = 0; i < accessor.count; ++i){Vertex& v = prim_data._allVertex[vertex_offset + i];v._pos = *(Position3*)p;p += byte_stride;}}// uvauto iter_uv = prim.attributes.find(“TEXCOORD_0”);if (iter_uv != prim.attributes.end()){tinygltf::Accessor accessor = model.accessors[iter_uv->second];tinygltf::BufferView buf_view = model.bufferViews[accessor.bufferView];tinygltf::Buffer& buf = model.buffers[buf_view.buffer];int byte_stride = accessor.ByteStride(buf_view);unsigned char* p = buf.data.data() + buf_view.byteOffset + accessor.byteOffset;for (size_t i = 0; i < accessor.count; ++i){Vertex& v = prim_data._allVertex[vertex_offset + i];v._uv = *(Position2*)p;p += byte_stride;}}// normalauto iter_normal = prim.attributes.find(“NORMAL”);if (iter_normal != prim.attributes.end()){tinygltf::Accessor accessor = model.accessors[iter_normal->second];tinygltf::BufferView buf_view = model.bufferViews[accessor.bufferView];tinygltf::Buffer& buf = model.buffers[buf_view.buffer];int byte_stride = accessor.ByteStride(buf_view);unsigned char* p = buf.data.data() + buf_view.byteOffset + accessor.byteOffset;for (size_t i = 0; i < accessor.count; ++i){Vertex& v = prim_data._allVertex[vertex_offset + i];v._normal = *(Position3*)p;p += byte_stride;}}// TANGENTauto iter_tangent = prim.attributes.find(“TANGENT”);if (iter_tangent != prim.attributes.end()){tinygltf::Accessor accessor = model.accessors[iter_tangent->second];tinygltf::BufferView buf_view = model.bufferViews[accessor.bufferView];tinygltf::Buffer& buf = model.buffers[buf_view.buffer];int byte_stride = accessor.ByteStride(buf_view);unsigned char* p = buf.data.data() + buf_view.byteOffset + accessor.byteOffset;for (size_t i = 0; i < accessor.count; ++i){Vertex& v = prim_data._allVertex[vertex_offset + i];v._tangent = *(Position3*)p;p += byte_stride;}}}}
    三、截图
    这里没有处理骨骼动画和光照,不过对于学习 tinygltf的基本用法,应该是足够了!
     
    【C++】tinygltf基本使用方法加载glb/gltf格式

    添加图片注释,不超过 140 字(可选)
    1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
    2. 分享目的仅供大家学习和交流,请不要用于商业用途!
    3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入!
    4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
    5. 如有链接无法下载、失效或广告,请联系管理员处理!
    6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
    7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员!
    8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载
    声明如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性

    GLB下载网 - GLB/GLTF模型与格式资源免费下载,支持在线浏览与转换 » 【C++】tinygltf基本使用方法加载glb/gltf格式

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载要提取码
    百度网盘提取码都是gltf。
    分享过期和重复下载怎么办
    分享过期请使用备份下载,重复下载是不另扣费的,请放心下载。
    模型和平台不兼容怎么办
    可以用网站在线编辑功能,修改模型属性,大小,方向,坐标,中心,透明等问题,然后重新导出既可https://glbxz.com/38636.html
    开通VIP 享更多特权,建议使用 QQ 登录