TilePrioritizer.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. import {Images360} from '../Images360.js'
  2. import TileUtils from './TileUtils.js'
  3. import cameraLight from '../../../utils/cameraLight.js'
  4. import math from '../../../utils/math.js'
  5. import Common from '../../../utils/Common.js'
  6. import * as THREE from "../../../../../libs/three.js/build/three.module.js";
  7. import browser from '../../../utils/browser.js'
  8. let {DownloadStatus} = Potree.defines
  9. var h = Object.freeze({
  10. None: 0,
  11. DirectionalFOV: 1
  12. });
  13. var u = function () {
  14. var e = function e(t, i) {
  15. var n = e._panoSpaceDir,
  16. r = e._fovThreshold,
  17. o = e._fovThresholdNarrow,
  18. a = Math.max(Math.min(n.dot(t.direction), 1), -1),
  19. s = Math.max(Math.min(n.dot(i.direction), 1), -1);
  20. return t._dot = a,
  21. i._dot = s,
  22. a >= r && s < r ? -1 : a < r && s >= r ? 1 : a >= o && s < o ? -1 : a < o && s >= o ? 1 : t.panoSize > i.panoSize ? 1 : i.panoSize > t.panoSize ? -1 : -(a - s)
  23. };
  24. return e._panoSpaceDir = new THREE.Vector3,
  25. e._fovThreshold = -1,
  26. e._fovThresholdNarrow = -1,
  27. e
  28. }();
  29. export default class TilePrioritizer {//优先级处理序列
  30. constructor(e,t, i, o, a) {
  31. this.qualityManager = e;
  32. this.maxNavQuality = this.qualityManager.getMaxNavPanoSize();
  33. this.maxZoomQuality = this.qualityManager.getMaxZoomPanoSize();
  34. this.baseSize = t;
  35. this.standardSize = i;
  36. this.highSize = o;
  37. this.ultraHighSize = a;
  38. this.priorityCriteria = new TilePrioritizer.PriorityCriteria(null, new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, -1), new THREE.Vector3(0, 0, -1));
  39. }
  40. updateCriteria(e, t, i, n) {//由player更新
  41. this.priorityCriteria.pano = e,
  42. this.priorityCriteria.cameraPosition.copy(t),
  43. //this.priorityCriteria.cameraDir.copy(i),
  44. this.priorityCriteria.cameraDirs = i
  45. this.priorityCriteria.upcomingPanos = n,
  46. this.maxNavQuality = this.qualityManager.getMaxNavPanoSize(),
  47. this.maxZoomQuality = this.qualityManager.getMaxZoomPanoSize()
  48. }
  49. canDownloadSize(e) {
  50. return this.maxNavQuality >= e || this.maxZoomQuality >= e && this.zoomingActive
  51. }
  52. /* populateNeighborPanos(e, t, i) {
  53. i = i || [],
  54. i.length = 0;
  55. var n = t.getNeighbours(e);
  56. for (var r in n)
  57. if (n.hasOwnProperty(r)) {
  58. var o = t.get(r);
  59. if(!o){
  60. console.log(1)
  61. }
  62. i.push(o)
  63. }
  64. return i
  65. } */
  66. getNearPanos(panos){
  67. if(!this.priorityCriteria.pano || viewer.mainViewport.view.isFlying())return
  68. let cameraDirLocals = this.priorityCriteria.cameraDirs.vectorForward
  69. this.populateScoredPanos(panos, [], cameraDirLocals , Infinity, true);
  70. }
  71. filterDepthTex(panos) {// 下载depthTex
  72. if(!Potree.settings.useDepthTex )return
  73. viewer.addTimeMark('filterDepthTex','start')
  74. let dlCount = 1 //window.slowDown ? 0 : (browser.isMobile() ? 1 : Common.getBestCountFPS('loadDepTexCount', false, 1, 2, 57, 62 ) )
  75. let loadingCount = panos.filter(p=>p.depthTexLoading).length
  76. if(viewer.mapViewer){
  77. let mapLayer = viewer.mapViewer.mapLayer
  78. loadingCount += mapLayer.loadingInProgress * 1.5 + mapLayer.waitQueue.length
  79. }
  80. if(loadingCount<dlCount){
  81. //console.log('dlCount-loadingCount', dlCount-loadingCount)
  82. (this.nearPanos || panos).filter(p=>!p.depthTex).slice(0, dlCount-loadingCount).forEach(p=>p.loadDepthImg())
  83. }
  84. viewer.addTimeMark('filterDepthTex','end')
  85. }
  86. populateScoredPanos(/* e, */ t, i, dirs, count, dontFilterDir) {
  87. i = i || [],
  88. i.length = 0;
  89. viewer.addTimeMark('populateScoredPanos','start')
  90. var s = [Images360.filters.not(this.priorityCriteria.pano)],
  91. l = [Images360.scoreFunctions.distanceSquaredNew(this.priorityCriteria.pano), Images360.scoreFunctions.direction(this.priorityCriteria.pano.position, dirs)]
  92. /* if(!dontFilterDir){//太耗时了,尤其是点多时,直接去掉,反正有count限制。如果必须的话,使用direction中得到的值
  93. s.push(Images360.filters.inPanoDirection(this.priorityCriteria.pano.position, dirs, TilePrioritizer.DIRECTION_SCORE_STRICTNESS) )
  94. } */
  95. let c = Common.sortByScore(t, s, l);
  96. //900个点的时候populateScoredPanos已经耗时1.8
  97. viewer.addTimeMark('populateScoredPanos','end')
  98. this.nearPanos = c.map(e=>e.item); //xzw add 用于获得邻近点位序列
  99. if (c)
  100. for (var h = 0; h < c.length && h < count; h++) {
  101. var u = c[h].item;
  102. i.push(u)
  103. }
  104. return i
  105. }
  106. queueTilesForPanos(e, t, i, n, r) {
  107. for (var o = 0, a = 0; a < t.length; a++) {
  108. var s = t[a],
  109. l = this.queueTilesForPano(e, i, s, n);
  110. if (o += l > 0 ? 1 : 0,
  111. r && o >= r)
  112. break
  113. }
  114. return o
  115. }
  116. /* queueTilesInDirectionForPanos(e, t, i, n, r, o, a, s) {//没用到
  117. for (var l = 0, c = 0; c < i.length; c++) {
  118. var h = i[c],
  119. u = this.queueTilesInDirectionForPano(e, t, h, n, o, a);
  120. if (l += u > 0 ? 1 : 0,
  121. s && l >= s)
  122. break
  123. }
  124. return l
  125. }
  126. */
  127. canIncludeDescriptor(e) {
  128. return e.status !== DownloadStatus.Downloading && e.status !== DownloadStatus.Downloaded
  129. }
  130. canIncludePano(e, t) {
  131. return !e.isLoaded(t)
  132. }
  133. getFOVDotThreshold(e) {
  134. return Math.cos(THREE.Math.degToRad(e / 2))
  135. }
  136. setZoomingActive(e) {
  137. e !== this.zoomingActive && (this.zoomingActive = e)
  138. }
  139. }
  140. TilePrioritizer.PriorityCriteria = function (e, t, i, n, o) {
  141. this.pano = e,
  142. this.cameraPosition = (new THREE.Vector3).copy(t),
  143. //this.cameraDir = (new THREE.Vector3).copy(i),
  144. this.cameraDirs = [], //
  145. this.panoSpaceDir = (new THREE.Vector3).copy(n),
  146. this.upcomingPanos = o,
  147. this.copy = function (e) {
  148. this.pano = e.pano,
  149. this.cameraPosition.copy(e.cameraPosition),
  150. //this.cameraDir.copy(e.cameraDir),
  151. this.cameraDirs = e.cameraDirs
  152. this.panoSpaceDir.copy(e.panoSpaceDir),
  153. this.upcomingPanos = o
  154. },
  155. this.zoomingActive = !1
  156. }
  157. TilePrioritizer.DIRECTIONAL_FOV = 180;
  158. TilePrioritizer.DIRECTIONAL_FOV_NARROW = 120;
  159. TilePrioritizer.MAX_SCORED_PANOS_TOCONSIDER = 6;
  160. TilePrioritizer.MAX_SCORED_PANOS_TOADD = 2;
  161. TilePrioritizer.MAX_UPCOMING_PANOS_TOADD = 3;
  162. TilePrioritizer.DIRECTION_SCORE_STRICTNESS = .75;
  163. TilePrioritizer.appendQueue = function (e, t) {
  164. if (e && t)
  165. for (var i = 0; i < t.length; i++){
  166. e.push(t[i])
  167. //console.log(t[i])
  168. }
  169. };
  170. TilePrioritizer.sortPanoTiles = function (descriptors, pano, dir) {
  171. if(dir.datasetsLocal) dir = dir.datasetsLocal.find(e=>e.datasetId == pano.pointcloud.dataset_id).direction;//add
  172. u._panoSpaceDir.copy(dir)
  173. TileUtils.getRelativeDirection(pano.quaternion4dkk, u._panoSpaceDir) //应该是将dir根据quaternion转化下
  174. u._fovThresholdNarrow = math.getFOVDotThreshold(TilePrioritizer.DIRECTIONAL_FOV_NARROW)
  175. u._fovThreshold = math.getFOVDotThreshold(TilePrioritizer.DIRECTIONAL_FOV)
  176. descriptors.sort(u)
  177. };
  178. TilePrioritizer.insertSortedPanoTile = function (e, t, pano, dir) {
  179. if(dir.datasetsLocal) dir = dir.datasetsLocal.find(e=>e.datasetId == pano.pointcloud.dataset_id).direction;//add
  180. u._panoSpaceDir.copy(dir),
  181. TileUtils.getRelativeDirection(pano.quaternion4dkk, u._panoSpaceDir),
  182. u._fovThresholdNarrow = math.getFOVDotThreshold(TilePrioritizer.DIRECTIONAL_FOV_NARROW),
  183. u._fovThreshold = math.getFOVDotThreshold(TilePrioritizer.DIRECTIONAL_FOV);
  184. for (var o = -1, a = 0; a < e.length; a++) {
  185. var s = u(t, e[a]);
  186. if (s <= 0) {
  187. o = a;
  188. break
  189. }
  190. }
  191. if (o === -1)
  192. e[e.length] = t;
  193. else {
  194. for (var h = e.length; h > o; h--)
  195. e[h] = e[h - 1];
  196. e[o] = t
  197. }
  198. };
  199. TilePrioritizer.prototype.filterAndPrioritize = function () {//挑选出优先加载的 pano和tile (有点复杂,没看很懂)
  200. var e = [],
  201. t = [],
  202. i = [];
  203. return function (queue, panos, tileDownloader) {
  204. //this.populateNeighborPanos(this.priorityCriteria.pano, panos, e);
  205. /* let cameraDirLocals = this.priorityCriteria.cameraDirs.map(e=>{ //add
  206. var dataset = viewer.scene.pointclouds.find(u=>u.dataset_id == e.datasetId)
  207. var matrix = new THREE.Matrix4().copy(dataset.rotateMatrix)
  208. var direction = math.convertVector.YupToZup(e.direction)
  209. return {
  210. datasetId:e.datasetId,
  211. direction: direction.clone().applyMatrix4(matrix)
  212. }
  213. }) */
  214. let cameraDirLocals = this.priorityCriteria.cameraDirs.vectorForward
  215. //获得视野范围内的邻近点位序列t
  216. this.populateScoredPanos(/* this.priorityCriteria.pano, */panos, t, cameraDirLocals , TilePrioritizer.MAX_SCORED_PANOS_TOCONSIDER);
  217. //t.filter(p=>!p.depthTex).slice(0, Potree.config.depTexDlCount).forEach(p=>p.loadDepthImg()) //add
  218. var s = this.baseSize //512
  219. ,
  220. l = this.standardSize //1024
  221. ,
  222. c = this.highSize //2048
  223. ,
  224. h = this.priorityCriteria.pano.pointcloud.tileClass //xzw //this.ultraHighSize; //4096
  225. this.queueTilesForPano(queue, tileDownloader, this.priorityCriteria.pano, s); //把当前pano的512下载了
  226. if (this.priorityCriteria.upcomingPanos) {// 添加即将走到的点(之前用于导览路线)512 tiles
  227. this.queueTilesForPanos(queue, this.priorityCriteria.upcomingPanos, tileDownloader, s, TilePrioritizer.MAX_UPCOMING_PANOS_TOADD);
  228. }
  229. i.length = 0;
  230. //把当前pano角度范围内的tile按照分辨率从低到高加入队列
  231. if (this.canDownloadSize(l)) {//1024如果在限制范围内的话
  232. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, l, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV_NARROW);
  233. }
  234. TilePrioritizer.sortPanoTiles(i, this.priorityCriteria.pano, this.priorityCriteria.cameraDirs); //排序
  235. TilePrioritizer.appendQueue(queue, i);
  236. //添加邻近点t 512的tiles
  237. this.queueTilesForPanos(queue, t, tileDownloader, s, TilePrioritizer.MAX_SCORED_PANOS_TOADD);
  238. i.length = 0;
  239. //NARROW :
  240. if (this.canDownloadSize(c)) {//2048
  241. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, c, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV_NARROW);
  242. }
  243. if (this.canDownloadSize(h) && this.priorityCriteria.pano.pointcloud.tileRes != '2k') {//4096
  244. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, h, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV_NARROW);
  245. }
  246. TilePrioritizer.sortPanoTiles(i, this.priorityCriteria.pano, this.priorityCriteria.cameraDirs);//排序
  247. TilePrioritizer.appendQueue(queue, i);
  248. i.length = 0;
  249. if (this.canDownloadSize(l)) {//1024
  250. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, l, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV);
  251. }
  252. if (this.canDownloadSize(c)) {//2048
  253. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, c, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV);
  254. }
  255. if (this.canDownloadSize(h) && this.priorityCriteria.pano.pointcloud.tileRes != '2k') {//4096
  256. this.queueTilesInDirectionForPano(i, tileDownloader, this.priorityCriteria.pano, h, this.priorityCriteria.cameraPosition, this.priorityCriteria.cameraDirs, TilePrioritizer.DIRECTIONAL_FOV);
  257. }
  258. TilePrioritizer.sortPanoTiles(i, this.priorityCriteria.pano, this.priorityCriteria.cameraDirs);//排序
  259. TilePrioritizer.appendQueue(queue, i);
  260. this.queueTilesForPanos(queue, e, tileDownloader, s); // 如果前面有populateNeighborPanos的话,这步就是加neibour
  261. }
  262. }()
  263. TilePrioritizer.prototype.queueTilesInDirectionForPano = function () {
  264. var e = {
  265. filter: h.DirectionalFOV,
  266. direction: new THREE.Vector3,
  267. fov: 60
  268. },
  269. t = new THREE.Vector3;
  270. return function (i, n, pano, o, a, dirs, c) {
  271. var dir = dirs.datasetsLocal.find(e=>e.datasetId == pano.pointcloud.dataset_id).direction;//add
  272. //var dir = dirs
  273. t.copy(dir);
  274. TileUtils.getRelativeDirection(pano.quaternion4dkk, t);
  275. e.direction.copy(t);
  276. e.fov = c;
  277. return this.filterAndQueueTileDownloadDescriptors(i, n, pano, o, e)
  278. }
  279. }()
  280. TilePrioritizer.prototype.filterAndQueueTileDownloadDescriptors = function () {
  281. var e = [];
  282. return function (t, i, n, r, o) {
  283. var a = i.getTileDownloadDescriptors(n, r);
  284. e.length = 0,
  285. this.filterTileDownloadDescriptors(n, a, e, o);
  286. for (var s = 0, l = 0; l < e.length; l++) {
  287. var c = e[l];
  288. if (c) {
  289. t.push(c);
  290. s++;
  291. }
  292. }
  293. return s
  294. }
  295. }()
  296. TilePrioritizer.prototype.filterTileDownloadDescriptors = function () {
  297. new THREE.Vector3;
  298. return function (e, t, i, n) {
  299. var r, o;
  300. switch (n.filter) {
  301. case h.DirectionalFOV:
  302. for (r = 0; r < t.length; r++)
  303. o = t[r],
  304. TileUtils.isTileWithinFOV(o.panoSize, o.tileSize, o.face, o.tileX, o.tileY, n.direction, n.fov) && i.push(o);
  305. break;
  306. default:
  307. for (r = 0; r < t.length; r++)
  308. o = t[r],
  309. i.push(o)
  310. }
  311. for (r = 0; r < i.length; r++)
  312. o = i[r],
  313. this.canIncludeDescriptor(o) || (i[r] = null)
  314. }
  315. }()
  316. TilePrioritizer.prototype.queueTilesForPano = function () {
  317. var e = {
  318. filter: h.None
  319. };
  320. return function (t, i, n, r) {
  321. return this.filterAndQueueTileDownloadDescriptors(t, i, n, r, e)
  322. }
  323. }()
  324. /* TilePrioritizer.prototype.queueTilesForPanosInDirection = function () { //没用到
  325. var e = new THREE.Vector3;
  326. return function (t, i, n, r, o, a, s, l) {
  327. for (var h = 0, u = 0; u < n.length; u++) {
  328. var d = n[u];
  329. e.copy(d.position),
  330. e.sub(o),
  331. e.normalize();
  332. var p = Math.max(Math.min(a.dot(e), 1), -1),
  333. f = c.getFOVDotThreshold(s);
  334. if (p >= f) {
  335. var g = this.queueTilesInDirectionForPano(t, i, d, r, o, a, s);
  336. if (h += g > 0 ? 1 : 0,
  337. l && h >= l)
  338. break
  339. }
  340. }
  341. return h
  342. }
  343. }() */