glTF 文件详解

glTF 文件详解

_

🎯 glTF 是什么

glTF (GL Transmission Format) 是 Khronos Group 开发的 3D 场景和模型的标准格式,被称为 "3D 界的 JPEG"


📦 文件类型

1️⃣ glTF 的三种格式

格式

扩展名

说明

标准 glTF

.gltf + .bin + 纹理

JSON + 二进制数据 + 图片文件

二进制 glTF

.glb

单个二进制文件(推荐)

嵌入式 glTF

.gltf

所有数据嵌入 JSON(不常用)

🎭 动画绑定原理

核心概念

{
  "nodes": [...]        // 骨骼节点
  "meshes": [...]       // 网格模型
  "skins": [...]        // 蒙皮(绑定骨骼和模型)
  "animations": [...]   // 动画数据
}

🔗 动画绑定流程

1️⃣ 定义骨骼层级 (nodes)

"nodes": [
  { 
    "name": "Actor",                // 根节点
    "children": [1, 2, 3]           // 子节点索引
  },
  { 
    "name": "mixamorig:Hips",      // 骨盆骨骼
    "translation": [0.002, 0.989, -0.001],
    "rotation": [-0.031, -0.046, -0.029, 0.998],
    "children": [4, 47, 51]         // 脊柱、右腿、左腿
  },
  { 
    "name": "mixamorig:Spine",     // 脊柱
    "translation": [0, 0.099, -0.012],
    "rotation": [0.029, 0.012, 0.022, 0.999],
    "children": [5]                 // 上脊柱
  }
  // ... 更多骨骼
]

骨骼树结构:

Actor (根)
└── Hips (骨盆)
    ├── Spine (脊柱)
    │   └── Spine1 → Spine2 → Neck → Head
    ├── RightUpLeg → RightLeg → RightFoot
    └── LeftUpLeg → LeftLeg → LeftFoot

2️⃣ 蒙皮绑定 (skins)

网格顶点绑定到骨骼上:

"skins": [
  {
    "name": "skeleton #0",
    "skeleton": 0,                    // 根骨骼节点索引
    "joints": [0, 3, 4, 5, ...],     // 参与动画的骨骼索引
    "inverseBindMatrices": 16         // 初始绑定姿态的逆矩阵
  }
]

作用:

  • 告诉每个顶点受哪些骨骼影响

  • 通过权重混合多个骨骼的变换


3️⃣ 动画通道 (animations)

定义每个骨骼在不同时间的位置、旋转、缩放:

"animations": [
  {
    "name": "Standard_Walk",      // 走路动画
    "channels": [
      {
        "sampler": 0,              // 使用哪个采样器
        "target": {
          "node": 3,               // 目标骨骼(Hips)
          "path": "translation"    // 动画类型:位置
        }
      },
      {
        "sampler": 1,
        "target": {
          "node": 3,
          "path": "rotation"       // 动画类型:旋转
        }
      }
      // ... 每个骨骼的 translation、rotation、scale
    ],
    "samplers": [
      {
        "input": 18,               // 时间数据索引
        "output": 19               // 位置数据索引
      }
    ]
  }
]

🎬 动画播放过程

流程图

1. 加载 glTF 文件
   ↓
2. 解析骨骼结构 (nodes)
   ↓
3. 创建蒙皮 (skins) → 绑定顶点到骨骼
   ↓
4. 读取动画数据 (animations)
   ↓
5. 每帧更新:
   a. 根据时间计算每个骨骼的变换矩阵
   b. 通过蒙皮权重影响顶点位置
   c. 重新渲染模型

📊 数据访问示例

时间轴数据 (accessor)

"accessors": [
  {
    "bufferView": 6,
    "componentType": 5126,    // FLOAT
    "count": 36,              // 36 个关键帧
    "max": [1.16666663],      // 动画时长 1.17 秒
    "min": [0.0],
    "type": "SCALAR",         // 标量(时间)
    "name": "accessorAnimationInput"
  }
]

位置数据 (accessor)

{
  "bufferView": 7,
  "componentType": 5126,      // FLOAT
  "count": 36,                // 36 个位置
  "type": "VEC3",             // 三维向量 (x, y, z)
  "name": "accessorAnimationPositions"
}

🔧 在 Three.js 中的使用

加载和播放动画

import { useGLTF, useAnimations } from '@react-three/drei';

function Player() {
  const { scene, animations } = useGLTF('/models/Actor/actor.gltf');
  const { actions, names } = useAnimations(animations, scene);
  
  // animations 包含:
  // [
  //   { name: "Standard_Walk", duration: 1.167, ... },
  //   { name: "Idle", duration: 8.333, ... },
  //   { name: "Standard_Run", duration: 0.733, ... }
  // ]
  
  // 播放走路动画
  actions['Standard_Walk']?.play();
}

每个动画控制 156 个通道

// 每个骨骼 × 3 个属性 = 通道数
53 个骨骼 × 3 (translation, rotation, scale) = 159 个通道

📝 完整的动画绑定链路

1. 骨骼定义 (nodes)
   ├── Hips (索引 3)
   ├── Spine (索引 4)
   └── ... (共 53 个骨骼)
   
2. 蒙皮绑定 (skins)
   ├── 顶点权重: vertex[0] → 80% Spine + 20% Hips
   └── inverseBindMatrices: 初始姿态
   
3. 动画数据 (animations)
   ├── 时间轴: [0, 0.033, 0.066, ..., 1.167]
   ├── Hips.translation: [(0, 0.989, -0.001), ...]
   └── Hips.rotation: [(-0.031, -0.046, -0.029, 0.998), ...]
   
4. 运行时更新
   ├── t = 0.5 秒 → 插值计算骨骼变换
   ├── 骨骼变换 → 影响顶点位置
   └── 渲染新的模型姿态

🎓 总结

组件

作用

nodes

定义骨骼层级结构

meshes

模型的几何体和材质

skins

绑定顶点到骨骼(蒙皮)

animations

记录骨骼随时间的变换

accessors

实际的二进制数据索引

glTF 通过这种分层设计,实现了高效的 模型 + 动画 存储和传输! 🚀

项目代码制作制品库以及上传 2025-12-30
四元数 (Quaternion) 深度解析 2025-12-30

评论区