利用Python和C++實現(xiàn)解析gltf文件
gltf是類似于stl、obj、ply等常見的3D對象存儲格式,它被設(shè)計出來是為了便于渲染的數(shù)據(jù)轉(zhuǎn)換和傳輸。如果你的瀏覽器可以連接外網(wǎng),可以通過 glTF Viewer 網(wǎng)址打開瀏覽gltf的3D對象。這里介紹兩種語言下從gltf拿到網(wǎng)格的頂點和面片數(shù)據(jù)。
一、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屬性,然后在網(wǎng)上找了下面的代碼是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,這個庫是開源的,網(wǎng)上可以下載,有了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; } //解析出頂點和面片數(shù)據(jù) 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++實現(xiàn)解析gltf文件的詳細內(nèi)容,更多關(guān)于Python解析gltf文件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python flask web服務(wù)實現(xiàn)更換默認端口和IP的方法
今天小編就為大家分享一篇python flask web服務(wù)實現(xiàn)更換默認端口和IP的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07Django實現(xiàn)列表頁商品數(shù)據(jù)返回教程
這篇文章主要介紹了Django實現(xiàn)列表頁商品數(shù)據(jù)返回教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-0410分鐘教你用python動畫演示深度優(yōu)先算法搜尋逃出迷宮的路徑
這篇文章主要介紹了10分鐘教你用python動畫演示深度優(yōu)先算法搜尋逃出迷宮的路徑,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-08-08給Python的Django框架下搭建的BLOG添加RSS功能的教程
這篇文章主要介紹了給Python的Django框架下搭建的BLOG添加RSS功能的教程,示例代碼非常簡單,需要的朋友可以參考下2015-04-04