Chapter 214 · 3D 图形

glTF 模型加载

glTF 2.0 是 XGE 3D 的模型交换格式:运行库直接消费 .gltf/.glb,一次加载、多次实例化,共享网格与材质。

214

加载与实例化

xge3d_model *pModel;
xge3dModelLoad("assets/explorer.gltf", &pModel);

// 实例化进场景:一个模型可以生成任意多个实例
xge3d_node_t tActor;
xge3dModelInstantiate(pScene, pModel, (xge3d_node_t){0}, &tActor);

// 实例持有模型引用之后,加载方即可释放自己的引用
xge3dModelFree(pModel);
共享的意义:实例保留(retain)模型的共享网格与材质——同一角色生成 100 个实例,GPU 里只有一份顶点数据。静态且兼容的不透明网格还会被自动合批实例化绘制(可在渲染描述里关闭)。

内存输入与 base_uri

资源包或网络流的场景用 xge3dModelLoadMemory(data, size, base_uri, &model)——数据被复制,base_uri 是解析相对 buffer/贴图引用的逻辑文件名。加载走 xgeResource 通道,因此自定义资源提供者同样生效。遇到未支持的 required 扩展时返回 UNSUPPORTED,不会产出半成品实例。

检查模型内容

xge3d_model_info_t tInfo = xge3dModelInfo(pModel);
// node_count / primitive_count / material_count /
// animation_count / skin_count / truncated_weight_vertices

// 按源索引取节点名与共享材质(借用指针,随模型存亡)
const char *sName = xge3dModelNodeName(pModel, 0);
const xge3d_material *pMat = xge3dModelMaterial(pModel, 0);

// 找到实例中对应的节点,做挂点或定制
xge3d_node_t tNode;
xge3dModelInstanceNode(pScene, tActor, 3, &tNode);

源节点索引在模型生命周期内稳定,与 ModelInfo、ModelNodeName 一致;不在所选 glTF scene 里的节点会返回 NOT_FOUND。骨骼动画相关的 xge3dModelSkinJointNode 见第 219 章。

离线转换工具链

FBX/BVH 素材由独立的 C 离线工具转换为 glTF 与动作剪辑,运行库只消费标准 glTF 2.0/GLB——转换工具、ufbx 与原始素材不进入运行库体积。人形重定向在离线阶段完成(两套不同参考姿态/轴/比例的目标骨架均已验证),运行时按名字或源索引绑定。

本章 API 速查

函数 / 类型说明
xge3dModelLoad(uri, out)glTF 2.0 / GLB 文件加载(xgeResource 通道)
xge3dModelLoadMemory(data, size, base_uri, out)内存输入,数据复制
xge3dModelInstantiate(scene, model, parent, out)实例化;失败不产出部分实例
xge3dModelInstanceNode(scene, root, index, out)按源索引取实例内节点
xge3dModelInfo / NodeName / Material内容检查(借用指针)
xge3dModelFree释放加载方引用;实例仍持有
行走示例中的 glTF 角色与岛屿
图:examples/xge_3d_walk 中加载的 explorer.gltf 角色(程序化生成的确定性测试资产),站在程序化岛屿地形上。

要点与常见陷阱

  • truncated_weight_vertices > 0 表示有顶点的蒙皮权重被截断到 4 根骨骼——检查它来发现建模侧问题。
  • 不要在实例存活时释放模型的 GPU 期望——模型句柄可以 Free,但贴图等资源的释放要遵守上下文线程规则。
  • 失败即清空——加载失败会清掉输出句柄,不会留下可用的半成品。

进阶练习

  1. 加载同一模型实例化 3 次,摆成不同姿势与缩放,观察 DrawCall 是否仍共享。
  2. 用 ModelNodeName 找到手部节点,挂一个小立方体网格作"武器"。
  3. 统计 ModelInfo 的 animation_count,为第 219 章做准备。