MapViewer.js 32 KB

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