import * as THREE from "../../../../../libs/three.js/build/three.module.js"; import TilePrioritizer from './TilePrioritizer.js' import TileUtils from './TileUtils.js' import {settings, config} from '../../../settings.js' import { http } from '../../../utils/request.js' let {TileDownloaderEvents, DownloadStatus} = Potree.defines window.downloaded = {} window.startdownloads = []; class TileDownloader extends THREE.EventDispatcher{ constructor( ) { super() this.panos = null; this.retryMinimumTime = 1e4; this.panoLoadCallbacks = {}; this.downloadDescriptors = {}; this.priorityQueue = []; this.forceQueue = []; this.activeDownloads = []; this.tilePrioritizer = null; this.refreshInterval = null; this.processPriorityQueue = !1; this.concurrentDownloads = 6;//e.concurrentDownloads || 1; this.downloadTestResults = {}; this.freeze = Object.freeze({ Testing: 1, Success: 2, Fail: 3 }); viewer.addEventListener('pageVisible', (e)=>{//不可见时不refreshUpdateInterval //console.log('visibilitychange:', state) viewer.updateVisible(this, 'pageVisible', e.v) this.judgeStart() }) this.visible = true //add 借用viewer.updateVisible来判断是否start if(Potree.settings.useDepthTex){ this.judgeStart() //开始下载depthTex }else{ viewer.updateVisible(this,'showPanos', false ) //默认visible = false } } setPanoData(e, t /* , i */) { this.panos = e, this.imagePanos = t // this.panoGroupId = i } start() { this.downloadCubeTex = true if(!Potree.settings.useDepthTex){ viewer.updateVisible(this,'showPanos', true ) this.judgeStart() }else{ this.refreshInterval || this.judgeStart() } } stop() { this.downloadCubeTex = false if(!Potree.settings.useDepthTex){ viewer.updateVisible(this,'showPanos', false ) this.judgeStart() } } judgeStart(){//add if(this.visible){ //console.log('judgeStart true') this.started = true this.refreshUpdateInterval(0) }else{ //console.log('judgeStart false') this.started = false window.clearTimeout(this.refreshInterval) } } refreshUpdateInterval(e) { e || (e = 0), this.refreshInterval = window.setTimeout(function() { var e = this.update(); e ? this.refreshUpdateInterval(TileDownloader.ACTIVE_REFRESH_DELAY) : this.refreshUpdateInterval(TileDownloader.IDLE_REFRESH_DELAY) } .bind(this), e) } update() { if(this.downloadCubeTex){ //可以下载贴图 var e = this.forceQueue.length > 0; this.processQueueForDownloading(this.forceQueue); if (this.processPriorityQueue) { this.queuePrioritizedTilesForPanos(this.panos); this.priorityQueue.length > 0 && (e = !0); this.processQueueForDownloading(this.priorityQueue); } return e }else{//仅下载depthTex this.tilePrioritizer.filterDepthTex(this.panos) } } queuePrioritizedTilesForPanos(e) { this.tilePrioritizer && (this.clearQueue(this.priorityQueue), this.tilePrioritizer.filterAndPrioritize(this.priorityQueue, e, this), this.clearFromQueue(this.priorityQueue, DownloadStatus.None, !0), //去除state为DownloadStatus.None的(可能是去除已经在下载的) this.setStatusOrRemoveForAllDescriptors(this.priorityQueue, DownloadStatus.Queued)) } clearQueue(e) {//停止下载并清空 this.setStatusForAllDescriptors(e, DownloadStatus.None), e.length = 0 } clearForceQueue() { this.clearQueue(this.forceQueue) } clearFromQueue(e, t, i) { for (var n = 0; n < e.length; n++) { var r = e[n]; r && (t === r.status && !i || t !== r.status && i) && (e[n] = null) } } setStatusForAllDescriptors(e, t) { for (var i = 0; i < e.length; i++) { var n = e[i]; n && (n.status = t) } } setStatusOrRemoveForAllDescriptors(e, t) { for (var i = 0; i < e.length; i++) { var n = e[i]; n && (n.status !== t ? n.status = t : e[i] = null) } } getTileDownloadDescriptors(pano, size) {//获取该pano的该size的全部的tile的descriptor var i = this.getAllTileDownloadDescriptorsForPano(pano), n = i[size]; return n || (n = this.buildDownloadDescriptorArray(size),//创建的全部是空的 i[size] = n, this.initTileDownloadDescriptors(n, pano, size)),//绑定到该pano size n } getAllTileDownloadDescriptorsForPano(pano) {//新建空Descriptors var t = this.downloadDescriptors[pano.id]; return t || (t = {}, this.downloadDescriptors[pano.id] = t), t } processQueueForDownloading(e, t) {//执行下载任务 this.cleanupActiveDownloads(); if (this.activeDownloads.length < this.concurrentDownloads || t) { var i = t ? e.length : this.concurrentDownloads - this.activeDownloads.length; for (var n = 0, r = 0; n < i && e.length > 0; r++) { var o = e.shift(); if(o){ //add 为了防止1024的在512前下载完,这里强行等待512下载完毕再开始下载 if(o.panoSize > 512 && !this.isPanoDownloaded(o.pano, 512) ){ //console.log('512的还没下载好呢!') e.push(o) break;//一般512的都是连续下载的,所以后面就都不是512了直接中断 } this.startDownload(o) n++ } } } } testDownload(panoSize, tileSize, callback) { var n = this.downloadTestResults[panoSize]; if (n) return void(n === this.freeze.Success ? callback(!0) : n === this.freeze.Fail && callback(!1)); this.downloadTestResults[panoSize] = this.freeze.Testing; var r = this.panos[0], o = this.getTileUrl({pano:r, panoSize, tileSize, tileIndex:0} /* r.id, panoSize, tileSize, 0 */), a = function(t) { this.downloadTestResults[panoSize] = this.freeze.Success, callback(!0) } .bind(this), s = function() { this.downloadTestResults[panoSize] = this.freeze.Fail, callback(!1) } .bind(this); this.loadImage(o, 0, a, s) } startDownload(e) {//开始下载啦 //console.log('startDownload') startdownloads.push(e) e.local2SrcFailed = this.local2SrcFailed e.status = DownloadStatus.Downloading; var t = this.getTileUrl(e/* e.pano.id, e.panoSize, e.tileSize, e.tileIndex, e.pano.alignmentType */);//xzw add alignmentType if(!t)return; this.activeDownloads.push(e); this.loadImage(t, TileDownloader.DOWNLOAD_RETRIES, this.downloadComplete.bind(this, e), this.downloadFailed.bind(this, e)) } downloadFailed(e, t) { //add if(Potree.settings.isLocal2 && !e.local2SrcFailed){//为了兼容旧的数据src,如果新src没加载成功,就加载旧的 e.local2SrcFailed = this.local2SrcFailed = true //this.startDownload(e)//重新下载 var t = this.getTileUrl(e); this.loadImage(t, TileDownloader.DOWNLOAD_RETRIES, this.downloadComplete.bind(this, e), this.downloadFailed.bind(this, e)) } } downloadComplete(e, t) {//下载成功时 //if (e.panoGroupId === this.panoGroupId) { var i = this.getPanoLoadCallbacks(e.pano, e.panoSize); e.status = DownloadStatus.Downloaded, i && i.onProgress && i.onProgress(e.pano, e.panoSize); var n = { panoId: e.pano.id, image: t, tileSize: e.tileSize, panoSize: e.panoSize, tileIndex: e.tileIndex, faceTileIndex: e.faceTileIndex, totalTiles: e.totalTiles, face: e.face, tileX: e.tileX, tileY: e.tileY, direction: e.direction }; downloaded[e.pano.id] || (downloaded[e.pano.id]={512:[],1024:[],2048:[]}) downloaded[e.pano.id][e.panoSize] || (downloaded[e.pano.id][e.panoSize] = []) downloaded[e.pano.id][e.panoSize].push(e) if(e.panoSize != 512 && downloaded[e.pano.id][512].length<6){ console.warn('没下完') } e.image = t, this.dispatchEvent({type:TileDownloaderEvents.TileDownloadSuccess, desc:n} ) this.isPanoDownloaded(e.pano, e.panoSize) && (n = { panoId: e.pano.id, tileSize: e.tileSize, panoSize: e.panoSize }, this.dispatchEvent({type:TileDownloaderEvents.PanoDownloadComplete, desc:n}), i && i.onLoad && i.onLoad(e.pano, e.panoSize)) //} } isPanoDownloaded(e, t) { var i = this.getTileDownloadDescriptors(e, t); if (i.length <= 0) return !1; for (var n = 0; n < i.length; n++) { var r = i[n]; if (r.status !== DownloadStatus.Downloaded) return !1 } return !0 } setPanoLoadCallbacks(e, t, i, n, r) { var o = e.id + ":" + this.qualityManager.getPanoSize(t); this.panoLoadCallbacks[o] = { onLoad: i, onFail: n, onProgress: r } } getPanoLoadCallbacks(e, t) { var i = e.id + ":" + t; return this.panoLoadCallbacks[i] } buildDownloadDescriptorArray(e) { for (var t = TileUtils.getTileCountForSize(e), i = [], n = 0; n < t; n++) { var r = this.buildDownloadDescriptor(); i.push(r) } return i } buildDownloadDescriptor() {//Descriptor! var e = { panoGroupId: null, pano: null, panoSize: -1, tileSize: -1, tileIndex: -1, totalTiles: -1, faceTileIndex: -1, status: DownloadStatus.None, url: null, image: null, direction: new THREE.Vector3, //该tile在cube中的方向 face: -1, cubeFace: -1, tileX: -1, tileY: -1 }; return e } initTileDownloadDescriptors(e, t, i) { for (var n = 0; n < e.length; n++) { var r = e[n]; this.initTileDownloadDescriptor(r, t, i, n) } } initTileDownloadDescriptor(desc, pano, size, index) { var r = size >= TileUtils.TILE_SIZE ? TileUtils.TILE_SIZE : size; desc.face = TileUtils.getFaceForTile(size, index);//根据顺序得到的face的index desc.cubeFace = TileUtils.mapFaceToCubemapFace(desc.face);//为了贴图而转化的face index //desc.panoGroupId = this.panoGroupId;//就是场景号 desc.pano = pano; desc.panoSize = size; desc.tileSize = r; //瓦片图size 512 desc.tileIndex = index; desc.totalTiles = TileUtils.getTileCountForSize(size); desc.status = DownloadStatus.None; desc.image = null; TileUtils.getTileLocation(desc.panoSize, desc.tileIndex, desc);//得到该tile在这个face中的具体位置(tileX等) TileUtils.getTileVector(desc.panoSize, desc.tileSize, desc.cubeFace, desc.tileX, desc.tileY, TileUtils.LocationOnTile.Center, 0, desc.direction); } getTiles(d, sceneNum, useV4url){ if(Potree.settings.isLocal2 && !this.local2SrcFailed || useV4url){//新的地址 scene_view_data/场景码/images/tiles return `${Potree.settings.urls.prefix3}/scene_view_data/${sceneNum}/images/${d}` } return `${Potree.settings.urls.prefix3}/images/images${sceneNum}/${d}` } loadImage(e, t, i, n) { //自己修改了ajax,把getImage改成了loadImg http.loadImage(e, t).then(function(e) { i(e) }).fail(n) } } TileDownloader.prototype.forceQueueTilesForPano = function() {//根据条件开始加载tile var e = [], t = []; return function(pano, size, dir, hFov, vFov, download) { e.length = 0; for (var u = this.getTileDownloadDescriptors(pano, size), d = 0; d < u.length; d++) { var p = u[d]; p.status !== DownloadStatus.None && p.status !== DownloadStatus.Queued || e.push(p) } if (dir && e.length > 0) { TilePrioritizer.sortPanoTiles(e, pano, dir) //按最佳方向排序e t.length = 0 TileUtils.matchingTilesInDirection(pano, size, dir, hFov, vFov, t);//得到在符合视野标准的集合t for (var f = 0, g = function(e) { return e.face === m.face && e.faceTileIndex === m.faceTileIndex }; f < e.length;) { //过滤掉不符合角度要求的 var m = e[f], v = t.findIndex(g); v < 0 ? e.splice(f, 1) : f++ } } for (var A = 0; A < e.length; A++){ this.forceQueue.push(e[A]); //装载 } /* if(e.length){ console.log(e) } */ this.setStatusForAllDescriptors(this.forceQueue, DownloadStatus.ForceQueued); this.clearFromQueue(this.priorityQueue, DownloadStatus.ForceQueued, !1); download && this.processQueueForDownloading(this.forceQueue, !0); } }() TileDownloader.prototype.cleanupActiveDownloads = function() { var e = []; return function() { e.length = 0; for (var t = 0; t < this.activeDownloads.length; t++) { var i = this.activeDownloads[t]; i.status !== DownloadStatus.Downloaded && i.status !== DownloadStatus.Failed && e.push(i) } this.activeDownloads.length = 0, this.activeDownloads.push.apply(this.activeDownloads, e) } }() TileDownloader.prototype.getTileUrl = function() { var e = { 256: "256", 512: "512", 1024: "1k", 2048: "2k", 4096: "4k" }, t = { face: -1, faceTileIndex: -1, tileX: -1, tileY: -1 }; return function(o={} ) { var id = o.pano.originID, //////// panoSize = o.panoSize, tileSize = o.tileSize, tileIndex = o.tileIndex, sceneCode = o.pano.pointcloud.sceneCode, useV4url = Potree.settings.testV4url /* && o.pano.pointcloud.useV4url */ //v4的全景图等路径不一样 var metadata = {sceneScheme:10} TileUtils.getTileLocation(panoSize, tileIndex, t); var s = Math.floor(panoSize / tileSize), l = s * s, h = Math.floor(tileIndex / l), u = "", d = '', g = ''; if(Potree.settings.isLocal){//原始规则 //1 === config.tiling.customCompression && (u = "_" + config.tiling["q" + e[panoSize]]); //1 === o.tiling.customCompression && (u = "_" + o.tiling["q" + e[n]]); d = "tiles/" + id + "/" + e[panoSize] + u + "_face" + h + "_" + t.tileX + "_" + t.tileY + ".jpg" d = this.getTiles(d, sceneCode, useV4url); g = "?" }else{//阿里云oss的规则 if (metadata.sceneScheme == 10) d = 'tiles/4k/' + id + '_skybox' + h + '.jpg?x-oss-process='; if (e[panoSize] == '512') { d += 'image/resize,h_512'; } else { //4k的图,移动端是1k,pc端是2k,放大才是4k if (e[panoSize] == '1k' || e[panoSize] == '2k') { //https://4dkk.4dage.com/images/imagesx4iqYDG3/tiles/4k/122_skybox0.jpg?x-oss-process=image/resize,m_lfit,w_1024/crop,w_512,h_512,x_511,y_0 d += 'image/resize,m_lfit,w_' + panoSize + '/crop,w_512,h_512,'; } else { d = 'tiles/4k/' + id + '_skybox' + h + '.jpg?x-oss-process=image/crop,w_512,h_512,'; } //起始位置 if (t.tileX == 0) { d += 'x_0,'; } else { d += 'x_' + (512 * t.tileX - 1) + ','; } if (t.tileY == 0) { d += 'y_0'; } else { d += 'y_' + (512 * t.tileY - 1); } } d = this.getTiles(d, sceneCode, useV4url); g = "&" } d += g + 'time='+o.pano.pointcloud.timeStamp //加后缀 return d; } }(); TileDownloader.tilegen = true; TileDownloader.IDLE_REFRESH_DELAY = 500; TileDownloader.ACTIVE_REFRESH_DELAY = 16; TileDownloader.DOWNLOAD_RETRIES = 4; /* 源:https://4dkk.4dage.com/images/imagesSS-t-ZZR7oKnlIl 目标:https://4dkk.4dage.com/scene_view_data/SS-t-ZZR7oKnlIl/images 源:https://4dkk.4dage.com/data/dataSS-t-ZZR7oKnlIl 目标:https://4dkk.4dage.com/scene_view_data/SS-t-ZZR7oKnlIl/data 源:https://4dkk.4dage.com/video/videoSS-t-ZZR7oKnlIl 目标:https://4dkk.4dage.com/scene_view_data/SS-t-ZZR7oKnlIl/video */ // var tileconc = TileDownloader.tilegen ? 6 : 2; // publicObjectSet.tileDownloader = new TileDownloader({ // concurrentDownloads: tileconc // }); // export default new TileDownloader({ // concurrentDownloads: TileDownloader.tilegen ? 6 : 2 // }) /* export default new TileDownloader({ concurrentDownloads: TileDownloader.tilegen ? 6 : 2 }) */ export default TileDownloader