Panorama.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. import * as THREE from "../../../../libs/three.js/build/three.module.js";
  2. import {transitions, easing, lerp} from '../../utils/transitions.js'
  3. import TileUtils from './tile/TileUtils.js'
  4. import math from '../../utils/math.js'
  5. import {TextSprite} from '../../objects/TextSprite.js'
  6. import DepthBasicMaterial from "../../materials/DepthBasicMaterial.js";
  7. let { PanoRendererEvents, PanoramaEvents, PanoSizeClass} = Potree.defines
  8. var texLoader = new THREE.TextureLoader()
  9. const labelProp = {
  10. sizeInfo: {minSize : 200 , maxSize : 250, nearBound : 0.8, farBound : 10},
  11. backgroundColor:{r: 255, g: 255, b: 255, a: 0.4 },
  12. textColor:{r: 0, g: 0, b: 0, a: 1 },
  13. borderRadius: 15,
  14. renderOrder:10,
  15. useDepth:true,
  16. clipDistance: 30, maxClipFactor:0.3, occlusionDistance:3,
  17. }
  18. const labelProp2 = {
  19. //sizeInfo: {minSize : 200 , maxSize : 250, nearBound : 0.8, farBound : 10},
  20. backgroundColor:{r: 255, g: 255, b: 255, a: 0 },
  21. textColor:{r:255 , g: 255, b: 255, a: 1 },
  22. textBorderColor:{r:30 , g:30, b: 30, a: 1 },
  23. textBorderThick:3,
  24. dontFixOrient:true,
  25. renderOrder:10,
  26. fontsize:30,
  27. }
  28. let standardMarkerMat
  29. let markerTex
  30. let getMarerMat = function(){
  31. if(!markerTex) {
  32. markerTex = {
  33. default:texLoader.load( Potree.resourcePath+'/textures/marker.png' ),
  34. ring:texLoader.load( Potree.resourcePath+'/textures/marker2.png' )
  35. }
  36. markerTex.default.anisotropy = 4 // 各向异性过滤 .防止倾斜模糊
  37. markerTex.ring.anisotropy = 4
  38. //有可能被点云遮住吗。
  39. }
  40. return new DepthBasicMaterial({opacity:0.7, side: THREE.DoubleSide , map:markerTex.default ,transparent:true,
  41. clipDistance: 2, occlusionDistance:1, //不能设置太短,因为过渡时深度不准确
  42. //depthTest: !!Potree.settings.useDepthTex,
  43. useDepth: !!Potree.settings.useDepthTex
  44. //改为DepthBasicMaterial是因为原Basic的材质过渡时会先隐藏后出现
  45. })
  46. }
  47. //显示全景图时marker没有被遮挡,如果需要,要换成depthBasicMaterial 或者直接把skybox的深度修改(拿到深度贴图后更如此)
  48. let planeGeo = new THREE.PlaneBufferGeometry(0.2,0.2);
  49. let sg = new THREE.SphereGeometry(0.1, 8, 8);
  50. let smHovered = new THREE.MeshBasicMaterial({/* side: THREE.BackSide, */color: 0xff0000});
  51. let sm = new THREE.MeshBasicMaterial({/* side: THREE.BackSide */});
  52. var rot90 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), Math.PI/2 ); //使用的是刚好适合全景图的,给cube贴图需要转90°
  53. //var rot90 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1,0,0), -Math.PI/2 ); //4dkk->navvis
  54. //var rot901 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,1,0), -Math.PI/2 ); //整张球幕图要旋转下
  55. //rot90 = new THREE.Quaternion().multiplyQuaternions( rot901, rot90)
  56. var old = null;
  57. /*
  58. 转成四维看看的axis:
  59. var a = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), THREE.Math.degToRad(-90)) 因为四维的要绕y转90
  60. 这里的quaternion.multiply(a);
  61. 先乘再换顺序 w : q.w, x:q.x , y:-q.z, z:q.y
  62. */
  63. //暂时直接用4dkkconsole输出的数据
  64. class Panorama extends THREE.EventDispatcher{
  65. constructor(o, images360){//file, time, longitude, latitude, altitude, course, pitch, roll
  66. super()
  67. this.id = o.id; //唯一标识
  68. this.images360 = images360
  69. this.visible = true //for viewer updateVisible
  70. this.enabled = true//是否可以走
  71. this.addEventListener('isVisible',(e)=>{//是否显示该点的mesh(不显示也能走)
  72. //console.log('pano isVisible', this.id, e.visible)
  73. viewer.updateVisible(this.marker, 'panoVisi', e.visible)
  74. Potree.settings.showPanoMesh && (this.mesh.visible = e.visible)
  75. if(e.reason == 'screenshot' || e.visible){
  76. this.label && (this.label.visible = e.visible)//截图时隐藏下
  77. }
  78. viewer.updateVisible(this.label2, 'panoVisi', e.visible)
  79. })
  80. /*
  81. 漫游点可见性:旧
  82. level reason 类型
  83. 2(最高)buildingChange(不在此楼层) unvisible
  84. 1 modeIsShowPanos(漫游模式) visible //不记得为什么加这个了,所以重写
  85. 0 pointcloudVisi(隐藏了数据集) unvisible
  86. */
  87. /*
  88. 漫游点可见性:新
  89. level reason 类型
  90. 2(最高)buildingChange(不在此楼层) unvisible
  91. 1 ifShowMarker(marker显示开关) unvisible
  92. 0 pointcloudVisi(隐藏了数据集) unvisible
  93. */
  94. if(Potree.settings.editType == 'pano'){//漫游点拼合编辑
  95. this.uuid = o.uuid //因为有多个数据集 所以会重复
  96. this.index = o.index //下标, 用于visibles
  97. this.pointcloud = viewer.scene.pointclouds.find(e=>e.panoUuid == o.uuid)
  98. this.pointcloud.panos.push(this)
  99. this.sid = this.pointcloud.dataset_id + '|' + this.uuid //不会更改的标记 用于entity.panos里的标记
  100. this.panosData = o
  101. //数据中原本的位置朝向
  102. this.dataPosition = new THREE.Vector3().copy(o.pose.translation)
  103. this.dataQuaternion = new THREE.Quaternion().copy(o.pose.rotation)
  104. this.dataRotation = new THREE.Euler().setFromQuaternion(this.dataQuaternion)
  105. //因为位置朝向随着点云位置改变,所以直接运用到点云上,这里清零
  106. this.originPosition = new THREE.Vector3() //{x: 0, y: 0, z: 0}
  107. this.quaternion = new THREE.Quaternion() //{w: 0, x: 0, y: 0, z: 1}
  108. //this.quaternion4dkk = math.convertVisionQuaternion(this.quaternion)//4dkk内使用的quaternion
  109. this.visibles = o.visibles
  110. this.rtkState = o.has_rtk ? o.use_rtk : null
  111. const height = 1.4; //相机高度
  112. this.originFloorPosition = this.originPosition.clone()
  113. this.originFloorPosition.z -= height
  114. /* this.originPosition = new THREE.Vector3().copy(o.pose.translation) //{x: 0, y: 0, z: 0}
  115. this.quaternion = new THREE.Quaternion().copy(o.pose.rotation) //{w: 0, x: 0, y: 0, z: 1}
  116. //this.quaternion4dkk = math.convertVisionQuaternion(this.quaternion)//4dkk内使用的quaternion
  117. this.visibles = o.visibles
  118. this.pointcloud = viewer.scene.pointclouds.find(e=>e.dataset_id == o.uuid)
  119. this.pointcloud.panos.push(this)
  120. const height = 1.5; //相机高度
  121. this.originFloorPosition = this.originPosition.clone()
  122. this.originFloorPosition.z -= height
  123. */
  124. }else{
  125. this.originPosition = new THREE.Vector3().fromArray(o.dataset_location)
  126. this.originFloorPosition = new THREE.Vector3().fromArray(o.dataset_floor_location)
  127. this.originID = parseInt(o.file_id)//"file_id":"00022"对应是原本的4dkk的id --来自vision.txt
  128. this.pointcloud = viewer.scene.pointclouds.find(e=>e.dataset_id == o.dataset_id) || viewer.scene.pointclouds[0]
  129. this.pointcloud.panos.push(this)
  130. //this.sid = this.pointcloud.sceneCode + '|' + this.originID //不会更改的标记
  131. this.sid = this.pointcloud.dataset_id + '|' + this.originID //不会更改的标记
  132. //全景图和Cube的水平采样起始坐标相差90度
  133. /* if(from4dkk){
  134. var qua = o.dataset_orientation
  135. var quaternion = new THREE.Quaternion().fromArray(qua)
  136. quaternion = new THREE.Quaternion().multiplyQuaternions(quaternion, rot901);//整张球幕图要旋转下 因为在4dkk里转过,还原。如果是tiles的不用
  137. this.quaternion = new THREE.Quaternion(quaternion.x, -quaternion.z, quaternion.y, quaternion.w) //转化坐标
  138. }else{ */
  139. var qua = o.dataset_orientation
  140. qua = [qua[1], qua[2], qua[3], qua[0]]
  141. this.quaternion = new THREE.Quaternion().fromArray(qua)
  142. this.quaternion4dkk = math.convertVisionQuaternion(this.quaternion)//4dkk内使用的quaternion
  143. this.quaternion2 = this.quaternion.clone()
  144. this.quaternion = new THREE.Quaternion().multiplyQuaternions(this.quaternion, rot90);//全景图和Cube的水平采样起始坐标相差90度,cubeTex转90度
  145. this.rotation4dkk = new THREE.Euler().setFromQuaternion(this.quaternion4dkk)
  146. //}
  147. //this.quaternion1 = Potree.Utils.QuaternionFactory.fromArray(o.dataset_orientation)
  148. //同quaternion
  149. //let xy = this.transform.forward([this.longitude, this.latitude]);
  150. //this.file = `https://4dkk.4dage.com/images/images${Potree.settings.number}/pan/high/${this.id}.jpg`
  151. }
  152. this.rotation = new THREE.Euler().setFromQuaternion(this.quaternion)
  153. this.build()
  154. this.transformByPointcloud() //初始化位移
  155. {//tile
  156. this.minimumTiledPanoLoaded = !1;
  157. this.highestPartialTileRenderOpCompleted = 0;
  158. this.highestFullTileRenderOpCompleted = 0;
  159. this.shouldRedrawOnBaseLoaded = !1;
  160. this.resolutionPromise = {}
  161. this.tiledPanoRenderTarget = null;
  162. this.zoomed = !1;
  163. images360.panoRenderer.addEventListener(PanoRendererEvents.TileRenderSuccess, this.onTileRendered.bind(this));
  164. images360.panoRenderer.addEventListener(PanoRendererEvents.PanoRenderComplete, this.onPanoRendered.bind(this));
  165. images360.panoRenderer.addEventListener(PanoRendererEvents.TileRenderFailure, this.onTileRenderFail.bind(this));
  166. images360.panoRenderer.addEventListener(PanoRendererEvents.UploadAttemptedForAllTiles, this.onUploadAttemptedForAllTiles.bind(this));
  167. }
  168. this.addEventListener('hoverOn', (e)=>{//from Map
  169. if(!e.byMainView){
  170. this.hoverOn(e)
  171. }
  172. })
  173. this.addEventListener('hoverOff', (e)=>{
  174. if(!e.byMainView){
  175. this.hoverOff(e)
  176. }
  177. })
  178. }
  179. setEnable(enable){//是否可以走
  180. viewer.updateVisible(this, 'isEnabled', enable) //令所有marker不可见
  181. this.enabled = enable
  182. //如果当前在全景模式且在这个点,需要切换显示吗? 目前用不到
  183. }
  184. loadDepthImg(){
  185. if(!this.pointcloud.hasDepthTex || this.depthTex || this.depthTexLoading)return
  186. this.depthTexLoading = true
  187. let src = //Potree.settings.number == 'SS-t-7DUfWAUZ3V' ? `${Potree.scriptPath}/data/${Potree.settings.number}/depthMap/${this.originID}.png` :
  188. `${Potree.settings.urls.prefix1}/${Potree.settings.webSite}/${this.pointcloud.sceneCode}/data/${this.pointcloud.sceneCode}/depthmap/${this.originID}.png`
  189. let texture = texLoader.load( src, ()=>{
  190. this.depthTex = texture
  191. this.images360.dispatchEvent({type:'loadedDepthImg', pano:this, loaded:true})
  192. this.depthTexLoading = false
  193. },null,(e)=>{//error
  194. console.error('loadDepthImg失败, 数据集sceneCode'+ this.pointcloud.sceneCode, this.id )
  195. this.pointcloud.hasDepthTex = false
  196. this.images360.dispatchEvent({type:'loadedDepthImg', pano:this, })
  197. });
  198. texture.wrapS = THREE.RepeatWrapping;
  199. texture.flipY = false
  200. texture.magFilter = THREE.LinearFilter
  201. texture.minFilter = THREE.LinearFilter
  202. }
  203. build(){
  204. /* let mesh = new THREE.Mesh(sg, sm);
  205. mesh.scale.set(1, 1, 1);
  206. mesh.material.transparent = true;
  207. mesh.material.opacity = 0.75;
  208. mesh.pano = this;
  209. mesh.name = 'panoSphere'
  210. mesh.addEventListener('mouseover',(e)=>{
  211. mesh.material = smHovered
  212. })
  213. mesh.addEventListener('mouseleave',(e)=>{
  214. mesh.material = sm
  215. })
  216. mesh.addEventListener('click',(e)=>{
  217. this.images360.focusPano(this)
  218. })
  219. this.mesh = mesh;
  220. if(!Potree.settings.showPanoMesh) mesh.visible = false
  221. this.images360.node.add(mesh)
  222. */
  223. { // orientation
  224. //var {course, pitch, roll} = this;
  225. //mesh.quaternion.copy(this.quaternion)
  226. //add
  227. //var quaternion = new THREE.Quaternion().multiplyQuaternions(this.quaternion, rot901);//改 为球目全
  228. //quaternion.premultiply(rot90)
  229. this.panoMatrix = new THREE.Matrix4().makeRotationFromQuaternion(this.quaternion)
  230. this.oriPanoMatrix = this.panoMatrix.clone()
  231. if(this.quaternion2)this.oriPanoMatrix2 = new THREE.Matrix4().makeRotationFromQuaternion(this.quaternion2)
  232. //console.log(this.quaternion)
  233. //this.quaternion = quaternion
  234. }
  235. let marker = new THREE.Mesh(planeGeo, getMarerMat() )
  236. marker.name = 'marker_'+this.id
  237. marker.up.set(0,0,1)
  238. marker.lookAt(marker.up)
  239. marker.scale.set(2,2,2)
  240. this.addEventListener('changeMarkerTex',(e)=>{
  241. marker.material.map = markerTex[e.name]
  242. })
  243. this.marker = marker
  244. if(Potree.settings.editType == 'pano'){
  245. viewer.updateVisible(marker, 'panoEdit', false, 4)
  246. }
  247. this.images360.node.add(marker)
  248. Potree.settings.isTest && this.createTextLabel()
  249. this.createTextLabel2()
  250. /* let mouseover = (e)=>{
  251. if(!e.byMap){
  252. pano.mapMarker.material = panoMarkerMats.selected
  253. if(!e.byMainView) pano.dispatchEvent({type: "hoverOn", byMap:true})
  254. this.needRender = true
  255. }
  256. }
  257. let mouseleave = (e)=>{
  258. if(!e.byMap){
  259. pano.mapMarker.material = panoMarkerMats.default
  260. if(!e.byMainView) pano.dispatchEvent({type: "hoverOff", byMap:true})
  261. this.needRender = true
  262. }
  263. } */
  264. marker.addEventListener('mouseover', this.hoverOn.bind(this));
  265. marker.addEventListener('mouseleave', this.hoverOff.bind(this));
  266. }
  267. transformByPointcloud(){
  268. let position = this.originPosition.clone().applyMatrix4(this.pointcloud.transformMatrix);//也可以用datasetPosTransform算
  269. let floorPosition = this.originFloorPosition.clone().applyMatrix4(this.pointcloud.transformMatrix);
  270. this.setPosition(position, floorPosition)
  271. this.panoMatrix = new THREE.Matrix4().multiplyMatrices(this.pointcloud.rotateMatrix, this.oriPanoMatrix )
  272. //this.panoMatrix2 = Potree.Utils.datasetRotTransform({fromDataset:true, pointcloud:this.pointcloud, matrix:this.oriPanoMatrix, getMatrix:true}) //和上一行结果一样
  273. //quaternion也变下
  274. if(this.oriPanoMatrix2){
  275. this.panoMatrix2 = new THREE.Matrix4().multiplyMatrices(this.pointcloud.rotateMatrix, this.oriPanoMatrix2 )//供DepthImageSampler使用
  276. this.panoMatrix2Inverse = this.panoMatrix2.clone().invert();
  277. }
  278. this.dispatchEvent('rePos')
  279. }
  280. setPosition(position, floorPosition){
  281. this.position = position
  282. this.floorPosition = floorPosition
  283. //this.mesh.position.copy(this.position)
  284. this.marker.position.copy(this.floorPosition)
  285. this.marker.position.z+=0.04//会被点云遮住
  286. if(this.label){
  287. if(Potree.settings.editType == 'pano'){
  288. this.label.position.copy(this.position)
  289. }else{
  290. this.label.position.copy(this.floorPosition)
  291. }
  292. this.label.position.z+=0.14
  293. this.label.update()
  294. }
  295. if(this.label2){
  296. if(Potree.settings.editType == 'pano'){
  297. this.label2.position.copy(this.position)
  298. }else{
  299. this.label2.position.copy(this.floorPosition)
  300. }
  301. this.label2.position.copy(this.marker.position)
  302. this.label2.update()
  303. }
  304. }
  305. hoverOn(e={}) {
  306. //console.log("hoverOn " + this.id )
  307. transitions.start(lerp.property(this.marker.material, "opacity", 1), 250)
  308. if(!e.byMap) this.dispatchEvent({type:'hoverOn', byMainView:true})
  309. if(!e.byImages360) this.images360.dispatchEvent({type:'markerHover', hovered:true, pano:this})
  310. }
  311. hoverOff(e={}){
  312. //console.log("hoverOff " + this.id )
  313. transitions.start(lerp.property(this.marker.material, "opacity", 0.5), 250)
  314. if(!e.byMap) this.dispatchEvent({type:'hoverOff', byMainView:true})
  315. if(!e.byImages360) this.images360.dispatchEvent({type:'markerHover', hovered:false, pano:this})
  316. }
  317. setZoomed(zoomed){
  318. this.zoomed = zoomed;
  319. Potree.settings.displayMode == 'showPanos' && this.updateSkyboxForZoomLevel(); //放大后换成zoomTarget贴图
  320. viewer.dispatchEvent({type:'panoSetZoom', zoomed})
  321. }
  322. enter(){
  323. this.setZoomed(!1),
  324. viewer.dispatchEvent({type:PanoramaEvents.Enter, oldPano:old, newPano:this } )
  325. old = this
  326. //console.log("enter pano "+ this.id)
  327. }
  328. exit(){
  329. /* if(this.tiled)
  330. { */
  331. this.clearWaitDeferreds();
  332. this.minimumTiledPanoLoaded = !1;
  333. this.tiledPanoRenderTarget = null;
  334. this.setZoomed(!1);
  335. this.images360.panoRenderer.deactivateTiledPano(this);
  336. this.highestPartialTileRenderOpCompleted = 0;
  337. this.highestFullTileRenderOpCompleted = 0;
  338. /*}
  339. else
  340. {
  341. this.solidSkybox.dispose();
  342. this.solidSkybox.loaded = !1;
  343. this.solidSkybox.version = 0;
  344. } */
  345. //console.log("exit pano "+ this.id)
  346. viewer.dispatchEvent({type:PanoramaEvents.Exit, pano:this});
  347. }
  348. updateSkyboxForZoomLevel(){
  349. if(this.minimumTiledPanoLoaded){
  350. this.images360.updateProjectedPanos();
  351. }
  352. }
  353. getSkyboxTexture(){
  354. if(this.minimumTiledPanoLoaded)
  355. {
  356. if(this.zoomed && this.images360.qualityManager.maxRenderTargetSize > this.images360.qualityManager.maxNavPanoSize)//change 如果放大后和不放大都是2k就不用这个
  357. {
  358. return this.images360.panoRenderer.zoomRenderTarget.texture;
  359. }
  360. else
  361. {
  362. this.tiledPanoRenderTarget.texture.mapping = THREE.UVMapping//add
  363. return this.tiledPanoRenderTarget.texture;
  364. }
  365. }
  366. else
  367. {
  368. return null;
  369. }
  370. }
  371. isLoaded(e){
  372. if (e && "string" == typeof e)
  373. console.error("Wrong panoSize given to Panorama.isLoaded(); a tiled pano uses PanoSizeClass");
  374. return !!this.minimumTiledPanoLoaded && (!e || this.highestFullTileRenderOpCompleted >= e)//改:原本是:this.highestPartialTileRenderOpCompleted >= e, 希望这代表全部加载完
  375. }
  376. getWaitDeferred(size){//获取不同size的tile贴图的promiss
  377. var t = this.resolutionPromise[this.id];
  378. t || (t = {}, this.resolutionPromise[this.id] = t);
  379. var i = t[size];
  380. return i || (i = {
  381. deferred: $.Deferred(),
  382. active: !1
  383. },
  384. t[size] = i),
  385. i
  386. }
  387. clearWaitDeferreds(){
  388. var e = this.resolutionPromise[this.id];
  389. e || (e = {},
  390. this.resolutionPromise[this.id] = e);
  391. for (var t in e)
  392. if (e.hasOwnProperty(t)) {
  393. var i = e[t];
  394. i.active = !1,
  395. i.deferred = $.Deferred()
  396. }
  397. }
  398. resetWaitDeferred(e){
  399. var t = this.getWaitDeferred(e);
  400. t.active = !1;
  401. t.deferred = $.Deferred();
  402. }
  403. onTileRendered(ev){
  404. ev.id === this.id && this.dispatchEvent({
  405. type:PanoramaEvents.TileLoaded,
  406. size:ev.panoSize, index:ev.tileIndex, count:ev.totalTiles
  407. });
  408. }
  409. onPanoRendered(ev) {
  410. if(ev.id === this.id)
  411. {
  412. this.minimumTiledPanoLoaded = !0;
  413. this.updateSkyboxForZoomLevel();//更新贴图 setProjected
  414. ev.panoSize > this.highestPartialTileRenderOpCompleted && (this.highestPartialTileRenderOpCompleted = ev.panoSize);//应该是更新最高获取到的Partial size
  415. ev.updateFullComplete && ev.panoSize > this.highestFullTileRenderOpCompleted && (this.highestFullTileRenderOpCompleted = ev.panoSize); //应该是更新最高获取到的Full size
  416. //this.dispatchEvent("load", ev.panoSize);
  417. viewer.ifAllLoaded( this);
  418. this.dispatchEvent({type:PanoramaEvents.LoadComplete, size:ev.panoSize, count:ev.totalTiles});
  419. }
  420. }
  421. onTileRenderFail(ev) {
  422. ev.id === this.id && this.dispatchEvent({type:PanoramaEvents.LoadFailed });
  423. }
  424. onUploadAttemptedForAllTiles(ev) {
  425. if (ev.id === this.id) {
  426. var n = this.images360.qualityManager.getPanoSize(PanoSizeClass.BASE);
  427. if(ev.panoSize === n && this.shouldRedrawOnBaseLoaded) //shouldRedrawOnBaseLoaded一直是false。在4dkk里只有初始点在quickstart后变为true。
  428. {
  429. this.shouldRedrawOnBaseLoaded = !1;
  430. this.panoRenderer.resetRenderStatus(this.id, !0, !1);
  431. this.panoRenderer.renderPanoTiles(this.id, null, !0, !0);
  432. }
  433. }
  434. }
  435. createTextLabel(){
  436. this.removeTextLabel()
  437. this.label = new TextSprite(Object.assign({},
  438. labelProp, {text: this.id + "("+this.originID+")"}) //{text: `id:${this.id}, dataset:${this.pointcloud.name}, 4dkkId:${this.originID}`}
  439. );
  440. this.images360.node.add(this.label);
  441. this.floorPosition && this.label.position.copy(this.floorPosition)
  442. }
  443. createTextLabel2(){
  444. this.label2 = new TextSprite(Object.assign({},
  445. labelProp2, {text: /* this.originID */ parseInt(this.id)+1 }) //{text: `id:${this.id}, dataset:${this.pointcloud.name}, 4dkkId:${this.originID}`}
  446. );
  447. this.images360.node.add(this.label2);
  448. this.floorPosition && this.label2.position.copy(this.floorPosition)
  449. let s = 0.4
  450. this.label2.scale.set(s,s,s)
  451. viewer.updateVisible(this.label2, 'notDisplay', false)
  452. }
  453. removeTextLabel(){
  454. if(this.label){
  455. this.label.parent.remove(this.label);
  456. }
  457. }
  458. dispose(){
  459. let i = viewer.images360.panos.indexOf(this);
  460. if(i==-1)return
  461. this.marker.parent.remove(this.marker)
  462. this.removeTextLabel()
  463. if(this.depthTex) this.depthTex.dispose()
  464. viewer.images360.panos.splice(i,1);
  465. this.dispatchEvent('dispose')
  466. //删除tile贴图、depthTex等以后再写
  467. }
  468. };
  469. Panorama.prototype.loadTiledPano = function() {
  470. //var downloads = [] , t = [];
  471. var downloaded = {} , eventAdded = {}, latestPartialRequest = {}; //每个pano对应一组这些
  472. return function(size, dirs, fov, o, a, download) {
  473. var dir = dirs.datasetsLocal.find(e=>e.datasetId == this.pointcloud.dataset_id).direction;
  474. //var dir = dirs
  475. null !== o && void 0 !== o || (o = !0),
  476. null !== a && void 0 !== a || (a = !0);
  477. var l = this.getWaitDeferred(size)
  478. , c = l.deferred
  479. , h = null
  480. , u = null;
  481. fov && ("number" == typeof fov ? h = fov : (h = fov.hFov, u = fov.vFov))
  482. if (!this.isLoaded(size)) {
  483. //console.log('loadTiledPano', this.id, size, fov)
  484. if (!l.active) {
  485. l.active = !0
  486. let name = this.id + ":" + size
  487. downloaded[name] = downloaded[name] || []
  488. /*
  489. this.downloaded = downloaded
  490. this.latestPartialRequest = latestPartialRequest
  491. */
  492. latestPartialRequest[name] = null
  493. if (fov) {
  494. let tileArr = []//add
  495. var d = TileUtils.matchingTilesInDirection(this, size, dir, h, u, tileArr);
  496. latestPartialRequest[name] = tileArr
  497. downloaded[name].forEach((e)=>{
  498. let item = latestPartialRequest[name].find(a=>e.faceTileIndex == a.faceTileIndex && e.face == a.face)
  499. if(item){
  500. item.loaded = true
  501. }
  502. })
  503. if(!latestPartialRequest[name].some(e=>!e.loaded)){//所需要的全部加载成功
  504. //let total = TileUtils.getTileCountForSize(size)
  505. //this.onPanoRendered(this.id, size, total, !0);
  506. c.resolve(size/* , total */);
  507. this.resetWaitDeferred(size)
  508. //console.log('该部分早已经加载好了'+size, this.id)
  509. latestPartialRequest[name] = null
  510. }
  511. //console.log("Loading partial pano: " + this.id + " with " + d + " tiles")
  512. }
  513. if(!eventAdded[this.id]) {
  514. eventAdded[this.id] = !0
  515. this.addEventListener(PanoramaEvents.LoadComplete, function(ev/* e, t */) {//本次任务全部加载完毕
  516. //console.warn('点位(可能部分)下载完成 ', 'id:'+this.id, 'size:'+ev.size )
  517. var i = this.getWaitDeferred(ev.size).deferred;//"pending"为还未完成
  518. i && "pending" === i.state() && this.highestPartialTileRenderOpCompleted >= ev.size && (i.resolve(ev.size, ev.count),
  519. this.resetWaitDeferred(ev.size))//恢复active为false
  520. }.bind(this))
  521. this.addEventListener(PanoramaEvents.LoadFailed, function(ev) {
  522. var t = this.getWaitDeferred(e).deferred;
  523. t && "pending" === t.state() && this.highestPartialTileRenderOpCompleted >= ev.t && (t.reject(ev.t),
  524. this.resetWaitDeferred(ev.t))//恢复active为false
  525. }.bind(this))
  526. this.addEventListener(PanoramaEvents.TileLoaded, function(ev/* t, i, n */) {//每张加载完时
  527. //console.log('tileLoaded', 'id:'+this.id, 'size:'+ev.size, 'tileIndex:'+ev.index )
  528. let tileIndex = ev.index
  529. let total = ev.count
  530. let size = ev.size
  531. let name = this.id + ":" + size
  532. downloaded[name] = downloaded[name] || [] //不是所有的加载都是从loadTiledPano获取的所以会有未定义的情况
  533. let {faceTileIndex,face} = TileUtils.getTileLocation(size, tileIndex, {})
  534. downloaded[name].push({faceTileIndex,face})
  535. var r = this.getWaitDeferred(size).deferred;
  536. if (r && "pending" === r.state()) {
  537. r.notify(size, tileIndex, total);
  538. if(latestPartialRequest[name]){
  539. let item = latestPartialRequest[name].find(e=>e.faceTileIndex == faceTileIndex && e.face == face)
  540. item && (item.loaded = true )
  541. if(!latestPartialRequest[name].some(e=>!e.loaded)){//所需要的局部tiles全部加载成功
  542. this.onPanoRendered(this.id, size, total, !0); //onPanoRendered还会触发 PanoramaEvents.LoadComplete
  543. r.resolve(size, total);
  544. this.resetWaitDeferred(size)
  545. //console.log('该部分加载好了'+size, this.id)
  546. latestPartialRequest[name] = null
  547. }
  548. }
  549. }
  550. /* var r = this.getWaitDeferred(ev.size).deferred;
  551. if (r && "pending" === r.state()) {
  552. r.notify(ev.size, ev.index, ev.count);
  553. var o = downloads[this.id + ":" + ev.size];
  554. if(o){//如果有规定下载哪些tile,只需要下载这些tile则LoadComplete
  555. o.tileCount++
  556. if(o.tileCount === o.targetTileCount){//达到下载目标数
  557. this.onPanoRendered(this.id, ev.size, ev.count, !0);
  558. r.resolve(ev.size, ev.count);
  559. this.resetWaitDeferred(ev.size)
  560. }
  561. }
  562. } */
  563. }.bind(this))
  564. }
  565. }
  566. this.images360.tileDownloader.clearForceQueue()
  567. this.images360.tileDownloader.forceQueueTilesForPano(this, size, dir, h, u, download)
  568. this.tiledPanoRenderTarget = this.images360.panoRenderer.activateTiledPano(this, this.images360.qualityManager.getMaxNavPanoSize(), o)
  569. this.images360.panoRenderer.renderPanoTiles(this.id, dirs, a)
  570. }else{
  571. //console.log('早已经全加载好了' +size, this.id)
  572. c.resolve(size)
  573. }
  574. return c.promise()
  575. }
  576. }()
  577. /*
  578. 经观察发现,navvis的也存在的问题是点云和全景有微小的偏差,导致远处的热点在全景和点云上看位置差别感大,比如一个在路上一个在天空上。
  579. */
  580. export default Panorama