当前位置: 首页 > news >正文

uniApp开发XR-Frame微信小程序 | 动态加载与删除模型

在使用xr-frame开发3D小程序时,我们经常需要根据需求去动态加载模型或删除模型,在官方的说明中,提到了相关方法,但并不太明确,也没有确切的实例。

我们先来看一下官方给出的说明。

一. Shadow元素

我们需要用代码动态创建元素之后添加到场景中,这个需求和wxml写标签这种静态的模板编译方式是冲突的,为了保证DOM树不混乱,我们提供了类似于HTML中的ShadowRoot的XRShadow元素,对应于xml中的xr-shadow标签,来解决这个问题。

<xr-shadow id="shadow" position="0 1 0" />

也就是说,我们要动态添加模型,就需要在这个xr-shadow元素下操作。

我们先来看一下实例

实例中,我们通过点击下一个按钮,将xr-frame框架中的模型卸载后再重新加载一个新的模型。

二.代码实现

下面我们从源码角度来讲解如何实现。

(1)index.wxml 中的部分代码

<xr-scene render-system="alpha:true" bind:ready="handleReady"><xr-light type="ambient" color="1 1 1" intensity="1" /><xr-light type="directional" rotation="40 150 0" color="1 1 1" intensity="3" cast-shadow /><xr-node node-id="target" anim-keyframe="anim" anim-autoplay="clip:cube"><xr-shadow id="shadow" position="0 0 0" /></xr-node><xr-env env-data="xr-frame-team-workspace-day" sky-map="weakme"/><xr-camera id="camera" clear-color="0 0 0 0" position="0 0.5 1.5" target="target" camera-orbit-control background="skybox"/>
</xr-scene>

上面的代码中,我们主要看

<xr-shadow id="shadow" position="0 0 0" />

这段源码就是shadow元素,我们要添加和删除模型,都是在这个元素里操作的。

我们给shadow元素设置了id,就是用于在 index.js 文件中查找这个元素,然后通过xr-frame框架下的API操作在这个元素下添加新的节点。

(2)获取场景中的shadow节点

 index.js 中的源码中

