MapViewer.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. import * as THREE from "../../../../libs/three.js/build/three.module.js";
  2. import {MapLayer} from './Map.js'
  3. import {FirstPersonControls} from '../../../navigation/FirstPersonControlsNew.js'
  4. import {InputHandler} from "../../../navigation/InputHandlerNew.js";
  5. import {ViewerBase} from "../viewerBase.js"
  6. import {ExtendView} from "../../../viewer/ExtendView.js";
  7. import Viewport from "../Viewport.js";
  8. import math from "../../utils/math.js";
  9. //import CursorDeal from '../utils/CursorDeal.js'
  10. import {Images360} from '../../modules/panos/Images360.js'
  11. import Common from '../../utils/Common.js'
  12. import {transitions, easing, lerp} from "../../utils/transitions.js";
  13. import {config } from "../../settings.js";
  14. /* var centerCross = new THREE.Mesh(new THREE.SphereGeometry(1, 4, 4),new THREE.MeshBasicMaterial({
  15. transparent:true, color:"#ff0000", opacity:0.5
  16. })); */
  17. import CopyShader from '../../materials/postprocessing/CopyShader.js'
  18. import {ShaderPass} from '../../materials/postprocessing/ShaderPass.js'
  19. /* const mapHeight = -1000;//要比点云低。最低
  20. const cameraHeight = 1000; //最高 */
  21. const panosHeight = config.map.mapHeight + 100 //要比点云低 (marker)
  22. const cursorHeight = 0;//比地图高就行
  23. const routeLayerHeight = config.map.mapHeight + 105
  24. const texLoader = new THREE.TextureLoader()
  25. const planeGeo = new THREE.PlaneBufferGeometry(1,1)
  26. const markerSize = 1;
  27. var initCameraFeildWidth = 50
  28. var panoMarkerMats
  29. export class MapViewer extends ViewerBase{
  30. constructor(dom){
  31. super(dom, {
  32. clearColor: Potree.config.mapBG,
  33. name: 'mapViewer',
  34. antialias:true
  35. })
  36. this.visible = true
  37. this.initScene()
  38. this.needRender_ = false
  39. this.mapLayer = new MapLayer(this, this.viewports[0])
  40. this.scene.add(this.mapLayer.sceneGroup)
  41. this.mapLayer.sceneGroup.position.setZ(Potree.config.map.mapHeight)
  42. this.mapRatio = 0.5
  43. this.splitDir = 'leftRight'
  44. this.renderMeasure = false
  45. //因context的preserveDrawingBuffer为false之后,canvas渲染多个viewport时会自动clear,所以若不渲染就会是空的。所以没有变化时就直接拷贝buffer好了。
  46. this.copyPass = new ShaderPass( CopyShader );
  47. this.copyBuffer = new THREE.WebGLRenderTarget( 100, 100 , {
  48. minFilter: THREE.LinearFilter,
  49. magFilter: THREE.LinearFilter,
  50. format: THREE.RGBAFormat,
  51. stencilBuffer: false,
  52. });
  53. viewer.addEventListener("camera_changed", (e)=>{
  54. let needUpdateCursor
  55. if(e.viewport == viewer.mainViewport){
  56. needUpdateCursor = true
  57. }else if(e.viewport == this.viewports[0]){//attachedToViewer
  58. needUpdateCursor = true
  59. this.mapChanged = true
  60. this.updateWhenAtViewer()
  61. e.changeInfo.projectionChanged && this.setViewLimit()
  62. }
  63. needUpdateCursor && this.updateCursor()
  64. })
  65. this.addEventListener("camera_changed", (e)=>{
  66. e.changeInfo.projectionChanged && this.setViewLimit()
  67. })
  68. //viewer.addEventListener("global_mousemove", this.updateWhenAtViewer.bind(this)) //鼠标移动时reticule也动,所以直接就needRender
  69. /* viewer.reticule.addEventListener('update',(e)=>{
  70. if(this.attachedToViewer)this.needRender = true
  71. }) */
  72. viewer.scene.addEventListener("360_images_added", this.addPanos.bind(this))
  73. viewer.addEventListener("loadPointCloudDone", this.initProjection.bind(this))
  74. this.addEventListener('global_click',(e)=>{
  75. if(!e.isTouch && e.button != THREE.MOUSE.LEFT)return
  76. this.updateClosestPano(e.intersect)
  77. })
  78. this.addEventListener('add',(e)=>{//添加其他mesh
  79. this.scene.add(e.object)
  80. if(e.name == 'route'){
  81. e.object.position.z = routeLayerHeight
  82. }
  83. Potree.Utils.setObjectLayers(e.object, 'mapObjects' )
  84. })
  85. viewer.addEventListener('allLoaded',()=>{
  86. this.setViewLimit('standard')
  87. })
  88. if(!Potree.settings.isOfficial){
  89. let domRoot = viewer.renderer.domElement.parentElement;
  90. let elAttach = $("<input type='button' value='map绑定'></input>");
  91. elAttach.css({
  92. position : "absolute",
  93. right : '80%',
  94. bottom: '20px',
  95. zIndex: "10000",
  96. fontSize:'1em', color:"black",
  97. background:'rgba(255,255,255,0.8)',
  98. })
  99. let state = false
  100. elAttach.on("click", () => {
  101. state = !state
  102. this.attachToMainViewer(state, 'measure')
  103. elAttach.val(state ? 'map分离':'map绑定')
  104. });
  105. domRoot.appendChild(elAttach[0]);
  106. }
  107. }
  108. get needRender(){
  109. return this.needRender_
  110. }
  111. set needRender(n){
  112. this.needRender_ = n
  113. n && (this.viewports[0].needRender = true) //使attachedToViewer时在renderDefault中可渲染
  114. }
  115. get mapChanged(){
  116. return this.mapChanged_
  117. }
  118. set mapChanged(c){//镜头移动、地图内容改变都会为true
  119. this.mapChanged_ = c
  120. c && (this.needRender = true)
  121. }
  122. waitLoadDone(callback){//确保加载完后执行
  123. let timer //等待一段时间看有没有新加载的tile,如果超过这个时间没有就不等了,算加载结束
  124. let pauseCountDown = ()=>{//重新等待加载结束,中断倒计时
  125. clearTimeout(timer)
  126. //console.log('pauseCountDown')
  127. }
  128. let freshCountDown = ()=>{//刷新倒计时
  129. //console.log('freshCountDown')
  130. clearTimeout(timer)
  131. timer = setTimeout(()=>{
  132. this.mapLayer.removeEventListener('loadDone', freshCountDown)
  133. this.mapLayer.removeEventListener('startLoad', pauseCountDown)
  134. callback()
  135. }, document.hidden ? 5000 : 500)
  136. }
  137. this.mapLayer.addEventListener('loadDone', freshCountDown)
  138. this.mapLayer.addEventListener('startLoad', pauseCountDown)
  139. if(this.mapLayer.loadingInProgress == 0){
  140. freshCountDown()
  141. }
  142. }
  143. addListener(images360){
  144. images360.addEventListener('flyToPano',e=>{
  145. let toPano = e.toPano
  146. if(toPano.dontMoveMap) return
  147. /* transitions.start(lerp.vector(this.view.position, toPano.pano.position.clone().setZ(cameraHeight),
  148. (pos, progress)=>{
  149. }), toPano.duration, null, 0, easing[toPano.easeName] ); */
  150. let boundSize// = new THREE.Vector2(10,10)
  151. this.moveTo(toPano.pano.position.clone().setZ(Potree.config.map.cameraHeight), boundSize, toPano.duration, null, toPano.easeName)
  152. })
  153. }
  154. initProjection(){
  155. this.started = true
  156. this.mapLayer.initProjection()
  157. }
  158. initScene(){
  159. let w = initCameraFeildWidth
  160. let width = this.renderArea.clientWidth;
  161. let height = this.renderArea.clientHeight;
  162. //let aspect = width / height
  163. this.camera = new THREE.OrthographicCamera(-width/2,width/2,height/2,-height/2/* -w/2, w/2, w/2/aspect, -w/2/aspect */, 0.01, 10000);
  164. this.camera.zoom = width / w //zoom越大视野越小
  165. //this.camera.position.set(0,0,10);
  166. this.camera.up.set(0,0,1)
  167. //this.camera.lookAt(new THREE.Vector3())
  168. //this.camera.updateMatrixWorld()
  169. this.view = new ExtendView();
  170. this.view.position.set(0,0,Potree.config.map.cameraHeight);
  171. this.view.lookAt(0,0,0)
  172. let viewport = new Viewport( this.view, this.camera, {
  173. left:0, bottom:0, width:1, height: 1, name:'mapViewport'
  174. })
  175. viewport.axis = ["x","y"]
  176. viewport.axisSign = [1,1]
  177. viewport.noPointcloud = true; //不要渲染点云
  178. viewport.render = this.render.bind(this)//标志给mainView渲染
  179. //viewport.unableDepth = true //depthBasicMaterial等在此viewport中不开启depth
  180. viewport.addEventListener('resize',()=>{
  181. this.copyBuffer.setSize(viewport.resolution2.x, viewport.resolution2.y)
  182. })
  183. this.viewports = [viewport]
  184. this.controls = new FirstPersonControls(this, this.viewports[0]);
  185. this.controls.setEnable(true)
  186. this.scene = new THREE.Scene();
  187. this.inputHandler = new InputHandler(this, this.scene);
  188. this.inputHandler.name = 'mapInputHandler'
  189. //this.inputHandler.addInputListener(this.controls);
  190. this.inputHandler.registerInteractiveScene(this.scene);//interactiveScenes
  191. this.viewports[0].interactiveScenes = this.inputHandler.interactiveScenes;//供viewer的inputHandler使用
  192. var cursor = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
  193. transparent:true,
  194. opacity:0.9,
  195. depthTest : false, //防止透明冲突
  196. map: texLoader.load(Potree.resourcePath+'/textures/pic_location128.png' )
  197. }))
  198. cursor.position.set(0,0,cursorHeight);
  199. this.cursor = cursor
  200. this.scene.add(cursor)
  201. Potree.Utils.setObjectLayers(this.scene, 'mapObjects' )
  202. }
  203. setViewLimit(state){//设置边界,当编辑空间模型等时要解禁
  204. if(!state)state = this.limitBoundState
  205. if(!state)return
  206. this.limitBoundState = state
  207. let setting = Potree.config.OrthoCameraLimit[state]
  208. if(setting){
  209. this.camera.zoomLimit = $.extend({},setting.zoom);
  210. let lonlatCenter = viewer.transform.lonlatToLocal.inverse([0,0]);
  211. let minY = viewer.transform.lonlatToLocal.forward([lonlatCenter[0], -90+setting.latPad])[1] //屏幕边界的bound
  212. let maxY = viewer.transform.lonlatToLocal.forward([lonlatCenter[0], 90-setting.latPad])[1]
  213. /*this.view.limitBound = new THREE.Box3(
  214. new THREE.Vector3(setting.xBound[0], minY, Potree.config.map.cameraHeight),
  215. new THREE.Vector3(setting.xBound[1], maxY, 1 / 0)
  216. ) */
  217. let halfHeight = this.viewports[0].resolution.y / 2 / this.camera.zoom;//屏幕所占高度的一半
  218. let halfWidth = this.viewports[0].resolution.x / 2 / this.camera.zoom;
  219. this.view.limitBound = new THREE.Box3(
  220. new THREE.Vector3(setting.xBound[0]+halfWidth, minY+halfHeight, Potree.config.map.cameraHeight),
  221. new THREE.Vector3(setting.xBound[1]-halfWidth, maxY-halfHeight, 1 / 0)
  222. )
  223. }else{
  224. this.view.limitBound = null
  225. this.camera.zoomLimit = null
  226. }
  227. }
  228. updateCursor(){
  229. //console.log('pos', viewer.mainViewport.camera.position.toArray() )
  230. var scale = math.getScaleForConstantSize( {//规定下最小最大像素
  231. minSize : 80, maxSize : 200, nearBound : initCameraFeildWidth*0.1 , farBound : initCameraFeildWidth*2,
  232. camera:this.camera , position: this.cursor.getWorldPosition(new THREE.Vector3()),
  233. resolution: this.viewports[0].resolution//2
  234. })
  235. this.cursor.scale.set(scale, scale, scale);//当地图缩放时
  236. this.cursor.position.copy(viewer.mainViewport.camera.position).setZ(cursorHeight)//当场景镜头旋转移动时
  237. this.cursor.rotation.z = viewer.mainViewport.view.yaw
  238. this.needRender = true
  239. }
  240. addPanos(e){
  241. var panosGroup = new THREE.Object3D; panosGroup.name = 'markers'
  242. panoMarkerMats = {
  243. default: new THREE.MeshBasicMaterial({
  244. transparent:true,
  245. opacity: 0.5,
  246. map: texLoader.load(Potree.resourcePath+'/textures/map_marker.png' ),
  247. }),
  248. selected: new THREE.MeshBasicMaterial({
  249. transparent:true,
  250. opacity: 1,
  251. map: texLoader.load(Potree.resourcePath+'/textures/map_marker.png' ),
  252. })
  253. }
  254. e.images.panos.forEach(pano=>{
  255. pano.mapMarker = new THREE.Mesh(planeGeo, panoMarkerMats.default);
  256. pano.mapMarker.position.copy(pano.position).setZ(0)
  257. pano.mapMarker.scale.set(markerSize,markerSize,markerSize)
  258. pano.mapMarker.name = 'mapMarker'
  259. panosGroup.add(pano.mapMarker);
  260. let mouseover = (e)=>{
  261. if(!e.byMap){
  262. pano.mapMarker.material = panoMarkerMats.selected
  263. if(!e.byMainView) pano.dispatchEvent({type: "hoverOn", byMap:true})
  264. this.needRender = true
  265. }
  266. }
  267. let mouseleave = (e)=>{
  268. if(!e.byMap){
  269. pano.mapMarker.material = panoMarkerMats.default
  270. if(!e.byMainView) pano.dispatchEvent({type: "hoverOff", byMap:true})
  271. this.needRender = true
  272. }
  273. }
  274. pano.mapMarker.addEventListener('mouseover', mouseover);
  275. pano.mapMarker.addEventListener('mouseleave', mouseleave);
  276. pano.addEventListener('hoverOn', mouseover)
  277. pano.addEventListener('hoverOff', mouseleave)
  278. let onclick = (e)=>{
  279. viewer.images360.flyToPano(pano)
  280. }
  281. pano.mapMarker.addEventListener('click', onclick);
  282. pano.addEventListener('isVisible',(e)=>{//是否显示该点的mesh(不显示也能走)
  283. //console.log('panoMarker isVisible', pano.id, e.visible)
  284. Potree.Utils.updateVisible(pano.mapMarker, 'panoVisible', e.visible )
  285. this.needRender = true
  286. })
  287. pano.addEventListener('rePos',(e)=>{
  288. pano.mapMarker.position.copy(pano.position).setZ(0)
  289. })
  290. })
  291. this.scene.add(panosGroup)
  292. panosGroup.position.z = panosHeight
  293. this.panosGroup = panosGroup
  294. Potree.Utils.setObjectLayers(panosGroup, 'mapObjects' )
  295. /* e.images.on('markersDisplayChange', (show)=>{
  296. panosGroup.visible = show
  297. this.needRender = true
  298. }) */
  299. //-------
  300. //this.fitPanosToViewport()
  301. this.initFitView()
  302. }
  303. updateClosestPano(intersect){
  304. if(viewer.images360.flying)return;
  305. intersect = intersect && intersect.orthoIntersect
  306. if(!intersect)return
  307. intersect = intersect.clone().setZ(0)
  308. const minDis = 20 //距离鼠标不能太远
  309. var filterFuncs = [
  310. Images360.filters.isEnabled(),
  311. Images360.filters.isVisible(),//只走显示的点,否则会走到别的层
  312. (pano)=>{
  313. return pano.position.clone().setZ(0).distanceTo(intersect) < minDis
  314. },
  315. ];
  316. var pano = Common.find(viewer.images360.panos, filterFuncs, [Images360.sortFunctions.floorDisSquaredToPoint(intersect)]);
  317. if (pano && pano != viewer.images360.currentPano ) {
  318. viewer.images360.flyToPano(pano)
  319. }
  320. }
  321. fitPanosToViewport(){//使所有漫游点占满viewport
  322. //var w = viewer.bound.boundSize.x;
  323. var boundSize = viewer.images360.bound.size.clone().multiplyScalar(1.1);
  324. boundSize.max(new THREE.Vector3(4,4,4))
  325. let endPosition = viewer.images360.bound.center.clone()
  326. this.moveTo(endPosition, boundSize, 0)
  327. }
  328. fitToPointcloud(pointcloud, duration=400){
  329. var boundSize = pointcloud.bound.getSize(new THREE.Vector3)/* .multiplyScalar(1.1); */
  330. boundSize.max(new THREE.Vector3(4,4,4))
  331. let endPosition = pointcloud.bound.getCenter(new THREE.Vector3)
  332. this.moveTo(endPosition, boundSize, duration) //给点duration去变化 否则地图放大后所占的还是很小
  333. }
  334. initFitView(){
  335. let dis = 5 , px = 70 //地图上px像素长度代表的距离为dis //px是手动缩放到5m后发现是这个长度
  336. let zoom = px / dis;
  337. this.camera.zoom = zoom
  338. this.moveTo(viewer.images360.position/* viewer.images360.bound.center */)
  339. this.camera.updateProjectionMatrix()
  340. }
  341. fitToDatasets(datasets){
  342. let bound = new THREE.Box3;
  343. datasets.forEach(e=>bound.union(e.bound))
  344. let center = bound.getCenter(new THREE.Vector3)
  345. let size = bound.getSize(new THREE.Vector3)
  346. this.moveTo(center, size, 200 ) //给duration是为了顺应视口大小改变,缓冲
  347. }
  348. moveTo(endPosition, boundSize, duration=0, margin, easeName, callback ){//前两个参数有xy即可
  349. endPosition = new THREE.Vector3(endPosition.x,endPosition.y,Potree.config.map.cameraHeight)
  350. this.view.moveOrthoCamera(this.viewports[0], {endPosition, boundSize, margin, callback}, duration, easeName)
  351. /* let endZoom, startZoom = this.camera.zoom
  352. //修改相机为bound中心,这样能看到全部(宽度范围内)
  353. this.view.setView({ position:endPosition, duration,
  354. callback:()=>{//done
  355. },
  356. onUpdate:(progress)=>{
  357. if(boundSize){
  358. let aspect = boundSize.x / boundSize.y
  359. let w, h;
  360. if(this.camera.aspect > aspect){//视野更宽则用bound的纵向来决定
  361. h = boundSize.y
  362. //w = h * this.camera.aspect
  363. endZoom = this.viewports[0].resolution.y / h
  364. }else{
  365. w = boundSize.x;
  366. //h = w / this.camera.aspect
  367. endZoom = this.viewports[0].resolution.x / w
  368. }
  369. //onUpdate时更新endzoom是因为画布大小可能更改
  370. this.camera.zoom = endZoom * progress + startZoom * (1 - progress)
  371. this.camera.updateProjectionMatrix()
  372. }
  373. },
  374. Easing:easeName
  375. }) */
  376. }
  377. updateWhenAtViewer(e){//两个触发来源: 1 camera_changed时 2 mapLayer.needUpdate时。 render在viewer中执行
  378. if(this.attachedToViewer){
  379. if(this.started) this.mapLayer.update()
  380. this.needRender = true
  381. }
  382. }
  383. update(delta, areaSize ){
  384. if(!this.visible && !this.attachedToViewer )return
  385. if(this.attachedToViewer){
  386. if(this.mapLayer.needUpdate){
  387. this.updateWhenAtViewer()
  388. }
  389. return
  390. }
  391. this.updateScreenSize()
  392. this.controls.update(delta);
  393. this.view.applyToCamera(this.camera)
  394. let changed = this.cameraChanged()
  395. if(this.started && (changed || this.mapLayer.needUpdate))this.mapLayer.update()
  396. if(changed /*|| || this.needRender */){
  397. /* this.dispatchEvent({
  398. type: "camera_changed",
  399. camera: this.camera,
  400. viewport : this.viewports[0]
  401. }) */
  402. this.mapChanged = true
  403. this.needRender = true
  404. this.updateCursor()//更改大小
  405. }
  406. this.render()
  407. }
  408. attachToMainViewer(state, desc, mapRatio=0.5, options={}){//转移到viewer中。测量时展示or截图需要
  409. if(!Potree.settings.isOfficial)this.renderArea.style.display = state ? 'none':'block'
  410. if(state){
  411. this.enabledOld = this.enabled
  412. this.enabled = true
  413. if(mapRatio != 'dontSet'){
  414. this.changeSplitScreenDir(options.dir, mapRatio)
  415. if(this.attachedToViewer){
  416. //this.fitPanosToViewport()
  417. viewer.updateScreenSize({forceUpdateSize:true})
  418. return
  419. }
  420. viewer.viewports = [viewer.mainViewport, viewer.mapViewer.viewports[0] ];//因为mainViewer的相机变化会触发map的变化,所以先渲染mainViewer
  421. }
  422. if(desc == 'measure') this.inputHandler.registerInteractiveScene(viewer.measuringTool.scene);//虽然用的是viewer的inputHandler,但借用了this.inputHandler的interactiveScenes
  423. else if(desc == 'split4Screens') {
  424. this.inputHandler.registerInteractiveScene(viewer.scene.scene);
  425. }
  426. }else{
  427. if(!this.attachedToViewer)return
  428. viewer.mainViewport.left = 0;
  429. viewer.mainViewport.bottom = 0;
  430. viewer.mainViewport.width = 1;
  431. viewer.mainViewport.height = 1;
  432. this.viewports[0].width = 1;
  433. this.viewports[0].bottom = 0;
  434. this.viewports[0].height = 1;
  435. this.viewports[0].left = 0;
  436. this.renderMeasure || this.inputHandler.unregisterInteractiveScene(viewer.measuringTool.scene);
  437. this.inputHandler.unregisterInteractiveScene(viewer.scene.scene);
  438. viewer.viewports = [viewer.mainViewport]
  439. this.updateScreenSize({forceUpdateSize:true}) //更新相机projectionMatrix
  440. }
  441. //if(desc == 'measure')this.renderMeasure = state
  442. this.attachedToViewer = state
  443. viewer.updateScreenSize({forceUpdateSize:true})
  444. //mapRatio != 'dontSet' && !options.dontFit && this.moveTo(...)//要写在updateScreenSize后面,因为要根据视图大小来fit
  445. if(options.moveToCurrentPos){
  446. let boundSize = new THREE.Vector2(10,10)
  447. let duration = 1000
  448. this.moveTo(viewer.images360.position.clone(), boundSize, duration)
  449. }
  450. this.needRender = true
  451. }
  452. setDrawMeasure(draw){
  453. this.renderMeasure = !!draw
  454. if(draw){
  455. this.inputHandler.registerInteractiveScene(viewer.measuringTool.scene);
  456. }else{
  457. this.inputHandler.unregisterInteractiveScene(viewer.measuringTool.scene);
  458. }
  459. }
  460. changeSplitScreenDir(dir, mapRatio){//左右 | 上下
  461. //if(!dir || dir == this.dir)return
  462. if(dir )this.splitDir = dir
  463. this.updateSplitSize(mapRatio)
  464. /* if(this.attachedToViewer){ //如果已经分屏了,中途修改方向的话……
  465. this.updateSplitSize()
  466. } */
  467. }
  468. updateSplitSize(mapRatio){
  469. if(mapRatio != void 0) this.mapRatio = mapRatio
  470. //console.log(this.mapRatio)
  471. if(this.splitDir == 'leftRight'){//地图在左方
  472. viewer.mainViewport.left = this.mapRatio
  473. viewer.mainViewport.width = 1-this.mapRatio
  474. this.viewports[0].width = this.mapRatio;
  475. viewer.mainViewport.bottom = this.viewports[0].bottom = 0
  476. viewer.mainViewport.height = this.viewports[0].height = 1
  477. }else if(this.splitDir == 'upDown'){ //地图在下方
  478. viewer.mainViewport.bottom = this.mapRatio
  479. viewer.mainViewport.height = 1-this.mapRatio
  480. this.viewports[0].height = this.mapRatio;
  481. viewer.mainViewport.left = this.viewports[0].left = 0
  482. viewer.mainViewport.width = this.viewports[0].width = 1
  483. }
  484. if(this.attachedToViewer){
  485. viewer.updateScreenSize({forceUpdateSize:true})
  486. }
  487. }
  488. render1(params={}){//viewer的preserveDrawingBuffer为false时的版本
  489. let needCopy, waitCopy
  490. if(!this.visible && !this.attachedToViewer || !this.needRender && !params.force){
  491. if(this.attachedToViewer ){
  492. needCopy = true
  493. }else{
  494. return
  495. }
  496. }
  497. waitCopy = this.attachedToViewer && this.needRender && !params.force//是否写入到copyBuffer。双屏时,若needRender就拷贝到copyBuffer中,双屏时就直接使用copyBuffer。 四屏时因渲染点云会每帧都渲染,所以不需要缓存。
  498. let renderer = params.renderer || this.renderer
  499. if(waitCopy){
  500. this.copyBuffer.setSize(params.viewport.resolution2.x, params.viewport.resolution2.y)
  501. renderer.setRenderTarget(this.copyBuffer)
  502. }else if(params.target){
  503. renderer.setRenderTarget(params.target)
  504. }
  505. /* if(params.resize){
  506. this.emitResizeMsg(new THREE.Vector2(params.width,params.height, viewport:params.viewport))
  507. } */
  508. params.clear ? params.clear() : renderer.clear();
  509. if(!needCopy || waitCopy){//重绘
  510. viewer.dispatchEvent({type: "render.begin", viewer: this, viewport:this.viewports[0], params });
  511. Potree.Utils.setCameraLayers(this.camera, ['map','mapObjects' , 'bothMapAndScene' ])
  512. if(this.mapGradientBG){//渲染背景
  513. viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg);
  514. renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
  515. }
  516. renderer.render(this.scene, this.camera);
  517. renderer.render(viewer.scene.scene, this.camera);
  518. //测量线等
  519. //params.renderOverlay && params.renderOverlay( $.extend({}, params, { isMap:true }))
  520. renderer.setRenderTarget(params.target||null)
  521. }
  522. if(needCopy || waitCopy){//使用缓存 ----当viewer的preserveDrawingBuffer为false的话,使用buffer
  523. this.copyPass.render(null,null, null, renderer, params.target||null, this.copyBuffer)
  524. }
  525. this.needRender = false
  526. return true
  527. }
  528. clear(params){
  529. if(this.transparentBG){
  530. this.renderer.setClearColor( 0x000000, 0 );
  531. }else{
  532. this.renderer.setClearColor( Potree.config.mapBG, 1 );
  533. }
  534. (params.renderer || this.renderer).clear()
  535. }
  536. //拆成两次渲染,一个地图一个其他物体,且地图渲染后保存在buffer中,只有当地图变化后才重渲染。
  537. render(params={}){
  538. if(!this.visible && !this.attachedToViewer || !this.needRender && !params.force){ //注意:mapViewer.needRender的权重高于它的viewport的needRender,也就是说,当attachedToViewer时,viewer即使needRender, mapViewer也不一定会渲染。
  539. return
  540. }
  541. viewer.addTimeMark('mapRender','start')
  542. let renderer = params.renderer || this.renderer
  543. if(this.mapChanged){ //渲染地图背景
  544. renderer.setRenderTarget(this.copyBuffer)
  545. params.clear ? params.clear(params) : this.clear(params);
  546. if(this.mapGradientBG){//渲染背景
  547. viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg);
  548. renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
  549. }
  550. Potree.Utils.setCameraLayers(this.camera, ['map'])
  551. renderer.render(this.scene, this.camera);
  552. params.renderBG && params.renderBG(this.viewports[0])
  553. this.mapChanged = false
  554. renderer.setRenderTarget(params.target||null)
  555. }
  556. params.clear ? params.clear(params) : this.clear(params);
  557. this.copyPass.render(null,null, null,renderer, params.target||null, this.copyBuffer) //拷贝地图背景
  558. renderer.clearDepth(); //防止地图遮挡其他物体
  559. //绘制其他物体
  560. Potree.Utils.setCameraLayers(this.camera, ['mapObjects' , 'bothMapAndScene' ])
  561. viewer.dispatchEvent({type: "render.begin", viewer: this, viewport:this.viewports[0], params });
  562. this.attachedToViewer || renderer.render(viewer.scene.scene, this.camera); //类同renderOverlay
  563. renderer.render(this.scene, this.camera);
  564. if(!this.attachedToViewer && this.renderMeasure){//在未attach到主页面时也要渲染测量线
  565. viewer.dispatchEvent({type: "render.pass.perspective_overlay", camera:this.camera, /* screenshot:params.screenshot, */viewport:this.viewports[0], renderer});
  566. }
  567. renderer.setRenderTarget(null)
  568. this.needRender = false
  569. viewer.addTimeMark('mapRender','end')
  570. return true
  571. }
  572. renderOverlay(){//偶尔需要绘制测量线
  573. viewer.renderOverlay({
  574. camera: this.camera, viewport:this.viewports[0], renderer:this.renderer
  575. })
  576. }
  577. }
  578. /*
  579. 渲染顺序:
  580. 地图
  581. 背景Overlay
  582. 地图scene的物体,如cursor、 marker
  583. 点云(如果有)
  584. overlay,两层:第一层:viewer的scene中bothMapAndScene的如reticule. 第二层:如测量线(attachToMainViewer时才渲染)
  585. */
  586. //本地调试地图白屏是因为代码自动更新了 但没刷新