11.Three.js使用indexeddb前端缓存模型优化前端加载效率

11.Three.js使用indexeddb前端缓存模型优化前端加载效率

1.简述

在使用Three.js做数字孪生应用场景时,我们常常需要用到大量模型或数据。在访问我们的数字孪生应用时,每次刷新都需要从web端进行请求大量的模型数据或其他渲染数据等等,会极大的消耗时间,用户体验不好,因而我们可以通过indexeddb缓存我们的模型数据。

2.indexeddb简介

indexeddb 介绍和学习可以参考这里:https://zhuanlan.zhihu.com/p/429086021

IndexedDB主要用来客户端存储大量数据而生的,我们都知道cookie、localstorage等存储方式都有存储大小限制。如果数据量很大,且都需要客户端存储时,那么就可以使用IndexedDB数据库。它是一种前端的非关系型数据库,同样具有增删改查的功能。我下面封装了一个工具类dbUtils.js对模型数据进行缓存:

const DB_NAME = 'modeldb'; //数据库名称
const DB_VERSION = 1; //数据库版本号
const DB_STORE_NAME = 'model_glb_table'; //数据库仓库function DBUtil() {this.db = null;// 根据模型的url地址,请求模型// 如果没有数据库中没有模型,则请求模型并放入缓存中,返回promise,带有模型的blob文件对象// 如果如果缓存中有模型了,就直接从缓存中取出this.get = async (url, onProgress) => {this.db = await this.initDataBase();let getRequest = this.db.transaction([DB_STORE_NAME], "readwrite") // 事务对象 指定表格名称和操作模式("只读"或"读写").objectStore(DB_STORE_NAME) // 仓库对象.get(url);  // 通过主键(url)获取数据let that = this;return new Promise((resolve, reject) => {getRequest.onsuccess = function (event) {let modelFile = event.target.result;// 假如已经有缓存了 直接用缓存if (modelFile) {if (onProgress) {onProgress(100);}console.log("使用缓存");resolve(modelFile.blob)} else {// 假如没有缓存 请求新的模型存入that.put(url, onProgress).then((blob) => {resolve(blob)}).catch(() => {reject()});}};getRequest.onerror = function (event) {// console.log('error', event)reject()}})}// 请求模型并放入缓存中this.put = async (url, onProgress) => {const response = await fetch(url);if (response.status !== 200) {throw new Error('Request failed');}const contentLength = response.headers.get('Content-Length');// console.log(contentLength)const totalBytes = parseInt(contentLength, 10);let downloadedBytes = 0;const readableStream = response.body;const { readable, writable } = new TransformStream();const writer = writable.getWriter();const reader = readableStream.getReader();const pump = async () => {const { done, value } = await reader.read();if (done) {writer.close();return;}writer.write(value);downloadedBytes += value.length;if (onProgress) {const progress = (downloadedBytes / totalBytes) * 100;console.log(progress.toFixed(2))onProgress(progress.toFixed(2));}return pump();};await pump();let blob = null;try {blob = await new Response(readable).arrayBuffer();} catch (e) {console.log('请求arrayBuffer失败,用blob方式')blob = await new Response(readable).blob();}let obj = {ssn: url}obj.blob = new Blob([blob])const inputRequest = this.db.transaction([DB_STORE_NAME], "readwrite").objectStore(DB_STORE_NAME).add(obj);return new Promise((resolve, reject) => {inputRequest.onsuccess = function () {console.log('glb数据添加成功');resolve(obj.blob);};inputRequest.onerror = function (evt) {console.log('glb数据添加失败', evt);reject();};});}// 打开数据库this.initDataBase = () => {if (!window.indexedDB) {console.log("浏览器不支持indexedDB缓存!!!")return;}let request = indexedDB.open(DB_NAME, DB_VERSION); //如果没有数据库,则创建,有数据库就链接return new Promise((resolve, reject) => {request.onerror = function () {// console.log("error: create db error");reject()};// 数据库创建或升级的时候会触发request.onupgradeneeded = function (evt) {evt.currentTarget.result.createObjectStore(DB_STORE_NAME, { keyPath: 'ssn' });};// 数据库打开成功回调request.onsuccess = function (evt) {// console.log("onsuccess: create db success ");resolve(evt.target.result)};})}
}

