TileDownloader.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. import * as THREE from "../../../../../libs/three.js/build/three.module.js";
  2. import TilePrioritizer from './TilePrioritizer.js'
  3. import TileUtils from './TileUtils.js'
  4. import {settings, config} from '../../../settings.js'
  5. import {
  6. http
  7. } from '../../../utils/request.js'
  8. let {TileDownloaderEvents, DownloadStatus} = Potree.defines
  9. window.downloaded = {}
  10. window.startdownloads = [];
  11. class TileDownloader extends THREE.EventDispatcher{
  12. constructor( ) {
  13. super()
  14. this.panos = null;
  15. this.retryMinimumTime = 1e4;
  16. this.panoLoadCallbacks = {};
  17. this.downloadDescriptors = {};
  18. this.priorityQueue = [];
  19. this.forceQueue = [];
  20. this.activeDownloads = [];
  21. this.tilePrioritizer = null;
  22. this.refreshInterval = null;
  23. this.processPriorityQueue = !1;
  24. this.concurrentDownloads = 6;//e.concurrentDownloads || 1;
  25. this.downloadTestResults = {};
  26. this.freeze = Object.freeze({
  27. Testing: 1,
  28. Success: 2,
  29. Fail: 3
  30. });
  31. viewer.addEventListener('pageVisible', (e)=>{//不可见时不refreshUpdateInterval
  32. //console.log('visibilitychange:', state)
  33. viewer.updateVisible(this, 'pageVisible', e.v)
  34. this.judgeStart()
  35. })
  36. this.visible = true //add 借用viewer.updateVisible来判断是否start
  37. if(Potree.settings.useDepthTex){
  38. this.judgeStart() //开始下载depthTex
  39. }else{
  40. viewer.updateVisible(this,'showPanos', false ) //默认visible = false
  41. }
  42. }
  43. setPanoData(e, t /* , i */) {
  44. this.panos = e,
  45. this.imagePanos = t
  46. // this.panoGroupId = i
  47. }
  48. start() {
  49. this.downloadCubeTex = true
  50. if(!Potree.settings.useDepthTex){
  51. viewer.updateVisible(this,'showPanos', true )
  52. this.judgeStart()
  53. }else{
  54. this.refreshInterval || this.judgeStart()
  55. }
  56. }
  57. stop() {
  58. this.downloadCubeTex = false
  59. if(!Potree.settings.useDepthTex){
  60. viewer.updateVisible(this,'showPanos', false )
  61. this.judgeStart()
  62. }
  63. }
  64. judgeStart(){//add
  65. if(this.visible){
  66. //console.log('judgeStart true')
  67. this.started = true
  68. this.refreshUpdateInterval(0)
  69. }else{
  70. //console.log('judgeStart false')
  71. this.started = false
  72. window.clearTimeout(this.refreshInterval)
  73. }
  74. }
  75. refreshUpdateInterval(e) {
  76. e || (e = 0),
  77. this.refreshInterval = window.setTimeout(function() {
  78. var e = this.update();
  79. e ? this.refreshUpdateInterval(TileDownloader.ACTIVE_REFRESH_DELAY) : this.refreshUpdateInterval(TileDownloader.IDLE_REFRESH_DELAY)
  80. }
  81. .bind(this), e)
  82. }
  83. update() {
  84. if(this.downloadCubeTex){ //可以下载贴图
  85. var e = this.forceQueue.length > 0;
  86. this.processQueueForDownloading(this.forceQueue);
  87. if (this.processPriorityQueue) {
  88. this.queuePrioritizedTilesForPanos(this.panos);
  89. this.priorityQueue.length > 0 && (e = !0);
  90. this.processQueueForDownloading(this.priorityQueue);
  91. }
  92. return e
  93. }else{//仅下载depthTex
  94. this.tilePrioritizer.filterDepthTex(this.panos)
  95. }
  96. }
  97. queuePrioritizedTilesForPanos(e) {
  98. this.tilePrioritizer && (this.clearQueue(this.priorityQueue),
  99. this.tilePrioritizer.filterAndPrioritize(this.priorityQueue, e, this),
  100. this.clearFromQueue(this.priorityQueue, DownloadStatus.None, !0), //去除state为DownloadStatus.None的(可能是去除已经在下载的)
  101. this.setStatusOrRemoveForAllDescriptors(this.priorityQueue, DownloadStatus.Queued))
  102. }
  103. clearQueue(e) {//停止下载并清空
  104. this.setStatusForAllDescriptors(e, DownloadStatus.None),
  105. e.length = 0
  106. }
  107. clearForceQueue() {
  108. this.clearQueue(this.forceQueue)
  109. }
  110. clearFromQueue(e, t, i) {
  111. for (var n = 0; n < e.length; n++) {
  112. var r = e[n];
  113. r && (t === r.status && !i || t !== r.status && i) && (e[n] = null)
  114. }
  115. }
  116. setStatusForAllDescriptors(e, t) {
  117. for (var i = 0; i < e.length; i++) {
  118. var n = e[i];
  119. n && (n.status = t)
  120. }
  121. }
  122. setStatusOrRemoveForAllDescriptors(e, t) {
  123. for (var i = 0; i < e.length; i++) {
  124. var n = e[i];
  125. n && (n.status !== t ? n.status = t : e[i] = null)
  126. }
  127. }
  128. getTileDownloadDescriptors(pano, size) {//获取该pano的该size的全部的tile的descriptor
  129. var i = this.getAllTileDownloadDescriptorsForPano(pano),
  130. n = i[size];
  131. return n || (n = this.buildDownloadDescriptorArray(size),//创建的全部是空的
  132. i[size] = n,
  133. this.initTileDownloadDescriptors(n, pano, size)),//绑定到该pano size
  134. n
  135. }
  136. getAllTileDownloadDescriptorsForPano(pano) {//新建空Descriptors
  137. var t = this.downloadDescriptors[pano.id];
  138. return t || (t = {},
  139. this.downloadDescriptors[pano.id] = t),
  140. t
  141. }
  142. processQueueForDownloading(e, t) {//执行下载任务
  143. this.cleanupActiveDownloads();
  144. if (this.activeDownloads.length < this.concurrentDownloads || t) {
  145. var i = t ? e.length : this.concurrentDownloads - this.activeDownloads.length;
  146. for (var n = 0, r = 0; n < i && e.length > 0; r++) {
  147. var o = e.shift();
  148. if(o){
  149. //add 为了防止1024的在512前下载完,这里强行等待512下载完毕再开始下载
  150. if(o.panoSize > 512 && !this.isPanoDownloaded(o.pano, 512) ){
  151. //console.log('512的还没下载好呢!')
  152. e.push(o)
  153. break;//一般512的都是连续下载的,所以后面就都不是512了直接中断
  154. }
  155. this.startDownload(o)
  156. n++
  157. }
  158. }
  159. }
  160. }
  161. testDownload(panoSize, tileSize, callback) {
  162. var n = this.downloadTestResults[panoSize];
  163. if (n)
  164. return void(n === this.freeze.Success ? callback(!0) : n === this.freeze.Fail && callback(!1));
  165. this.downloadTestResults[panoSize] = this.freeze.Testing;
  166. var r = this.panos[0],
  167. o = this.getTileUrl({pano:r, panoSize, tileSize, tileIndex:0} /* r.id, panoSize, tileSize, 0 */),
  168. a = function(t) {
  169. this.downloadTestResults[panoSize] = this.freeze.Success,
  170. callback(!0)
  171. }
  172. .bind(this),
  173. s = function() {
  174. this.downloadTestResults[panoSize] = this.freeze.Fail,
  175. callback(!1)
  176. }
  177. .bind(this);
  178. this.loadImage(o, 0, a, s)
  179. }
  180. startDownload(e) {//开始下载啦
  181. //console.log('startDownload')
  182. startdownloads.push(e)
  183. e.local2SrcFailed = this.local2SrcFailed
  184. e.status = DownloadStatus.Downloading;
  185. var t = this.getTileUrl(e/* e.pano.id, e.panoSize, e.tileSize, e.tileIndex, e.pano.alignmentType */);//xzw add alignmentType
  186. if(!t)return;
  187. this.activeDownloads.push(e);
  188. this.loadImage(t, TileDownloader.DOWNLOAD_RETRIES, this.downloadComplete.bind(this, e), this.downloadFailed.bind(this, e))
  189. }
  190. downloadFailed(e, t) {
  191. //add
  192. if(Potree.settings.isLocal2 && !e.local2SrcFailed){//为了兼容旧的数据src,如果新src没加载成功,就加载旧的
  193. e.local2SrcFailed = this.local2SrcFailed = true
  194. //this.startDownload(e)//重新下载
  195. var t = this.getTileUrl(e);
  196. this.loadImage(t, TileDownloader.DOWNLOAD_RETRIES, this.downloadComplete.bind(this, e), this.downloadFailed.bind(this, e))
  197. }
  198. }
  199. downloadComplete(e, t) {//下载成功时
  200. //if (e.panoGroupId === this.panoGroupId) {
  201. var i = this.getPanoLoadCallbacks(e.pano, e.panoSize);
  202. e.status = DownloadStatus.Downloaded,
  203. i && i.onProgress && i.onProgress(e.pano, e.panoSize);
  204. var n = {
  205. panoId: e.pano.id,
  206. image: t,
  207. tileSize: e.tileSize,
  208. panoSize: e.panoSize,
  209. tileIndex: e.tileIndex,
  210. faceTileIndex: e.faceTileIndex,
  211. totalTiles: e.totalTiles,
  212. face: e.face,
  213. tileX: e.tileX,
  214. tileY: e.tileY,
  215. direction: e.direction
  216. };
  217. downloaded[e.pano.id] || (downloaded[e.pano.id]={512:[],1024:[],2048:[]})
  218. downloaded[e.pano.id][e.panoSize] || (downloaded[e.pano.id][e.panoSize] = [])
  219. downloaded[e.pano.id][e.panoSize].push(e)
  220. if(e.panoSize != 512 && downloaded[e.pano.id][512].length<6){
  221. console.warn('没下完')
  222. }
  223. e.image = t,
  224. this.dispatchEvent({type:TileDownloaderEvents.TileDownloadSuccess, desc:n} )
  225. this.isPanoDownloaded(e.pano, e.panoSize) && (n = {
  226. panoId: e.pano.id,
  227. tileSize: e.tileSize,
  228. panoSize: e.panoSize
  229. },
  230. this.dispatchEvent({type:TileDownloaderEvents.PanoDownloadComplete, desc:n}),
  231. i && i.onLoad && i.onLoad(e.pano, e.panoSize))
  232. //}
  233. }
  234. isPanoDownloaded(e, t) {
  235. var i = this.getTileDownloadDescriptors(e, t);
  236. if (i.length <= 0)
  237. return !1;
  238. for (var n = 0; n < i.length; n++) {
  239. var r = i[n];
  240. if (r.status !== DownloadStatus.Downloaded)
  241. return !1
  242. }
  243. return !0
  244. }
  245. setPanoLoadCallbacks(e, t, i, n, r) {
  246. var o = e.id + ":" + this.qualityManager.getPanoSize(t);
  247. this.panoLoadCallbacks[o] = {
  248. onLoad: i,
  249. onFail: n,
  250. onProgress: r
  251. }
  252. }
  253. getPanoLoadCallbacks(e, t) {
  254. var i = e.id + ":" + t;
  255. return this.panoLoadCallbacks[i]
  256. }
  257. buildDownloadDescriptorArray(e) {
  258. for (var t = TileUtils.getTileCountForSize(e), i = [], n = 0; n < t; n++) {
  259. var r = this.buildDownloadDescriptor();
  260. i.push(r)
  261. }
  262. return i
  263. }
  264. buildDownloadDescriptor() {//Descriptor!
  265. var e = {
  266. panoGroupId: null,
  267. pano: null,
  268. panoSize: -1,
  269. tileSize: -1,
  270. tileIndex: -1,
  271. totalTiles: -1,
  272. faceTileIndex: -1,
  273. status: DownloadStatus.None,
  274. url: null,
  275. image: null,
  276. direction: new THREE.Vector3, //该tile在cube中的方向
  277. face: -1,
  278. cubeFace: -1,
  279. tileX: -1,
  280. tileY: -1
  281. };
  282. return e
  283. }
  284. initTileDownloadDescriptors(e, t, i) {
  285. for (var n = 0; n < e.length; n++) {
  286. var r = e[n];
  287. this.initTileDownloadDescriptor(r, t, i, n)
  288. }
  289. }
  290. initTileDownloadDescriptor(desc, pano, size, index) {
  291. var r = size >= TileUtils.TILE_SIZE ? TileUtils.TILE_SIZE : size;
  292. desc.face = TileUtils.getFaceForTile(size, index);//根据顺序得到的face的index
  293. desc.cubeFace = TileUtils.mapFaceToCubemapFace(desc.face);//为了贴图而转化的face index
  294. //desc.panoGroupId = this.panoGroupId;//就是场景号
  295. desc.pano = pano;
  296. desc.panoSize = size;
  297. desc.tileSize = r; //瓦片图size 512
  298. desc.tileIndex = index;
  299. desc.totalTiles = TileUtils.getTileCountForSize(size);
  300. desc.status = DownloadStatus.None;
  301. desc.image = null;
  302. TileUtils.getTileLocation(desc.panoSize, desc.tileIndex, desc);//得到该tile在这个face中的具体位置(tileX等)
  303. TileUtils.getTileVector(desc.panoSize, desc.tileSize, desc.cubeFace, desc.tileX, desc.tileY, TileUtils.LocationOnTile.Center, 0, desc.direction);
  304. }
  305. getTiles(d, sceneNum, useV4url){
  306. if(Potree.settings.isLocal2 && !this.local2SrcFailed || useV4url){//新的地址 scene_view_data/场景码/images/tiles
  307. return `${Potree.settings.urls.prefix3}/scene_view_data/${sceneNum}/images/${d}`
  308. }
  309. return `${Potree.settings.urls.prefix3}/images/images${sceneNum}/${d}`
  310. }
  311. loadImage(e, t, i, n) {
  312. //自己修改了ajax,把getImage改成了loadImg
  313. http.loadImage(e, t).then(function(e) {
  314. i(e)
  315. }).fail(n)
  316. }
  317. }
  318. TileDownloader.prototype.forceQueueTilesForPano = function() {//根据条件开始加载tile
  319. var e = [],
  320. t = [];
  321. return function(pano, size, dir, hFov, vFov, download) {
  322. e.length = 0;
  323. for (var u = this.getTileDownloadDescriptors(pano, size), d = 0; d < u.length; d++) {
  324. var p = u[d];
  325. p.status !== DownloadStatus.None && p.status !== DownloadStatus.Queued || e.push(p)
  326. }
  327. if (dir && e.length > 0) {
  328. TilePrioritizer.sortPanoTiles(e, pano, dir) //按最佳方向排序e
  329. t.length = 0
  330. TileUtils.matchingTilesInDirection(pano, size, dir, hFov, vFov, t);//得到在符合视野标准的集合t
  331. for (var f = 0, g = function(e) {
  332. return e.face === m.face && e.faceTileIndex === m.faceTileIndex
  333. }; f < e.length;) { //过滤掉不符合角度要求的
  334. var m = e[f],
  335. v = t.findIndex(g);
  336. v < 0 ? e.splice(f, 1) : f++
  337. }
  338. }
  339. for (var A = 0; A < e.length; A++){
  340. this.forceQueue.push(e[A]); //装载
  341. }
  342. /* if(e.length){
  343. console.log(e)
  344. } */
  345. this.setStatusForAllDescriptors(this.forceQueue, DownloadStatus.ForceQueued);
  346. this.clearFromQueue(this.priorityQueue, DownloadStatus.ForceQueued, !1);
  347. download && this.processQueueForDownloading(this.forceQueue, !0);
  348. }
  349. }()
  350. TileDownloader.prototype.cleanupActiveDownloads = function() {
  351. var e = [];
  352. return function() {
  353. e.length = 0;
  354. for (var t = 0; t < this.activeDownloads.length; t++) {
  355. var i = this.activeDownloads[t];
  356. i.status !== DownloadStatus.Downloaded && i.status !== DownloadStatus.Failed && e.push(i)
  357. }
  358. this.activeDownloads.length = 0,
  359. this.activeDownloads.push.apply(this.activeDownloads, e)
  360. }
  361. }()
  362. TileDownloader.prototype.getTileUrl = function() {
  363. var e = {
  364. 256: "256",
  365. 512: "512",
  366. 1024: "1k",
  367. 2048: "2k",
  368. 4096: "4k"
  369. },
  370. t = {
  371. face: -1,
  372. faceTileIndex: -1,
  373. tileX: -1,
  374. tileY: -1
  375. };
  376. return function(o={} ) {
  377. var id = o.pano.originID, ////////
  378. panoSize = o.panoSize,
  379. tileSize = o.tileSize,
  380. tileIndex = o.tileIndex,
  381. sceneCode = o.pano.pointcloud.sceneCode,
  382. useV4url = Potree.settings.testV4url /* && o.pano.pointcloud.useV4url */ //v4的全景图等路径不一样
  383. var metadata = {sceneScheme:10}
  384. TileUtils.getTileLocation(panoSize, tileIndex, t);
  385. var s = Math.floor(panoSize / tileSize),
  386. l = s * s,
  387. h = Math.floor(tileIndex / l),
  388. u = "",
  389. d = '', g = '';
  390. if(Potree.settings.isLocal){//原始规则
  391. //1 === config.tiling.customCompression && (u = "_" + config.tiling["q" + e[panoSize]]);
  392. //1 === o.tiling.customCompression && (u = "_" + o.tiling["q" + e[n]]);
  393. d = "tiles/" + id + "/" + e[panoSize] + u + "_face" + h + "_" + t.tileX + "_" + t.tileY + ".jpg"
  394. d = this.getTiles(d, sceneCode, useV4url);
  395. g = "?"
  396. }else{//阿里云oss的规则 if (metadata.sceneScheme == 10)
  397. d = 'tiles/4k/' + id + '_skybox' + h + '.jpg?x-oss-process=';
  398. if (e[panoSize] == '512') {
  399. d += 'image/resize,h_512';
  400. } else {
  401. //4k的图,移动端是1k,pc端是2k,放大才是4k
  402. 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
  403. d += 'image/resize,m_lfit,w_' + panoSize + '/crop,w_512,h_512,';
  404. } else {
  405. d = 'tiles/4k/' + id + '_skybox' + h + '.jpg?x-oss-process=image/crop,w_512,h_512,';
  406. }
  407. //起始位置
  408. if (t.tileX == 0) {
  409. d += 'x_0,';
  410. } else {
  411. d += 'x_' + (512 * t.tileX - 1) + ',';
  412. }
  413. if (t.tileY == 0) {
  414. d += 'y_0';
  415. } else {
  416. d += 'y_' + (512 * t.tileY - 1);
  417. }
  418. }
  419. d = this.getTiles(d, sceneCode, useV4url);
  420. g = "&"
  421. }
  422. d += g + 'time='+o.pano.pointcloud.timeStamp //加后缀
  423. return d;
  424. }
  425. }();
  426. TileDownloader.tilegen = true;
  427. TileDownloader.IDLE_REFRESH_DELAY = 500;
  428. TileDownloader.ACTIVE_REFRESH_DELAY = 16;
  429. TileDownloader.DOWNLOAD_RETRIES = 4;
  430. /*
  431. 源:https://4dkk.4dage.com/images/imagesSS-t-ZZR7oKnlIl
  432. 目标:https://4dkk.4dage.com/scene_view_data/SS-t-ZZR7oKnlIl/images
  433. 源:https://4dkk.4dage.com/data/dataSS-t-ZZR7oKnlIl
  434. 目标:https://4dkk.4dage.com/scene_view_data/SS-t-ZZR7oKnlIl/data
  435. 源:https://4dkk.4dage.com/video/videoSS-t-ZZR7oKnlIl
  436. 目标:https://4dkk.4dage.com/scene_view_data/SS-t-ZZR7oKnlIl/video
  437. */
  438. // var tileconc = TileDownloader.tilegen ? 6 : 2;
  439. // publicObjectSet.tileDownloader = new TileDownloader({
  440. // concurrentDownloads: tileconc
  441. // });
  442. // export default new TileDownloader({
  443. // concurrentDownloads: TileDownloader.tilegen ? 6 : 2
  444. // })
  445. /* export default new TileDownloader({
  446. concurrentDownloads: TileDownloader.tilegen ? 6 : 2
  447. }) */
  448. export default TileDownloader