利用Python和C++实现解析gltf文件

 更新时间:2023年09月17日 15:43:41   作者:Hunter_pcx  
gltf是类似于stl、obj、ply等常见的3D对象存储格式,它被设计出来是为了便于渲染的数据转换和传输,本文为大家介绍了使用Python和C++解析gltf文件的方法,感兴趣的可以了解下

gltf是类似于stl、obj、ply等常见的3D对象存储格式,它被设计出来是为了便于渲染的数据转换和传输。如果你的浏览器可以连接外网,可以通过 glTF Viewer 网址打开浏览gltf的3D对象。这里介绍两种语言下从gltf拿到网格的顶点和面片数据。

一、Python

第一步安装pygltflib:

pip install pygltflib

第二步,python解析:

import pygltflib
import numpy as np
pathGltf="test.gltf"
gltf=pygltflib.GLTF2().load(pathGltf)
scene=gltf.scenes[gltf.scene]
nodes=[gltf.nodes[node] for node in scenes.nodes]
vertices=np.arry([node.mesh.primitives[0].attributes["POSITION"] for node in nodes])
print(vertices)

不知道为什么,通过上面这种方式解析,node.mesh我这里是一个int类型的值,运行代码提示node.mesh没有primitives属性,然后在网上找了下面的代码是ok的:

import pygltflib
import pathlib
import struct
# load a gltf file
fname = pathlib.Path("C:/Users/User/Desktop/cube.gltf")
gltf = GLTF2().load(fname)
# get the first mesh in the current scene
mesh = gltf.meshes[gltf.scenes[gltf.scene].nodes[0]-1]
# get the vertices for each primitive in the mesh
for primitive in mesh.primitives:
    # get the binary data for this mesh primitive from the buffer
    accessor = gltf.accessors[primitive.attributes.POSITION]
    bufferView = gltf.bufferViews[accessor.bufferView]
    buffer = gltf.buffers[bufferView.buffer]
    data = gltf.get_data_from_buffer_uri(buffer.uri)
    # pull each vertex from the binary buffer and convert it into a tuple of python floats
    vertices = []
    for i in range(accessor.count):
        index = bufferView.byteOffset + accessor.byteOffset + i*12  # the location in the buffer of this vertex
        d = data[index:index+12]  # the vertex data
        v = struct.unpack("<fff", d)   # convert from base64 to three floats
        vertices.append(v)
# unpack floats
vertices2 = []
for a,b,c in vertices:
    vertices2 += [a,b,c]
# create triangles
vertices = vertices2
triangles = []
for i in range(0,len(vertices),9):
    triangles.append(vertices[i:i+9])
# print data
print(triangles)

二、C++解析

c++依赖的库主要是draco,这个库是开源的,网上可以下载,有了draco之后代码如下:

#include<draco/io/gltf_decoder.h>
#include<draco/tools/draco_transcoder_lib.h>
// 读取gltf文件
bool parse_gltf_from_file(const std::string& filename,std::unique_ptr<draco::Mesh>& mesh){
    draco::GltfDecoder gltfDec;
    draco::StatusOr<std::unique_ptr<draco::Mesh>> stormesh=gltfDec.DecodeFromFile(filename);
    if(!stormesh.ok()){
        return false;
    }
    std::unique_ptr<draco::Mesh> pDracomesh=std::move(stormesh).value();
    std::cout<<"faces num:"<<pDracomesh->num_faces()<<std::endl;
    pDracomesh.swap(mesh);
    return true;
}
//解析出顶点和面片数据
bool get_faces_vertexes(const std::unique_ptr<draco::Mesh>& dracomesh,
                        std::vector<Eigen::Vector3>& vertexes,
                        std::vector<Eigen::Vector3i>& faces){
    auto dump_attribute_to_vec3=[](const draco::PointAttribute& att,std::vector<Eigen::Vector3>& attD){
        if(att.size()==0) return;
        std::vector<Eigen::Vector3> tmp(att.size());
        for(int i=0;i<att.size();++i){
            if(!att.ConvertValue<float,3>(draco::AttributeValueIndex(i),&tmp[i][0])) return;
        }
        attD=std::move(tmp);
    }
    // 解析顶点
    const draco::PointAttribute* posAtt=nullptr;
    std::vector<Eigen::Vector3> points;
    for(int i=0;i<dracomesh->num_attributes();++i){
        const draco::PointAttribute* pAtt=dracomesh->attribute(i);
        switch(pAtt->attribute_type()){
            case draco::PointAttribute::POSITION:
                posAtt=pAtt;
                dump_attribute_to_vec3(*pAtt,points);
                break;
        }
    }
    vertexes=points;
    // 解析面片
    faces.resize(dracomesh->num_faces());
    for(int i=0;i<dracomesh->num_faces();++i){
        for(int j=0;j<3;++j){
            const draco::PointIndex idx=dracomesh->face(draco::FaceIndex(i))[j];
            faces[i][j]=posAtt->mapped_index(idx).value();
        }
    } 
    return true;
}

以上就是利用Python和C++实现解析gltf文件的详细内容,更多关于Python解析gltf文件的资料请关注脚本之家其它相关文章!

相关文章

  • Python 元组(Tuple)操作详解

    Python 元组(Tuple)操作详解

    Python的元组与列表类似,不同之处在于元组的元素不能修改,元组使用小括号,列表使用方括号,元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可
    2014-03-03
  • Pytorch实现网络部分层的固定不进行回传更新问题及思路详解

    Pytorch实现网络部分层的固定不进行回传更新问题及思路详解

    这篇文章主要介绍了Pytorch实现网络部分层的固定不进行回传更新,实现思路就是利用tensor的requires_grad,每一个tensor都有自己的requires_grad成员,值只能为True和False,具体内容详情跟随小编一起看看吧
    2021-08-08
  • PyCharm 接入 DeepSeek最新完整教程

    PyCharm 接入 DeepSeek最新完整教程

    文章介绍了DeepSeek-V3模型的性能提升以及如何在PyCharm中接入和使用DeepSeek进行代码开发,本文通过图文并茂的形式给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2025-02-02
  • Django框架model模型对象验证实现方法分析

    Django框架model模型对象验证实现方法分析

    这篇文章主要介绍了Django框架model模型对象验证实现方法,结合实例形式分析了Django框架model模型对象验证相关原理、实现步骤及操作注意事项,需要的朋友可以参考下
    2019-10-10
  • pip install urllib2不能安装的解决方法

    pip install urllib2不能安装的解决方法

    今天小编就为大家分享一篇pip install urllib2不能安装的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-06-06
  • python如何利用turtle绘制正方形

    python如何利用turtle绘制正方形

    这篇文章主要介绍了python如何利用turtle绘制正方形,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • Pygame框架实现飞机大战

    Pygame框架实现飞机大战

    这篇文章主要为大家详细介绍了Pygame框架实现飞机大战,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-08-08
  • 解决python xlrd无法读取excel文件的问题

    解决python xlrd无法读取excel文件的问题

    今天小编就为大家分享一篇解决python xlrd无法读取excel文件的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-12-12
  • 重构Python代码的六个实例

    重构Python代码的六个实例

    这篇文章主要给大家介绍了关于重构Python代码的六个实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Flask应用中执行指定JavaScript脚本的6种方法

    Flask应用中执行指定JavaScript脚本的6种方法

    在 Flask 应用中执行指定 JavaScript 脚本,需结合后端路由,模板渲染及前后端交互技术,本文主要介绍了六种核心方法及其实现细节,大家可以根据需要进行选择
    2025-06-06

最新评论