用C++或者Python解析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("

二、C++解析

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

#include
#include

// 读取gltf文件
bool parse_gltf_from_file(const std::string& filename,std::unique_ptr& mesh){
    draco::GltfDecoder gltfDec;
    draco::StatusOr> stormesh=gltfDec.DecodeFromFile(filename);
    if(!stormesh.ok()){
        return false;
    }
    std::unique_ptr pDracomesh=std::move(stormesh).value();
    std::cout<<"faces num:"<num_faces()<& dracomesh,
                        std::vector& vertexes,
                        std::vector& faces){
    auto dump_attribute_to_vec3=[](const draco::PointAttribute& att,std::vector& attD){
        if(att.size()==0) return;
        std::vector tmp(att.size());
        for(int i=0;i(draco::AttributeValueIndex(i),&tmp[i][0])) return;
        }
        attD=std::move(tmp);
    }

    // 解析顶点
    const draco::PointAttribute* posAtt=nullptr;
    std::vector points;
    for(int i=0;inum_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;inum_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;
}

你可能感兴趣的:(工程技能,c++,python,开发语言)