微信小程序xr-frame GLTF

前言:什么是GLTF?

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

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

  •  单一文件,完整场景

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

  •  成熟生态,海量资源

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

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

<xr-asset-load type="gltf" asset-id="gltfModel" src="/assets/xxx.gltf" />

2.GLTF组件

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

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

<xr-gltf id="myGLTF" model="gltfModel"></xr-gltf>

 3.标签属性

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

 4.事件:

事件名描述事件回调参数备注
gltf-loadedGLTF组件将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"
    }],
    ...
}
<xr-gltf id="myGLTF" model="gltfModel" bind:gltf-loaded="handleGLTFLoaded"></xr-gltf>
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

<xr-gltf id="myGLTF" model="gltfModel" anim-autoplay></xr-gltf>
  • 使用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)加载动画资源

 <xr-asset-load asset-id="anim" type="keyframe" src="/assets/animation/miku-kawaii-animation.json"/>

3)绑定动画

  <xr-node anim-keyframe="anim" anim-autoplay="clip:parent">

4)控制动画

如果你只想播放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属性(参考官方文档)。

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部分

<xr-scene id="xr-scene" bind:ready="handleReady">
  <xr-assets bind:progress="handleAssetsProgress" bind:loaded="handleAssetsLoaded">
    <xr-asset-load asset-id="anim" type="keyframe" src="/assets/animation/miku-kawaii-animation.json"/>
    <xr-asset-load type="gltf" asset-id="cloud-station" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/cloud-station/index.glb" />
    <xr-asset-load type="gltf" asset-id="miku-kawaii" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/shiteyanyo-hatsune-miku/index.glb" />
    <xr-asset-load type="gltf" asset-id="miku" src="https://mmbizwxaminiprogram-1258344707.cos.ap-guangzhou.myqcloud.com/xr-frame/demo/miku.glb" />
  </xr-assets>
  <xr-node>
    <xr-node node-id="target" position="0 1 0" />
    <xr-gltf position="0 0 0" scale="1 1 1" model="cloud-station" anim-autoplay></xr-gltf>
    <xr-gltf position="1.8 -0.5 1.5" scale="0.12 0.12 0.12" rotation="0 180 0" model="miku" anim-autoplay></xr-gltf>
    <xr-node anim-keyframe="anim" anim-autoplay="clip:parent">
      <xr-node position="0 -0.5 3" rotation="0 90 0" anim-keyframe="anim" anim-autoplay="clip:child">
        <xr-gltf model="miku-kawaii" anim-keyframe="anim" anim-autoplay></xr-gltf>
      </xr-node>
    </xr-node>
    <xr-camera
      id="camera" node-id="camera" position="0 1 7" clear-color="0.925 0.925 0.925 1"
      target="target" background="default" camera-orbit-control=""
    ></xr-camera>
  </xr-node>
  <xr-node node-id="lights">
    <xr-light type="ambient" color="1 1 1" intensity="1" />
    <xr-light type="directional" rotation="40 180 0" color="1 1 1" intensity="2" />
  </xr-node>
</xr-scene>

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动画

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在uniapp微信小程序中使用three.js导入gltf模型包,你可以按照以下步骤进行操作: 1. 将gltf模型文件放置在uniapp项目的静态资源目录中,比如`static/models`。 2. 在uniapp页面或组件的js文件中引入three.js库和GLTFLoader。 ```javascript import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; ``` 3. 创建一个canvas元素作为渲染器的渲染目标。 ```html <template> <canvas id="canvas"></canvas> </template> ``` 4. 在mounted钩子函数中编写加载和渲染模型的代码。 ```javascript mounted() { const canvas = document.getElementById('canvas'); const renderer = new THREE.WebGLRenderer({ canvas }); const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000); camera.position.z = 5; const loader = new GLTFLoader(); loader.load('../../static/models/model.gltf', (gltf) => { const model = gltf.scene; scene.add(model); // 设置模型的初始位置、旋转等属性 model.position.set(0, 0, 0); model.rotation.set(0, 0, 0); model.scale.set(1, 1, 1); }); function animate() { requestAnimationFrame(animate); // 更新模型、相机等状态 renderer.render(scene, camera); } animate(); } ``` 请确保将`../../static/models/model.gltf`替换为你实际的模型文件路径。 这样,当页面或组件加载后,就会渲染gltf模型在canvas上。 希望对你有所帮助!如有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值