BIM轻量化之路(五)-多文件加载及缓存

it2024-06-30  39

一、多文件加载

通过revit将很多专业文件合并成一个文件,稍微大点的文件合并的过程也会很痛苦,然后导出的GLTF文件很大threejs加载往往会内存溢出,一般来说一个文件大于50M,THREEJS就不好加载进来,往往会内存溢出,对于互联网上的加载,超过30M的文件加载用户体验及其差。所以需要对多文件进行分部加载,使用load多个文件加载至场景渲染。 部分代码:

CsscModelCore.prototype.loadGitfDraco = function(instance){ let gLTFLoader = new THREE.GLTFLoader() let dracoLoader = new THREE.DRACOLoader(); dracoLoader.setDecoderPath('/js/plugin/threejs/examples/js/libs/draco/gltf/'); dracoLoader.setDecoderConfig({ type: 'js' }); gLTFLoader.setDRACOLoader(dracoLoader); loadCsscModel(instance.settings.urls[0],instance.settings.urls,gLTFLoader,instance); } function loadCsscModel(url,urls,gLTFLoader,instance){ let indexUrl = 0; for (let i = 0; i < urls.length; i++) { if(urls[i] == url){ indexUrl = i; break; } } $('#loadding_total').html('总计:'+urls.length+"个文件,当前:"+indexUrl+"."); gLTFLoader.load(url, function(obj) { obj.scene.rotateY(Math.PI); instance.scene.add(obj.scene); instance.setCenter(instance); if(indexUrl < urls.length -1){ //递归加载文件 loadCsscModel(urls[indexUrl+1],urls,gLTFLoader,instance); }else{ instance.render(); $('#loading').hide(); } }, onProgress); } 通过数组和递归将模型加载至场景加载时可以增加遮罩提示用户加载进度 效果如下:

二、缓存的使用

1.threejs的cache

新版的threejs支持了缓存的机制,load的数据文件会存储在本地

Cache 的结构:

var Cache = { enabled: false, files: {}, add: function ( key, file ) { if ( this.enabled === false ) { return; } // console.log( 'THREE.Cache', 'Adding key:', key ); this.files[ key ] = file; }, get: function ( key ) { if ( this.enabled === false ) { return; } // console.log( 'THREE.Cache', 'Checking key:', key ); return this.files[ key ]; }, remove: function ( key ) { delete this.files[ key ]; }, clear: function () { this.files = {}; } };

threejs在加载文件的时候会首先判断Cache中是否存在已加载的文件,如果已经加载直接从缓存中读取 代码片段(示例):

load: function ( url, onLoad, onProgress, onError ) { if ( url === undefined ) { url = ''; } if ( this.path !== undefined ) { url = this.path + url; } url = this.manager.resolveURL( url ); var scope = this; var cached = Cache.get( url );//判断是否存在加载数据 if ( cached !== undefined ) { scope.manager.itemStart( url ); ......

2.Cache与IndexedDB

每次刷新页面都会重新拉取模型文件,不能读取本地缓存,影响用户体验,所以需要将模型数据手动加载至浏览器缓存,对于比较大的数据存储在IndexedDB中是比较合适的,IndexedDB允许储存大量数据,能建立索引,这些都是 LocalStorage 所不具备的,更接近 NoSQL 数据库,可按照key,value的方式操作。 通过与threejs 的Cache结合,我们可以实现首次刷新页面从服务端拉取数据,再次刷新从IndexedDB获取模型数据,减少带宽的使用率,提高threejs加载速度。 代码片段:

function intThreejsCache(){ let request = window.indexedDB.open("modelDB", 1); request.onupgradeneeded = (ev) => { modelDb = ev.target.result; if (!modelDb.objectStoreNames.contains('info')) { modelDb.createObjectStore('info'); } console.log("数据库创建成功"); } request.onsuccess = (ev) => { console.log("数据库打开成功"); modelDb=ev.target.result; THREE.Cache.enabled = true;//开启缓存 let transaction = modelDb.transaction(["info"], "readwrite"); let objectStoreModelDB = transaction.objectStore("info"); objectStoreModelDB.openCursor().onsuccess = function (event) { var cursor = event.target.result; if (cursor) { if(viewer.settings.urls.indexOf(cursor.key)>-1){ console.log("indexdb加载模型:"+cursor.key); //将文件存入到threejs 的cache中 THREE.Cache.add( cursor.key, cursor.value ); } cursor.continue(); } }; transaction.oncomplete=function(event) { viewer.Init(); } } request.onerror = (ev) => { console.log("打开数据库失败:"+ev.target.message); } } 每次刷新页面判断IndexedDB中是否存在需要加载的URL文件资源,可根据版本号、名称等判断是否为最新资源,存在则直接加载至cache中每次load完模型后,将url的文件资源更新至IndexedDB中
最新回复(0)