handleReady({detail}) {this.xrFrameSystem = wx.getXrFrameSystem()this.scene = detail.valuethis.control.isLockZoom = truethis.shadow = this.scene.getElementById('shadow')// 给父组件发送通知this.triggerEvent('sceneReady',"ready")},

handleReady() 这个函数表示场景加载完成后执行的回调函数。

在这个函数中,我们通过 this.scene = detail.value 获取到了场景的根节点信息,这一步是基础,获取到场景的根节点后,才能获取更多的子节点。

随后,我们通过 this.shadow =this.scene.getElementById('shadow') 获取到了 shadow 元素的节点,下一步,我们就要实现在 shadow 元素下添加子节点的操作了。

(3)使用api动态创建gltf节点到shadow中。

async addGltf() {//1 创建xr-gltf元素const el = this.scene.createElement(this.xrFrameSystem.XRGLTF)//2 获取shadow节点this.shadow = this.scene.getElementById('shadow')//3 将xr-gltf节点加入到shaodow节点中this.shadow.addChild(el)//4 读取对应的模型文件const { value: model} = await this.scene.assets.loadAsset({type: 'gltf',assetId: 'gltfmodel',src: modelsrc})// 5 获取gltf组件this.gltfComp = el.getComponent('gltf') // 6 给gltf组件设置模型数据this.gltfComp.setData({model: model})// 7 给元素设置一个ID,用于后续方便removeel.setId(name)
}

注意:这个函数前面加了 async ,是一个异步函数。

因为在函数中我们需要做加载模型文件的操作,这个操作可能会很耗时,需要视网络情况和模型大小而定。

下面我们一步步解析:

..1 源码中,我们先创建了一个xr-gltf元素

const el = this.scene.createElement(this.xrFrameSystem.XRGLTF)
        这里通过框架的API createElement()我们创建了一个元素

..2 然后将该元素作为子元素添加到shadow元素中

//2 获取shadow节点
this.shadow = this.scene.getElementById('shadow')
//3 将xr-gltf节点加入到shaodow节点中
this.shadow.addChild(el)
        这里我们先通过 getElementById() 方法找到shadow节点。
        然后,通过 addChild() 方法将创建的XRGLTF元素添加到节点下。

..3 通过 scene.assets.loadAsset() 方法加载一个模型资源

const { value: model} = await this.scene.assets.loadAsset({type: 'gltf',assetId: 'gltfmodel',src: modelsrc})
这个方法中有几个属性:
type 表示要加载的资源类型,这里设置为gltf。
assetId 表示设置的资源ID,这个可以用于后期清理资源。
src 表示资源的网络地址。
这里需要注意的一点,scene.assets.loadAsset() 这个方法要加载资源,有时耗费时间会比较长,所以这里采用async/await 的语法来进行异步操作。

..4 获取到xr-gltf元素中的 gltf 组件

this.gltfComp = el.getComponent('gltf') 
这一部,我们获取到了元素XRGLTF元素中的gltf组件

..5 给组件设置属性

// 6 给gltf组件设置模型数据
this.gltfComp.setData({model: model})
// 7 给元素设置一个ID,用于后续方便remove
el.setId(name)
这一步我们给组件中的model属性设置了变量名为 model 的对象
这个 model 就是我们第3步加载的模型对象
最后我们给元素 el 设置了一个id。用于后期清理资源使用。

(4)清理资源

在官方说明中,通过动态加载的资源需要自己手动释放,不然如果加载越来越多,会对程序造成卡顿。

release(name) {//1 删除节点this.shadow.removeChild(this.scene.getElementById(name))//2 释放资源this.scene.assets.releaseAsset('gltf', name)
},

上面代码中,我们首先调用了 shadow.removeChild() 方法,移除了shadow下的子节点。

然后通过 scene.assets.releaseAsset()方法,释放了加载的gltf资源。

函数中的参数 name 就是我们给上一步创建的 el 设置的 id

函数中的这两个方法都是xr-frame官方api中的方法,详细的解释可以看一下官方文件。

关于释放资源的时机,可以根据自己的场景需求进行合理的设计。

三.附件说明

附件中的代码就是本篇文章用到的动态加载模型的xr-frame组件中的代码。

代码中我做了一些优化,由于gltf文件有时会过大,所以我采用模型和贴图分开加载的方法,加载完成后再给模型设置上贴图。

大家可以参考学习,如果不会配置需要查看一下这篇文章,xr-frame基础环境搭建。

四.示例小程序

下面这个小程序,是我根据官方指南做的一个简易的示例程序,其中运用了场景的搭建,材质动态修改,模型动态添加与删除,粒子特效等功能,可以作为本片文章的参考。

http://www.dtcms.com/a/384542.html

相关文章:

  • AR 巡检在工业的应用|阿法龙XR云平台
  • eureka微服务注册问题
  • 【LangChain指南】大语言模型(LLMs)
  • 一台设备管理多个 GitHub 账号:从配置到切换的完整指南
  • K - 近邻(KNN)算法:基于约会数据集的分类任务全流程
  • 机器学习实战第四章 线性回归
  • 概率统计面试题2:随机抛掷两点到圆心距离较小值的期望
  • 什么是 OFDM?它如何解决频率选择性衰落?
  • 第一部分:VTK基础入门(第3章:VTK架构与核心概念)
  • 基于深度学习的中文方言识别模型训练实战
  • 【机器学习】用Anaconda安装学习环境
  • 【C语言】C语言内存存储底层原理:整数补码、浮点数IEEE754与大小端(数据内存存储的深度原理与实践)
  • MongoDB - 连接
  • 【Day 57】Linux-Redis
  • Go语言爬虫:爬虫入门
  • HarmonyOS图表组件库对比:UCharts、VChart、Omni-UI、mcCharts
  • 生活中的花花草草和各色人物
  • HTML属性和值
  • 【STL库】unordered_map/unordered_set 类学习
  • 学习threejs,使用自定义GLSL 着色器,实现水面、粒子特效
  • 机器学习-第二章
  • 贪心算法在SDN流表优化中的应用
  • 植物1区TOP——GWAS eQTL如何精准定位调控棉花衣分的候选基因
  • iOS 灵动岛 ActivityKit 开发实践
  • JVM 垃圾收集器
  • 学习日记-XML-day55-9.14
  • SenseVoice + WebRTC:打造行业级实时语音识别系统的底层原理与架构设计
  • C++ 异常机制深度解析:从原理到实战的完整指南
  • 在 Qoder 等 AI 二创 IDE 里用 VS Code Remote-SSH 的“曲线连接”实战
  • 云计算与大数据技术深入解析