微信小程序xr-frame GLTF

前言:什么是GLTF?

原文解释是:GLTF是一种被广泛使用的文件格式,用来储存3D模型和3D场景。在xr-frame里你可以非常轻松地引入任意GLTF模型,并将其渲染出来。想要更详细的讲解:glTF -传输格式;

优势(摘自GLTF介绍 | 微信开放文档 (qq.com)):

  •  单一文件,完整场景

使用GLTF打包后的GLB文件,可将一整个场景的所有要素包揽进去。轻松管理你的3D资源。

  •  成熟生态,海量资源

来自全世界的优秀创作者,在不同社区中分享作品。配合xr-frame的渲染能力,简直是随取随用。

  • 以下使用方法、属性、事件、动画等 (摘自GLTF介绍 | 微信开放文档 (qq.com))

1.GLTF模型需要先通过Loader加载进小程序中,才可以渲染。

2.GLTF组件

GLTF组件可以渲染一个已经加载完成的GLTFModel资源。

使用xr-gltf标签可以为标签自动创建GLTF组件

 3.标签属性

属性名 组件.属性 备注
model GLTF.model 使用的GLTFModel资源,对应xr-asset-load标签中的asset-id属性
cast-shadow GLTF.castShadow GLTF模型是否投射阴影
receive-shadow GLTF.receiveShadow GLTF模型是否接受阴影

 4.事件:

事件名 描述 事件回调参数 备注
gltf-loaded GLTF组件将GLTFModel渲染完毕后触发。 { target: Element } -

5.修改 :

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文档

用法:修改GLTF贴图

// gltf信息
{
    ...
    "nodes": [{
      "mesh": 0,
      "name": "Banana"
    }],
    ...
}
function handleGLTFLoaded({ detail }) {
    const el = detail.value.target;
    //获取名字为nana的mesh
    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);
    }
}

6.动画

如果GLTF模型有自带的动画,就会在当前元素下自动创建一个Animator组件,并将GLTF模型内的动画片段加入到这个Animator组件中。 

如果GLTF组件所在的元素本来已经拥有Animator组件,就不会新建,而是直接使用这个Animator组件。 在标签上添加anim-autoplay属性可以自动播放GLTF模型内的动画,会播放GLTF内的所有动画片段:

  •  自身就有动画直接加 anim-autoplay


  • 使用animator实现动画

1) 设置动画json

{
  "keyframe": {
    "parent": {
      "0": {
        "rotation": [0, 0, 0]
      },
      "100": {
        "rotation": [0, 6.28, 0]
      }
    },
    "child": {
      "0": {
        "position.y": -0.5
      },
      "100": {
        "position.y": 1.5
      }
    }
  },
  "animation": {
    "parent": {
      "keyframe": "parent",
      "duration": 8,
      "ease": "linear",
      "loop": -1
    },
    "child": {
      "keyframe": "child",
      "duration": 4,
      "ease": "ease-in-out",
      "direction": "both",
      "loop": -1
    }
  }
}

2)加载动画资源

 

3)绑定动画

  

4)控制动画

如果你只想播放GLTF模型里的某一个动画片段,或者想切换播放的动画片段,可以使用TS脚本来控制。

例如以下代码在GLTF模型渲染完毕后播放名为idle的动画:

// xml

// ts
function handleGLTFLoaded({ detail }) {
    const el = detail.value.target;
    const animator = el.getComponent("animator");
    animator.play("idle");
}

动画的名字idle,对应的是.gltf文件中animations数组节点的每一个元素的name属性(参考官方文档)。

7.Morph Target:(demo详见下篇文章)

1.什么是Morph Target?详见:静态网格体变形目标 | 虚幻引擎文档 (unrealengine.com)

xr-frame支持Morph Target动画,但是对target的数量有限制,同一个模型最多使用8个target

这里的target概念有别于.gltf文件内的target节点:.gltf文件内的一个同时拥有POSITIONNORMAL属性的target节点,在xr-frame中算作2个target(不影响渲染效果)。

8.注意事项(gltf模型限制)

GLTF模型需要满足以下条件才能正常渲染:

  • 纹理使用的顶点UV不超过2个;
  • 使用的顶点JOINTS不超过1个;
  • 使用的顶点WEIGHTS不超过1个;
  • 不使用sparse accessor
  • accessornormalized属性不为true
  • morph targets数量小于等于8个;
  • morph的属性为POSITION,NORMALTANGENT
  • 图元类型不为LINE_LOOPTRIANGLE_FAN;

经测试,只有少数模型会超出限制,大多数模型都可以正常渲染。并且随着项目迭代,未来将会解除或者放宽一些条件。

9.典型案例(多动画显示demo来源于微信开放文档)

1)wxml部分


  
    
    
    
    
  
  
    
    
    
    
      
        
      
    
    
  
  
    
    
  

2)json动画部分

{
  "keyframe": {
    "parent": {
      "0": {
        "rotation": [0, 0, 0]
      },
      "100": {
        "rotation": [0, 6.28, 0]
      }
    },
    "child": {
      "0": {
        "position.y": -0.5
      },
      "100": {
        "position.y": 1.5
      }
    }
  },
  "animation": {
    "parent": {
      "keyframe": "parent",
      "duration": 8,
      "ease": "linear",
      "loop": -1
    },
    "child": {
      "keyframe": "child",
      "duration": 4,
      "ease": "ease-in-out",
      "direction": "both",
      "loop": -1
    }
  }
}

3)js部分

Component({
  properties: {
    a: Number,
  },
  data: {
    loaded: false
  },
  lifetimes: {
    attached() {
      console.log('data.a', this.data.a) // expected 123
    }
  },
  methods: {
    handleReady: function({detail}) {
      this.scene = detail.value;
      console.log('scene', detail.value);
    },
    handleAssetsProgress: function({detail}) {
      console.log('assets progress', detail.value);
    },
    handleAssetsLoaded: function({detail}) {
      console.log('assets loaded', detail.value);
      this.setData({loaded: true});
    },
    handleRaf: function({detail}) {
      console.log('raf', detail.value);
    }
  }
})

4)效果展示

xr-frame gltf动画

你可能感兴趣的:(微信小程序,gltf,xr-frame)