# xr-frame里的GLTF
# GLTF资源
GLTF模型需要先通过Loader加载进小程序中,才可以渲染。
<xr-asset-load type="gltf" asset-id="gltfModel" src="/assets/xxx.gltf" />
在xr-asset-load标签中:
- type需为"gltf"
- src可以填写.gltf文件也可以填写.glb文件
- 使用.gltf文件的时候,需要确保将附属资源与.gltf文件放在同一路径下(保持原有相对结构)
该Loader加载完成后会返回一个GLTFModel资源,可以用来传递给GLTF组件来实例化成场景元素和Mesh组件等。
Loader加载过程中会进行:
- .gltf和.glb文件的数据解析
- 所有附属资源的下载
- 将模型数据重新拼接成xr-frame渲染数据
所有步骤执行完毕后才算是加载完成。由于步骤3的存在,所以比较复杂的GLTF模型就算有缓存,也可能加载得比较缓慢。使用xr-frame-toolkit离线预处理模型可以解决这个问题。
# Loader选项
添加选项的方法:
<xr-asset-load ... options="preserveRaw: true" />
| 选项名 | 用途 | 备注 |
|---|---|---|
| preserveRaw | 加载完后,在GLTFModel资源中保留原始json,保存在jsonRaw字段中。 | 可通过scene.assets.getAsset("gltf", "xxx")来获取GLTFModel资源。 |
| ignoreError | 可用于渲染超出限制的模型。 | 使用方法参考渲染超出限制的模型。 |
# GLTF组件
GLTF组件可以渲染一个已经加载完成的GLTFModel资源。
使用xr-gltf标签可以为标签自动创建GLTF组件:
<xr-gltf id="myGLTF" model="gltfModel"></xr-gltf>
🚫
xr-gltf标签对应的元素为Shadow元素,所以请不要在xml里为xr-gltf添加子标签。点击这里阅读Shadow元素的详细说明。
标签属性映射:
| 属性名 | 组件.属性 | 备注 |
|---|---|---|
| model | GLTF.model | 使用的GLTFModel资源,对应xr-asset-load标签中的asset-id属性 |
| cast-shadow | GLTF.castShadow | GLTF模型是否投射阴影 |
| receive-shadow | GLTF.receiveShadow | GLTF模型是否接受阴影 |
GLTF组件事件:
| 事件名 | 描述 | 事件回调参数 | 备注 |
|---|---|---|---|
| gltf-loaded | GLTF组件将GLTFModel渲染完毕后触发。 | { target: Element } | - |
# 使用TS脚本来修改GLTF
GLTF组件提供了一系列接口来让用户操作xr-frame为GLTF模型生成的内部子树,开发者也可以用这些接口来动态修改glTF模型的颜色、纹理等材质属性。
🚫 不可以手动添加或删除节点,只能操作节点上已有的组件。
| 接口名 | 描述 | 备注 |
|---|---|---|
| getInternalNodeByName | 根据GLTFNode节点的name字段来获取xr-frame对应的Element | |
| get meshes | 获取生成的所有Mesh组件 | |
| getPrimitivesByNodeName | 根据GLTFNode节点的name字段来获取其下的所有Mesh组件 | 2.28.1版本加入;详见API文档 |
| getPrimitivesByMeshName | 根据GLTFMesh节点的name字段来获取所有相关的Mesh组件 | 2.28.1版本加入;详见API文档 |
# 例:使用TS脚本来修改GLTF贴图
以下代码在GLTF模型渲染完毕后修改其中某个mesh的贴图:
// gltf
{
...
"nodes": [{
"mesh": 0,
"name": "Banana"
}],
...
}
// xml
<xr-gltf id="myGLTF" model="gltfModel" bind:gltf-loaded="handleGLTFLoaded"></xr-gltf>
// ts
function handleGLTFLoaded({ detail }) {
const el = detail.value.target;
const gltf = el.getComponent("gltf");
const newMat = this.scene.assets.getAsset("texture", "...texture name...");
for (const mesh of gltf.getPrimitivesByNodeName("Banana")) {
mesh.material.setTexture("u_baseColorMap", newMat);
}
}
# GLTF动画
如果GLTF模型有自带的动画,就会在当前元素下自动创建一个Animator组件,并将GLTF模型内的动画片段加入到这个Animator组件中。
如果
GLTF组件所在的元素本来已经拥有Animator组件,就不会新建,而是直接使用这个Animator组件。 在标签上添加anim-autoplay属性可以自动播放GLTF模型内的动画,会播放GLTF内的所有动画片段:
<xr-gltf id="myGLTF" model="gltfModel" anim-autoplay></xr-gltf>
# 例:使用TS脚本来控制GLTF动画
如果你只想播放GLTF模型里的某一个动画片段,或者想切换播放的动画片段,可以使用TS脚本来控制。
例如以下代码在GLTF模型渲染完毕后播放名为idle的动画:
// xml
<xr-gltf id="myGLTF" model="gltfModel" bind:gltf-loaded="handleGLTFLoaded"></xr-gltf>
// ts
function handleGLTFLoaded({ detail }) {
const el = detail.value.target;
const animator = el.getComponent("animator");
animator.play("idle");
}
动画的名字idle,对应的是.gltf文件中animations数组节点的每一个元素的name属性(参考官方文档)。
如果.gltf文件内的动画节点没有name属性,则会自动给动画分配名字gltfAnimation#x,其中x是数字编号,从0开始:gltfAnimation#0, gltfAnimation#1, 以此类推。
如果.gltf文件内有多个
name相同的动画,也会使用这个规则,在名称后面添加#x作为动画名称,以此来区别。此时如果用不加#x的原始名称来索引动画,会返回#0的动画。
# Morph Target
xr-frame支持Morph Target动画,但是对target的数量有限制,同一个模型最多使用8个target。
这里的target概念有别于.gltf文件内的target节点:.gltf文件内的一个同时拥有POSITION和NORMAL属性的target节点,在xr-frame中算作2个target(不影响渲染效果)。
# GLTF扩展
GLTF模型可以使用扩展,所使用的扩展会在.gltf文件内extensionsUsed和extensionsRequired节点下列出。
extensionsUsed中声明的扩展非必需。如果xr-frame目前不支持该扩展,GLTF模型会以基础样式渲染,并在console中生成相关warning。
extensionsRequired中声明的扩展为必需。如果xr-frame目前不支持该扩展,GLTF模型将不会渲染,并在console中生成相关error。
# xr-frame已支持扩展
- KHR_materials_unlit
- KHR_materials_clearcoat
- KHR_materials_ior
- KHR_materials_specular
- KHR_materials_pbrSpecularGlossiness
- SEIN_processed
- *WX_processed_model
- KHR_draco_mesh_compression(2.32.1及以后,仅限真机,工具上暂时无法加载)
- *WX_compress_textures:支持压缩纹理,需要配合xr-frame-toolkit一起使用,在基础库版本
3.0.1以上支持。
*号标注的扩展为xr-frame内部扩展,主要被xr-frame-cli使用。
# GLTF模型的限制
GLTF模型需要满足以下条件才能正常渲染:
- 纹理使用的顶点
UV不超过2个; - 使用的顶点
JOINTS不超过1个; - 使用的顶点
WEIGHTS不超过1个; - 不使用
sparse accessor; accessor的normalized属性不为true;morph targets数量小于等于8个;morph的属性为POSITION,NORMAL或TANGENT;图元类型不为LINE_LOOP或TRIANGLE_FAN;
经测试,只有少数模型会超出限制,大多数模型都可以正常渲染。并且随着项目迭代,未来将会解除或者放宽一些条件。
# 渲染超出限制的模型
(基础库2.31.0及以后)
如果模型超出上方限制,使用GLTF组件的时候会无法渲染,并在console中报错:(例)
无论如何也想要渲染这个模型的话,可以在<xr-asset-load>标签中填写ignoreError属性:
<xr-asset-load type="gltf" asset-id="..." src="..." options="ignoreError: 10602"/>
ignoreError属性可以接受一系列由空格分隔的数字,数字对应着console中模型报错信息里的编号。
可以用
ignoreError: -1来忽略所有错误(不推荐)。