探索 GLTF 文件格式规范:从零开始解析

505 阅读4分钟

GLTF(GL Transmission Format)是一种专为高效传输和渲染 3D 模型设计的文件格式。今天,我们将以一次深入解析 GLTF 文件的过程,带你全面了解它的结构、关联方式以及使用方式。

一、初识 GLTF 文件 在开始我的介绍之前,我先放一张官方的图片,上面使用图形化的方式描述了gltf的格式规范(英文的),各位看官可以在官方网站上找到这张图:

image.png

GLTF 文件通常以 .gltf 或 .glb 作为后缀名,其中 .gltf 是 JSON 格式文件,可能会附带二进制文件(.bin)和图片素材;而 .glb 则是将所有数据整合成一个二进制文件。

解析的第一步是加载 JSON 文件,我们以 Node.js 为例:

const fs = require('fs');

const gltfPath = './model.gltf'; const gltfData = JSON.parse(fs.readFileSync(gltfPath, 'utf-8')); console.log('GLTF 文件内容:', gltfData); 读取后的文件内容是一个包含多个字段的 JSON 结构:asset 描述文件信息,scenes 定义场景结构,nodes 是场景中具体的节点等。

二、核心数据结构与关联

  1. scenes 和 nodes scenes 是 GLTF 的入口,每个场景会引用若干节点(nodes)。

"scenes": [ { "nodes": [0] } ], "nodes": [ { "name": "RootNode", "children": [1, 2] }, { "mesh": 0 }, { "mesh": 1 } ]

关联关系图:

Scene (0) --> Node (0: RootNode) |--> Node (1: Mesh 0) |--> Node (2: Mesh 1) 在代码中,我们可以递归解析场景和节点:

function traverseNodes(nodes, currentNodeIndex) { const node = nodes[currentNodeIndex]; console.log('Node:', node.name); ​ if (node.children) { node.children.forEach(childIndex => traverseNodes(nodes, childIndex)); } } ​ const nodes = gltfData.nodes; gltfData.scenes[0].nodes.forEach(nodeIndex => traverseNodes(nodes, nodeIndex));

  1. meshes 和 primitives meshes 定义几何数据,它由一个或多个 primitives 构成,而 primitives 包含顶点属性和材质信息。

"meshes": [ { "primitives": [ { "attributes": { "POSITION": 0, "NORMAL": 1 }, "indices": 2, "material": 0 } ] } ] POSITION: 定义顶点位置。

NORMAL: 定义法线方向。

indices: 定义三角形索引。

关联关系图:

Mesh --> Primitive --> Attributes (POSITION, NORMAL, ...) --> Accessors --> BufferViews --> Buffers 3. buffers 和 bufferViews 顶点、索引等数据存储在二进制文件中,通过 buffers 字段引用。

"buffers": [ { "uri": "model.bin", "byteLength": 1024 } ], "bufferViews": [ { "buffer": 0, "byteOffset": 0, "byteLength": 512, "target": 34963 } ] 关联示意图:

Buffer (model.bin) --> BufferView (byteOffset, byteLength) 通过 Node.js 加载并解析 buffer 数据:

const bufferData = fs.readFileSync('./model.bin'); const bufferView = gltfData.bufferViews[0]; const extractedData = bufferData.slice( bufferView.byteOffset, bufferView.byteOffset + bufferView.byteLength ); console.log('提取的二进制数据:', extractedData);

  1. materials 和 textures materials 定义了模型的材质属性,包括金属度、粗糙度等,而 textures 则关联了图片数据。

"materials": [ { "pbrMetallicRoughness": { "baseColorTexture": { "index": 0 } } } ], "textures": [ { "source": 0 } ], "images": [ { "uri": "texture.png" } ]

关联流程:

Material --> Texture --> Image (texture.png) 三、构建图形化示意图 以下是关联关系的总体结构图:

顶层结构:场景与节点

Scene --> Nodes --> Meshes 几何数据路径

Mesh --> Primitive --> Attributes --> Accessors --> BufferViews --> Buffers 材质与纹理路径

Material --> Texture --> Image 四、完整解析示例 将以上模块结合起来,我们可以解析完整的 GLTF 模型。

function parseGLTF(gltfPath, binPath) { const gltfData = JSON.parse(fs.readFileSync(gltfPath, 'utf-8')); const bufferData = fs.readFileSync(binPath); ​ gltfData.scenes.forEach(scene => { console.log('Scene:', scene); scene.nodes.forEach(nodeIndex => { traverseNodes(gltfData.nodes, nodeIndex); }); }); ​ gltfData.meshes.forEach(mesh => { mesh.primitives.forEach(primitive => { const positionAccessor = gltfData.accessors[primitive.attributes.POSITION]; const positionBufferView = gltfData.bufferViews[positionAccessor.bufferView]; const positionData = bufferData.slice( positionBufferView.byteOffset, positionBufferView.byteOffset + positionBufferView.byteLength ); console.log('顶点位置数据:', positionData); }); }); } ​ parseGLTF('./model.gltf', './model.bin');

通过上述代码,我们完成了从场景到几何数据、再到材质与纹理的完整解析。

五、在线预览GLTF 3D文件 NSDT gltfviewer gltf glb文件的在线预览

[NSDT 3Dconvert](3D模型在线转换 - GLB|GLTF|PLY|STL|OBJ|OFF|DAE|FBX|DXF|IFC|XYZ|PCD|LAS|LAZ|STP|STEP|3DXML|IGES|IGS|SHP|GEOJSON|XAML|PTS|ASC|BREP|FCSTD|BIM|USDZ|PDB|VTK|SVG|WRL|3DM|3DS|AMF|3MF|DWG|JSON|RFA|RVT|AC|ZGL|X|TER|SMD|SIB|Q3O|Q3S|OGEX|NFF|MS3D|MDL|MD5MESH|MD2|LWS|HMP|IRRMESH|CSV|GPKG|X3D|VRML|B3DM|XYZRGB|X3DV|VTU|URDF|UGRID|SU2|BABYLON|AC3D|BVH|ASE - 3Dconvert)是一个可以进行3D模型格式转换的在线工具,支持多种3D模型格式在线预览和格式转换,支持将模型转换为GLTF、OBJ、GLB、PLY、STL、XYZ、OFF、DAE等格式。 NSDT 3Dconvert支持GLB、GLTF、PLY、STL、OBJ、OFF、DAE、FBX、DXF、IFC、XYZ、PCD、 LAS、LAZ、STP、STEP、3DXML、IGES、IGS、SHP、GEOJSON、XAML、PTS、ASC、 BREP、FCSTD、BIM、USDZ和PDB等源格式。 NSDT 3Dconvert提供Revit、MicroStation等设计软件插件,通过插件将RVT、RFA、DGN等设计文件进行在线预览和格式转换。

结语 GLTF 文件格式通过其模块化设计,提供了一种高效传输和渲染 3D 模型的方式。从场景节点到几何数据、从材质到纹理,每个部分都有清晰的关联路径。这种结构化的格式不仅易于解析,也为高性能渲染提供了保障。如果你还没有尝试过 GLTF 文件,不妨用本文的示例从零开始解析一次!

原文链接:blog.csdn.net/qq_38617050…