# 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
来忽略所有错误(不推荐)。