3.Three.js加载模型

原本的three.js加载模型如下,这是最基础的加载模型的方法:

function initObject() {//再加载模型const objLoader = new THREE.GLTFLoader();objLoader.load("./data/Soldier.glb",function (gltf) {let root = gltf.scene;root.position.set(0,0,0);root.scale.set(100,100,100);scene.add(root);},//加载回调function (xhr) {console.log((xhr.loaded / xhr.total) * 100 + "% loaded");},//加载失败回调function (error) {console.log("An error happened");});}

使用缓存后加载的方法:

function initObject() {new DBUtil().get("./data/Soldier.glb", (progress) => {console.log("progress", progress);}).then((blob) => {//再加载模型const objLoader = new THREE.GLTFLoader();let url = URL.createObjectURL(new Blob([blob]));objLoader.load(url, function (gltf) {let root = gltf.scene;root.position.set(0, 0, 0);root.scale.set(100, 100, 100);scene.add(root);},//加载回调function (xhr) {console.log((xhr.loaded / xhr.total) * 100 + "% loaded");},//加载失败回调function (error) {console.log("An error happened");});})}

4.验证检查

我们刷新网页后,查看应用程序中是否多了一个数据库,数据库中是否有数据

在这里插入图片描述

尝试删除该数据库后,再刷新页面。

对比数据库存在时,再次刷新页面。可以发现该数据库缓存存在时,模型渲染效率快了很多。特别时互联网访问时,还会有一个模型数据下载的过程,使用缓存可以直接省略下载的时间,效率上可以得到很大的提升。

视频地址:https://www.bilibili.com/video/BV1cQSzYLE9n/?vd_source=0f4eae2845bd3b24b877e4586ffda69a

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/463636.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【HarmonyOS】引导用户跳转APP设置详情页开启权限

【HarmonyOS】引导用户跳转设置APP详情页开启权限 前言 众所周知在鸿蒙应用中,向用户申请权限时,会弹出系统请求授权的弹框。当用户拒绝了你申请的权限,弹框会直接关闭。当下次触发同样的权限申请,会直接返回失败,不…

深入理解Transformer中的位置编码

1 位置编码的作用 由于注意力的作用机制,不论输入序列的顺序如何,输出结果都是一样的。 也就是丢失了位置信息。 但是对于语言模型, 我们都知道顺序是很重要的, 所以需要对输入序列额外注入位置信息。 2 位置编码方式 Transfor…

MySQL分区表(二)

说明:之前有写过一篇博客,介绍MySQL如何建立分区表,本文介绍如何建立子分区表。子分区,就是在原来分区的基础上,再嵌套一个分区。 例如,按照记录的创建时间分区,在此基础上,再按照租…

一文弄懂Bert模型

01 引言 计算机一直难以理解语言,其中一个重要原因就是该任务需要更基本的语言语境。每个 NLP 任务都可以通过使用为每个任务创建的单独模型来解决。 2018 年,谷歌发布了论文BERT,旨在对模型进行预训练,这样就可以通过增加不同…

HTML5实现小鸟过管道小游戏源码

文章目录 1.设计来源1.1 主界面1.2 游戏中主界面1.3 游戏结束界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板,程序开发,在线开发,在线沟通 作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/…

Linux·进程控制(system V)

1. 共享内存 system V共享内存是最快的IPC形式,之前的管道是基于Linux内核开发的通讯方案,其读写接口都是现成的,因此内核设计者为了完成进程间通讯任务并不需要新增太多代码。而共享内存属于system V标准,是操作系统单独…

【Python+Pycharm】2024-Python安装配置教程

【PythonPycharm】2024-Python安装配置教程 一、下载装 Python 1、进入Python官网首页,下载最新的Python版本 Download Python | Python.org 选择对应版本下载 安装 测试安装情况 python如果安装失败 在系统环境变量添加安装路径 where pythonwin7安装路径添加…

文献阅读 11.3

文献阅读 Physics-informed neural networks for hydraulic transient analysis in pipeline systems (基于物理信息的管道系统水力瞬态分析神经网络) 一、文献摘要 该文献提出了一种新的基于物理和数据驱动的定向瞬态压力重建方法,无需建立完整的管道系统模型。…

MFC工控项目实例二十八模拟量信号每秒采集100次

用两个多媒体定时器,一个定时0.1秒计时,另一个定时0.01秒用来对模拟量信号采集每秒100次。 1、在SEAL_PRESSUREDlg.h中添加代码 class CSEAL_PRESSUREDlg : public CDialo { public:CSEAL_PRESSUREDlg(CWnd* pParent NULL); // standard constructor&a…

气膜冰雪项目:推动冰雪运动发展的新纪元—轻空间

随着2024年北京冬奥会的余温仍在延续,气膜冰雪项目在我国的冰雪运动发展中扮演着愈发重要的角色。气膜结构以其独特的优势,正吸引着越来越多的参与者,推动着冰雪运动的普及与发展。 突出的优势 气膜冰雪馆的设计理念充分体现了现代建筑的灵活…

市场分化!汽车零部件「变天」

全球汽车市场的动荡不安,还在持续。 本周,全球TOP20汽车零部件公司—安波福(Aptiv)发布2024年第三季度财报显示,三季度公司经调整后确认收入同比下降6%;按照区域市场来看,也几乎是清一色的下滑景…

ES6中数组新增了哪些扩展?

ES6中数组新增了哪些扩展? 1、扩展运算符的应⽤ ES6通过扩展元素符 … ,好⽐ rest 参数的逆运算,将⼀个数组转为⽤逗号分隔的参数序列 console.log(...[1, 2, 3]) // 1 2 3 3 console.log(1, ...[2, 3, 4], 5) // 1 2 3 4 5 [...documen…

基于物联网的户外环境检测装置教学文章

引言 随着物联网(IoT)技术的发展,越来越多的应用被广泛研究和应用于我们的日常生活中。户外环境检测装置是一种利用传感器、网络连接和数据分析技术,监测和分析环境数据(如温度、湿度、空气质量等)的设备。…

ubuntu20安装opencv3.2记录

系统环境 ubuntu20安装了ros-noetic,所以系统默认装了opencv4.2.0,但是跑fastlivo推荐的是opencv3.2.0,而且海康相机别人写的ros驱动(海康相机ros驱动)也是需要opencv3.2.0,最终还是选择安装多版本的openc…

全!新!LLM推理加速调研

本文主要内容 介绍一篇大模型推理加速综述论文,简单说明了LLM推理加速的基本内容。 介绍了推理阶段的prefilling(主要方向:计算优化)和decoding(主要方向:内存优化)差异。 prefilling优化方面…

大数据-206 数据挖掘 机器学习理论 - 多元线性回归 回归算法实现 算法评估指标

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

Python+Appium+Pytest+Allure自动化测试框架-安装篇

文章目录 安装安装ADT安装NodeJs安装python安装appium安装Appium Server(可选)安装Appium-Inspector(可选)安装allure安装pytest PythonAppiumPytestAllure框架的安装 Appium是一个开源工具,是跨平台的,用于…

Nature Methods | 新型三维光场显微成像技术

欢迎关注GZH《光场视觉》 近日,中科院脑科学与智能技术卓越创新中心王凯研究组在《自然方法》(Nature Methods)上,在线发表了题为Volumetric Voltage Imaging of Neuronal Populations in Mouse Brain by Confocal Light Field M…

深度学习基础—循环神经网络的梯度消失与解决

引言 深度学习基础—循环神经网络(RNN)https://blog.csdn.net/sniper_fandc/article/details/143417972?fromshareblogdetail&sharetypeblogdetail&sharerId143417972&sharereferPC&sharesourcesniper_fandc&sharefromfrom_link深…

基于向量检索的RAG大模型

一、什么是向量 向量是一种有大小和方向的数学对象。它可以表示为从一个点到另一个点的有向线段。例如,二维空间中的向量可以表示为 (𝑥,𝑦) ,表示从原点 (0,0)到点 (𝑥,𝑦)的有向线段。 1.1、文本向量 1…