import {View} from "../viewer/View.js"; import Viewport from "../viewer/Viewport.js"; const viewportProps = [ { left:0.5, bottom:0.5, width: 0.5,height:0.5, name : 'MainView', //view: viewer.scene.view, active: true, }, { left:0, bottom:0.5, width: 0.5,height:0.5, name : 'Top', name2 : 'mapViewport', axis:["x","y"], //axisSign:[1,1], active: true, }, { left:0.5, bottom:0, width: 0.5,height:0.5, name : 'Right', axis:["y","z"], //axisSign:[1,1], active: true, }, { left:0, bottom:0, width: 0.5,height:0.5, name : 'Back', axis:["x","z"], //axisSign:[-1,1], // 从镜头方向看 x向左 所以取负 active: true, }, ] var SplitScreen = { //viewer.modules.Alignment.SplitScreen.viewportFitBound(viewer.mapViewer.viewports[0],viewer.bound.boundSize, viewer.bound.center) splitScreen4Views : function(o={}){ var defaultCamera = viewer.scene.getActiveCamera() let {boundSize, center} = viewer.bound var getOrthographicCamera = function(widthRatio, heightRatio, axis){ var widthPX = viewer.renderArea.clientWidth * widthRatio; var heightPX = viewer.renderArea.clientHeight * heightRatio; var aspect = widthPX/heightPX console.log(viewer.renderArea.clientWidth,viewer.renderArea.clientHeight,aspect) var width = Math.max(boundSize[axis[0]], boundSize[axis[1]] * aspect) var orthographicCamera = new THREE.OrthographicCamera(-widthPX/2, widthPX/2, heightPX/2, -heightPX/2, 0.01, 10000); var margin = 50 //px orthographicCamera.zoom = (widthPX - margin) / width//zoom越大视野越小 var moveAtAxis = ['x','y','z'].find(e=>!(axis.includes(e))) orthographicCamera.up.set(0,0,1) orthographicCamera.position.copy(center) orthographicCamera.position[moveAtAxis] += 1000;//偏移一些 在模型外即可 return orthographicCamera } //材质 let material = viewer.scene.pointclouds[0].material this.statesBefore = { mat : { colorType : material.activeAttributeName, color : material.color.clone(), opacity : material.opacity, }, pointDensity : Potree.settings.pointDensity, displayMode : Potree.settings.displayMode, } let beforeRender = function(viewport){ viewer.scene.pointclouds.forEach(e=>{ if(viewport.name == "MainView"){ e.material.activeAttributeName = SplitScreen.statesBefore.mat.colorType e.material.color.copy(SplitScreen.statesBefore.mat.color) e.material.useFilterByNormal = false e.material.opacity = SplitScreen.statesBefore.mat.opacity Potree.settings.pointDensity = 'fourViewports' //本来想比另外三屏高一点质量,结果发现会闪烁,因为点云加载需要时间 (navvis仿版也是一样,以后看看能否优化) }else{ e.material.activeAttributeName = "color" e.material.color.set(e.color) e.material.useFilterByNormal = true e.material.opacity = /* THREE.Math.clamp( */e.material.spacing /* , 0.01,100); */ //0.09 //越稀疏给的opacity应该越高,支持超过1(隧道场景 spacing达9之多) Potree.settings.pointDensity = 'fourViewports' //强制降低点云质量 } }) } let viewports = [] //更改mainViewport参数 viewports.push(viewer.mainViewport) let mapViewport = viewer.mapViewer.viewports[0] viewports.push(mapViewport) for(let i=0;i<4;i++){ let prop = viewportProps[i]; let viewport; let v = viewports.find(e=>e.name == (prop.name2||prop.name)) if(v){ viewport = v viewport.left = prop.left; viewport.bottom = prop.bottom; viewport.width = prop.width; viewport.height = prop.height; } if(!viewport){ viewport = new Viewport( new View(), getOrthographicCamera(prop.width, prop.height, prop.axis), prop ) viewports.push(viewport) } viewport.beforeRender = beforeRender; if(viewport.name != 'MainView'){ viewport.view.setCubeView(viewport.name) viewport.view.position.copy(viewport.camera.position) } } viewer.viewports = viewports; viewer.setLimitFar(false) viewer.mapViewer.attachToMainViewer(true,'split4Screens','dontSet') //覆盖在map上、点云等其他物体之下的一层背景 mapViewport.noPointcloud = false //隐藏地图游标 viewer.updateVisible(viewer.mapViewer.cursor, 'split4Screens', false) viewer.images360.panos.forEach(pano=>{ viewer.updateVisible(pano.mapMarker, 'split4Screens', false) //希望这时候mapMarker已经建好了吧 }) this.enableMap(false) this.enableFloorplan(false) //viewer.dispatchEvent({'type': 'beginSplitView' }) viewer.updateScreenSize({forceUpdateSize:true}) this.viewportFitBound(mapViewport, boundSize, center) Potree.settings.displayMode = 'showPointCloud' }, recoverFrom4Views: function(){ this.unfocusViewport() const {width, height} = viewer.renderer.getSize(new THREE.Vector2()); viewer.renderer.setViewport(0,0,width,height) viewer.renderer.setScissorTest( false ); viewer.scene.pointclouds.forEach(e=>{ e.material.color.set(SplitScreen.statesBefore.mat.color) e.material.activeAttributeName = SplitScreen.statesBefore.mat.colorType e.material.useFilterByNormal = false e.material.opacity = SplitScreen.statesBefore.mat.opacity }) viewer.viewports = [viewer.mainViewport] viewer.mainViewport.width = 1; viewer.mainViewport.height = 1; viewer.mainViewport.left = 0 viewer.mainViewport.bottom = 0; viewer.mainViewport.beforeRender = null viewer.setLimitFar(true) let mapViewport = viewer.mapViewer.viewports[0] viewer.mapViewer.attachToMainViewer(false) viewer.updateVisible(viewer.mapViewer.cursor, 'split4Screens', true) viewer.images360.panos.forEach(pano=>{ viewer.updateVisible(pano.mapMarker, 'split4Screens', true) }) mapViewport.noPointcloud = true this.enableMap(true) this.enableFloorplan(true) Potree.settings.pointDensity = SplitScreen.statesBefore.pointDensity Potree.settings.displayMode = SplitScreen.statesBefore.displayMode //viewer.dispatchEvent({'type': 'finishSplitView' }) viewer.updateScreenSize({forceUpdateSize:true}) }, focusOnViewport : function(name){//全屏 viewer.viewports.forEach((viewport, i )=>{ if(viewport.name == name){ this.focusInfo = { name, left : viewport.left, bottom : viewport.bottom, height : viewport.height, width : viewport.width } viewport.left = 0; viewport.bottom = 0; viewport.height = 1; viewport.width = 1 }else{ viewport.active = false } }) viewer.updateScreenSize({forceUpdateSize:true}) }, unfocusViewport:function(){ if(!this.focusInfo)return viewer.viewports.forEach((viewport, i )=>{ if(this.focusInfo.name == viewport.name){//全屏的恢复 viewport.left = this.focusInfo.left; viewport.bottom = this.focusInfo.bottom; viewport.height = this.focusInfo.height; viewport.width = this.focusInfo.width; } viewport.active = true }) viewer.updateScreenSize({forceUpdateSize:true}) this.focusInfo = null }, updateMapViewerBG(){ let mapViewport = viewer.mapViewer.viewports[0] if(this.floorplanEnabled || this.mapEnabled){ mapViewport.background = 'overlayColor' mapViewport.backgroundColor = new THREE.Color(0,0,0) mapViewport.backgroundOpacity = 0.5; }else{ mapViewport.background = null mapViewport.backgroundColor = null mapViewport.backgroundOpacity = null } }, setFloorplanDisplay: function(e, show=false){ viewer.updateVisible(e.floorplan.objectGroup, 'splitScreen', !!show) }, enableMap(enable){ let map = viewer.mapViewer.mapLayer.maps.find(e=>e.name == 'map') viewer.updateVisible(map.objectGroup, 'splitScreen', !!enable) //viewer.mapViewer.mapGradientBG = viewer.background == 'gradient' && !enable this.mapEnabled = enable this.updateMapViewerBG() if(enable)viewer.mapViewer.mapLayer.needUpdate = true //加载地图 }, enableFloorplan(enable){ //是否让自定义的平面图显示 let floorplan = viewer.mapViewer.mapLayer.maps.find(e=>e.name == 'floorplan') if(!enable){ //隐藏平面图 if(floorplan){ //console.log('已经有floorplan') this.setFloorplanDisplay({floorplan},false) }else{ viewer.mapViewer.mapLayer.addEventListener( 'floorplanLoaded', this.setFloorplanDisplay ) //万一之后才加载 } }else{ if(!floorplan){ //??? }else{ this.setFloorplanDisplay({floorplan},true) } } this.floorplanEnabled = enable this.updateMapViewerBG() }, viewportFitBound:function(viewport, boundSize, center){ //使一个viewport聚焦在某个范围 var prop = viewportProps.find(v => viewport.name == v.name2||viewport.name == v.name) let axis = prop.axis var moveAtAxis = ['x','y','z'].find(e=>!(axis.includes(e))) let ori = viewport.view.position[moveAtAxis] viewport.view.position.copy(center) viewport.view.position[moveAtAxis] = ori //不改变这个值,尤其是mapViewer中的z var width = Math.max(boundSize[axis[0]], boundSize[axis[1]] * viewport.camera.aspect)//视口宽度(米) var margin = 50 //px viewport.camera.zoom = (viewport.resolution.x - margin) / width viewport.camera.updateProjectionMatrix() }, focusOnPointCloud:function(pointcloud){//三个屏都聚焦在这个点云 var boundSize = pointcloud.bound.getSize(new THREE.Vector3); var center = pointcloud.bound.getCenter(new THREE.Vector3); viewer.viewports.forEach(e=>{ if(e.name == 'MainView')return this.viewportFitBound(e, boundSize, center) }) } } export default SplitScreen