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

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

一、初识 GLTF 文件

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

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. scenesnodes

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));
2. meshesprimitives

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. buffersbufferViews

顶点、索引等数据存储在二进制文件中,通过 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);
4. materialstextures

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

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

关联流程

Material --> Texture --> Image (texture.png)
三、构建图形化示意图

以下是关联关系的总体结构图:

  1. 顶层结构:场景与节点

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

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

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文件
  1. NSDT gltfviewer gltf glb文件的在线预览

  2. NSDT 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 文件,不妨用本文的示例从零开始解析一次!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值