xzw 3 lat temu
rodzic
commit
c542af0b7c

+ 2 - 2
libs/three.js/build/three.module.js

@@ -220,7 +220,7 @@ Object.assign( EventDispatcher.prototype, {
 
 		}
 
-		if ( listeners[ type ].indexOf( listener ) === - 1 ) { 
+		if ( !listeners[ type ].some(e=>e.listener == listener )  ) { 
 			//listeners[ type ].push( listener );
             listeners[type].push({ listener,  importance});
             listeners[type] = listeners[type].sort((e,a)=> a.importance - e.importance)//add
@@ -234,7 +234,7 @@ Object.assign( EventDispatcher.prototype, {
 
 		const listeners = this._listeners;
 
-		return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
+		return listeners[ type ] !== undefined &&  listeners[ type ].some(e=>e.listener == listener )    
 
 	},
 

+ 14 - 15
libs/three.js/lines/LineMaterial.js

@@ -288,7 +288,7 @@ ShaderLib[ 'line' ] = {
 
                 float fragDepth = convertToLinear(gl_FragCoord.z);
 
-                vec2 depthTxtCoords = vec2(gl_FragCoord.x - viewportOffset.x,  gl_FragCoord.y) / resolution;
+                vec2 depthTxtCoords = vec2(gl_FragCoord.x - viewportOffset.x,  gl_FragCoord.y - viewportOffset.y) / resolution;
 
                 float textureDepth = convertToLinear(texture2D(depthTexture, depthTxtCoords).r);
 
@@ -614,10 +614,10 @@ var LineMaterial = function ( parameters ) {
 
 
     viewer.addEventListener('resize',(e)=>{
-        //if(!e.viewport || e.viewport.name != 'mapViewport'){
+        if(!e.viewport || e.viewport.camera.isPerspectiveCamera){//地图不需要
             setSize(e)
             //console.log(this.name +  viewportOffset.toArray())     
-        //} 
+        } 
     })  
 
     
@@ -627,16 +627,14 @@ var LineMaterial = function ( parameters ) {
         //add
         this.updateDepthParams()
         
-        viewer.addEventListener('camera_changed', (e)=>{
+        /* viewer.addEventListener('camera_changed', (e)=>{
             if(e.viewport.name != 'mapViewport') this.updateDepthParams(e) 
-        })   
-
-        
-        
+        })  */  
+ 
     
-        /* viewer.addEventListener("render.begin", (e)=>{//before render  如果有大于两个viewport的话可能要
-            if(e.viewport.name != 'mapViewport') this.updateDepthParams({camera:e.viewport.camera})
-        }) */
+        viewer.addEventListener("render.begin", (e)=>{//before render  如果有大于两个viewport的话,不同viewport用不同的depthTex
+            if(e.viewport.camera.isPerspectiveCamera) this.updateDepthParams(e)
+        }) 
 
     }
 
@@ -650,10 +648,11 @@ LineMaterial.prototype.constructor = LineMaterial;
 
 LineMaterial.prototype.isLineMaterial = true;
 LineMaterial.prototype.updateDepthParams = function(e={}){   
-    if(this.useDepth){
-        var camera = e.camera || viewer.scene.getActiveCamera()
-        this.uniforms.depthTexture.value = viewer.getPRenderer().rtEDL.depthTexture  
-        this.uniforms.nearPlane.value = camera.near;
+    if(this.useDepth){ 
+        var viewport = e.viewport || viewer.mainViewport;
+        var camera = viewport.camera;
+        this.uniforms.depthTexture.value = viewer.getPRenderer().getRtEDL(viewport).depthTexture  //viewer.getPRenderer().rtEDL.depthTexture  
+        this.uniforms.nearPlane.value = camera.near; //似乎因为这个所以对OrthographicCamera 无效
         this.uniforms.farPlane.value = camera.far; 
     }
 }

+ 0 - 299
note笔记笔记笔记.txt

@@ -1,299 +0,0 @@
-https://potree.org/potree/examples/page.html 
-http://localhost:1234/examples/page.html
-
- 
-
-应用navvis : 
-https://testlaser.4dkankan.com/maxkk/t-iksBApb/?image=1&vlon=4.91&vlat=-0.13&fov=100.0
-navvis官网?
-https://hq.iv.navvis.com/?site=1493761991057195&vlon=1.12&vlat=-0.52&fov=100.0&image=16902 
-我们这复制的?
-http://139.224.42.18:8080/siemens/?pc=true&vlon=2.59&vlat=-0.03&fov=100.0&lon=116.46694741&lat=39.98387332&z=1.807
-三味书屋可以编辑:
-http://indoor.popsmart.cn:8084/sxswsw-sx/?vlon=5.25&vlat=0.03&fov=100.0&pc=true&lon=120.58634810&lat=29.99135414&z=2.002
-
-用户名:admin
-密码:ipadmin
-
- 
-========
-
-
-测试服务器可以:
-t-CwfhfqJ 大佛 有平面图 
-t-e2Kb2iU 隧道 
-t-8KbK1JjubE  回家湘
-t-Y22JxCS7sP 小区 (无pano)
-t-8BCqxQAr93 小会议室
-t-AY03FoVZhm 一楼      (编辑完空间模型的)
-t-GusppsiKEC 字节跳动楼外场景
-t-YLZ5XAALl7 燃气管线街景
-SS-t-P6zBR73Gke 燃气站
-t-QaHxu5Nmn3 一楼门口
-t-5HxBflA 梁启超故居
-
-t-FhDWmV5xur 车库
-
-
-多数据集:
-SS-t-Gpnepyz1JI
-
-	--多楼层漫游点:
-
-
-
- 
-
-
-正式服务器:
-3o5II3n9Rs 地下车库
- 
-4dkk.html 场景:
-
-t-ia44BhY 机场(两个数据集。点量大 )
-t-iksBApb 一楼 一个数据集 十个点左右
-t-Zvd3w0m 室内 4dkk的场景 三个点 
-t-OW5ShsQ 一楼 有平面图 点五个
-
- 
- 
-
-
-============== 
-添加数据集登录4dkk
-18666146601
-Aa123456
-
-==========================================================================================
-
- 
-
-
-
----------
-优化:  |
----------
-加载深度图(因为一开始用的全景)( 用深度图来模拟全景漫游的mesh似乎行不通,因为是非线性的,但可以加载chunks,超低模,或者重写点云shader,改成mesh的,只加载到level3)
- 
-该场景有很多小房间,而boundingsky很大,导致过渡像瞬间渐变
-https://laser.4dkankan.com/index.html?m=SS-irJmUUy86l#/  
-
-
-
-当距离很远的过渡可以考虑瞬间过渡,否则会很奇怪
-
-热点和测量线可能需要再次矫正(尤其截图时尽量居中)
- 
- 
-测量线截图的抗锯齿
-
-
-初始加载全景的话容易崩溃。 要不要减少点云加载。或在unfocus页面时释放点云和贴图。
-注意是否暂停下载点云or贴图了(异步请求过多会崩溃) 
-
-是否可以监听到场景的变化,变化了才渲染。要监听所有材质变化、object改变。
-
-moveSpeed 、 地图的自适应缩放
-
-数据集校准最好能显示现在位移和旋转距离上次修改的总量
- 
-点击测量线后,或执行了setView后,如果再次移动镜头或再次setView,要取消之前的setView
-
-刚开始加载高质量点云可以在rendertarget内。或者有没有办法加载了不绘制
-
-地理位置修改了的话,没有绑定到数据集上的测量线怎么办? 要不还是默认放第一个数据集?
-
-
- 
-clip没写完。如果按照房间显示点云的话。
- 
- 
-
-
----------
-Bug	|
----------
-
-
-
-不是我的bug:
-
-有的点位贴图不准,回复说是计算问题。
-
-----------------
-截图时map为何闪一下
-为什么pano的label被marker遮住  透明问题无解?
- 
-隐藏数据集后再全景
-
-  
-
-空间模型 这里要显示的是自定义的平面图,但是如果没有自定义的,应该是不显示这个选项的
- 
-地图坐标矫正??
- 
- 
-
-
-
-测量在地图上的高度确定:
-  navvis很奇怪,在地面上很准,但是到了房屋上就只能在当前高度了。在房屋内是依靠空间模型判断属于哪个Floor楼层,得到层高。
-地图上画的datasetpoints为空   
-导航在地图上的高度怎么定
- 
- 
-  
-----
-
- 
- 
-  
- macbook触摸板的也没有检查。 还不知道navvis的表现如何
-
- 
-
- 
- 
-我的se打开是空白的!!连调试都不行。不过navvis也是空白
-
- 
-检查四倍放大的闪退。手机
-
-
-
-
- 
-前进时贴图好像是一个tile一个tile变的,尤其手机
-
-触屏放大后测量很卡。手机全景很卡
-
- 
-偶现手机里测量线没marker  
-
-
- 
- 
-手机打开全景图特别慢
-
-  
-在坐标页面加放大镜,场景的ray是最高密度吗
-========================
- 
-sitemodel 
-
-
-暂时不做的功能: 重置or解锁轮廓(没啥用)。  添加子实体
-	移除点、结束绘画、去掉最后一个点
-	吸附点、线、90度
-
-  
-
- 
-
---------------------
- 
-
- this.setProjectedPanos({  在点云模式禁止,切换全景转动后会变白
-
-
- this.on('updateNodeMaxLevel',(pointcloud,nodeMaxLevel)  多个数据集的话,万一node level比较高的在远方还没加载怎么办?
-
-
-消防 https://78h5qu.axshare.com/#id=k94ltt&p=%E6%B7%BB%E5%8A%A0%E8%A7%86%E9%A2%91&g=1
-
-
-
- 
-为什么分屏时clip的transfrom框在map区域也绘制了? 黑色线框是boxVolume里的,黄色线框居然不属于boxVolume
-如果数据集可以任意旋转,如何判断数据集和entity重叠体积?
-如何判断数据集是否和clipBox(任意旋转)相交
-1 使用node判断
- 
-
-  
-
- 
- 
-
-
-
-
-
-端点拖动时最好能切换成着附在点云上。或者在有点云时着附在点云上
-
- 
-
-http://localhost:8080/index.html?m=t-8KbK1JjubE&test#/space-division    
-点云t-8KbK1JjubE_U1 发现都是0,0,-1  在数据集校准显示不出来
-还有一次boudingbox显示错误。导致居中不了
-
-  
-
- 
-粒子的剪裁 和 lod
-  
- 
-检查 hole没有点时,离开的话,hole会被删除吗
- 
- 
-卡顿 
-
-给大场景的热点也写一个isInsideFrustum
-
- 
-  
-加载平面图:根据所在的楼层(如果多个楼层重叠,只算找到的第一个楼层),找出它所包含的全部数据集(重合体积占数据集体积10%以下的不算),加载这部分平面图。
-	或者随同漫游点,显示了的漫游点所在的数据集的平面图显示	
-
-	如果不在任何一个楼层,就不加载平面图?(navvis不加载)也可以加载最近层的平面图(如比最低层低就保留最低层,比最高层高就保留最高层,否则就是中间层的)
-
-	直接根据显示的漫游点的楼层吧
-
-
-test20220429-12:30
-test20220429-18:30
-
- 
-
-
-SS-t-Tbb9PpkNzd  三个数据集 但也不是很大吧 为什么这么卡?
-
-
-
-
-用boundingbox来判断数据集在哪个空间的话,对于参差不齐的数据集叠成的楼层,算不准。比如框柱的是数据集的上部,这个地方点云,明显很少,但算出的和下部的体积是一致的。
-用node会好些吗? 不过这种情况可能不多见。
-
-
-
-拖拽后取消选中marker
-
-
-updatclose 改为 raycaster  marker
- 
-
-  
-突然发现小地图一放大就自动切换到点云模式了!
- 
-
- 
-不支持depth的可以直接depthTest : true吗
- floor的box也改下
-
-
-
-
-room绘制、添加后删除 报错,等待修复
-
-感觉floor的depthMAterail没效果  
-
-
-floor
-
-
-
-
-
-
-
-if(viewport.alignment && handleState && viewport.alignment[handleState])  移动到alignment里吧 

+ 176 - 28
src/PointCloudOctree.js

@@ -151,7 +151,7 @@ export class PointCloudOctree extends PointCloudTree {
 		this.updateMatrix();
         this.nodeMaxLevel = 0;//add
         this.maxLevel = Infinity;
-        this.temp = {}//add
+        this.temp = { sizeFitToLevel:{}, opacity:{}}//add
         //add 
         this.rotateMatrix = new THREE.Matrix4;
         this.transformMatrix = new THREE.Matrix4;// 数据集的变化矩阵
@@ -159,6 +159,8 @@ export class PointCloudOctree extends PointCloudTree {
         this.rotateInvMatrix = new THREE.Matrix4; 
         this.material.spacing = this.pcoGeometry.spacing;//初始化一下 以便于设置pointsize
         
+        this.nodeMaxLevelPredict = this.predictNodeMaxLevel()//预测maxNodeLevel  
+        this.testMaxNodeCount = this.testMaxNodeCount2 = 0
 		{
 
 			let priorityQueue = ["rgba", "rgb", "intensity", "classification"];
@@ -228,14 +230,144 @@ export class PointCloudOctree extends PointCloudTree {
 	}
 
 
-    updateNodeMaxLevel(e){//目前点云包含node的最高level
+   
+    /* 
+    
+    注释:node的level从最大的box 0开始。
+    且加载任意一个node必定也会加载它的所有祖先。(如visibleNodes中有一个level为4,则一定有3,2,1,0) 
+    visibleNodes就是所有可见的node,比如:
+    如果相机在0这个位置朝下,这时候的visibleNodes中只有一个level为0的node;
+    而如果朝上看,上方的几个node如果在视野中占据足够大的位置的话,就会加载。
+    如果相机在2这个位置朝上,这时候的visibleNodes中所包含的level为: 0,1,2
+    
+    ________________
+    |   |   |       |
+    |__2|   |       |
+    |     1 |   1   |
+    |_______|_______|
+    |               |    
+    |               |    
+    |      0        |    
+    |_______________|
+    
+    查看box可在potree中开启
+     */
+     
+     
+     
+     
+     
+    updateNodeMaxLevel(e){//目前点云包含node的最高level  
         var level = Math.max(e.level, this.nodeMaxLevel)
         if(level != this.nodeMaxLevel){
             this.nodeMaxLevel = level 
-            viewer.dispatchEvent({type:'updateNodeMaxLevel', pointcloud: this, nodeMaxLevel:level}) 
+            //viewer.dispatchEvent({type:'updateNodeMaxLevel', pointcloud: this, nodeMaxLevel:level}) 
+             
+            console.log('updateNodeMaxLevel ' + this.dataset_id + " : "+ this.nodeMaxLevel)                
+              
+            this.setPointLevel()//重新计算
+             
+            if(!Potree.settings.sizeFitToLevel){
+                this.changePointSize() 
+            }   
         }
+    }//注:在没有加载到真实的 nodeMaxLevel之前,点云会显示得偏大
+     
+     
+     
+     
+     
+   testMaxNodeLevel(){//手动使maxLevel达到最高,从而迫使updateNodeMaxLevel。  因为Potree.settings.pointDensity 不为 'high'时,maxLevel不是所加载的最高,就很容易加载不出下一个层级,导致无法知道nodeMaxLevel
+        if(this.testMaxNodeLevelDone ) return
+        //if(this.nodeMaxLevel > this.nodeMaxLevelPredict.min  )return 
+        
+        
+        if( this.nodeMaxLevel==0 )return true
+        if( !viewer.atDatasets.includes(this))return true //否则老远就count++
+        
+        let levels = this.visibleNodes.map(e=>e.getLevel())
+        let actMaxLevel = Math.max.apply(null, levels) //实际加载到的最高的node level
+        if(actMaxLevel <  this.maxLevel)return true// 还没加载到能加载到的最高。  但在细节设置较低时,排除作用微弱。
+        
+         
+        //尝试加载出更高级的level 
+        let old = this.maxLevel
+        this.maxLevel = 12;
+        //var visibleNodes1 = this.visibleNodes.map(e=>e.getLevel())
+        //console.log('visibleNodes1',visibleNodes1)
+        Potree.updatePointClouds([this],  viewer.scene.getActiveCamera(), viewer.mainViewport.resolution );
+        var visibleNodes2 = this.visibleNodes.map(e=>e.getLevel())
+        //console.log('visibleNodes2',visibleNodes2) 
+        this.maxLevel = old;
+        
+        
+        
+        this.testMaxNodeCount ++
+        if(this.testMaxNodeCount > 500){
+            console.log('testMaxNodeLevel次数超出,强制结束:',this.dataset_id,  this.nodeMaxLevel,  this.nodeMaxLevelPredict.min) 
+            this.testMaxNodeLevelDone = 'moreThanMaxCount'
+            return; //在可以看见点云的情况下,超时,有可能是预测的max是错的    
+        }
+        if(this.nodeMaxLevel < this.nodeMaxLevelPredict.min) return  true //仍需要继续testMaxNodeLevel
+        
+        this.testMaxNodeCount2 ++; // 已经> this.nodeMaxLevelPredict.min 后,开始计数。因为min可能低于真实nodeMaxLevel所以要再试几次
+        
+        /* if(this.name == 'SS-t-CWmVgzP4XU'){
+            console.log('SS-t-CWmVgzP4XU count++')
+        } */
+        
+        if(this.testMaxNodeCount2 < 50)  return  true //再试几次 ( 主要是细节调得低时需要多测几次才加载到
+        this.testMaxNodeLevelDone = true
+        
+        
+           
+         
+        
+   }       
+     
+     
+     
+     
+     
+    
+    setPointLevel(){
+        
+        var pointDensity = Potree.settings.pointDensity
+        var config = Potree.config.pointDensity[pointDensity];
+        if(!config)return
+        
+        
+        /* if(this.testingMaxLevel){
+            this.maxLevel = 12;//先加载到最大的直到测试完毕。由于5个level为一组来加载,所以如果写4最高能加载到5,如果写5最高能加载到下一个级别的最高也就是10
+            //console.log('maxLevel: '+e.maxLevel +  ' testingMaxLevel中 '  )                                
+        }else{ */
+            let percent = config.percentByUser && Potree.settings.UserDensityPercent != void 0  ? Potree.settings.UserDensityPercent : config.maxLevelPercent  
+            this.maxLevel = Math.round( percent * this.nodeMaxLevel); 
+            //console.log('maxLevel: '+e.maxLevel +  ',   density : '+Potree.settings.pointDensity,  ",  percent :"+percent);
+            
+            if(Potree.settings.sizeFitToLevel){
+                this.changePointSize() 
+            } 
+            this.changePointOpacity()
+        //}   
     }
-
+    
+    //预测可能的nodeMaxLevel:
+    
+    predictNodeMaxLevel(){//预测maxNodeLevel。  可能只适用于我们相机拍的点云
+        let spacing = {min:0.005, max:0.014};//最小节的两点间的距离  ,获得方法:spacing / Math.pow(2, nodeMaxLevel)。 目前观测的我们自己拍的这个数值的范围大概是这样
+        let min = Math.log2(this.material.spacing / spacing.max); //有见过最大是0.01368 
+        let max = Math.log2(this.material.spacing / spacing.min); //大部分是 0.006
+        //console.log('predictNodeMaxLevel:', this.name ,  min, max ) 
+    
+    
+        return {min, max}
+    }
+    
+    getHighestNodeSpacing(){
+        return this.material.spacing / Math.pow(2, this.nodeMaxLevel) //前提是这个nodeMaxLevel是准确的
+    }
+    
 	setName (name) {
 		if (this.name !== name) {
 			this.name = name;
@@ -1799,17 +1931,26 @@ export class PointCloudOctree extends PointCloudTree {
             this.temp.pointSize = num
         }
         
+        
+        num = Math.pow(num, 1.05) * 6 
+         
+        
         if(sizeFitToLevel || Potree.settings.sizeFitToLevel){//按照点云质量来调整的版本:
-            let base = this.material.spacing / Math.pow(2, this.maxLevel) //点云大小在level为0时设置为spacing,每长一级,大小就除以2
-            base *= this.nodeMaxLevel > 0 ? Math.max(0.1, Math.pow(this.maxLevel / this.nodeMaxLevel, 1.3)) : 0.1 //低质量的缩小点,因为视觉上看太大了。navvis是不铺满的,我们也留一点缝隙
+            let str = this.temp.pointSize+':'+this.maxLevel+':'+this.nodeMaxLevel
+            let value = this.temp.sizeFitToLevel[str]  //储存。防止每次渲染(反复切换density)都要算。
+            if(value){
+                this.material.size = value
+            }else{
+                let base = this.material.spacing / Math.pow(2, this.maxLevel) //点云大小在level为0时设置为spacing,每长一级,大小就除以2
+                base *= this.nodeMaxLevel > 0 ? Math.max(0.1, Math.pow(this.maxLevel / this.nodeMaxLevel, 1.3)) : 0.1 //低质量的缩小点,因为视觉上看太大了。navvis是不铺满的,我们也留一点缝隙
 
-            this.material.size = base * 3 * num/*  * window.devicePixelRatio */
-            //在t-8BCqxQAr93 会议室 和 t-e2Kb2iU 隧道 两个场景里调节,因为它们的spacing相差较大,观察会议室墙壁的龟裂程度
-            
-            
+                this.material.size = base * 3 * num/*  * window.devicePixelRatio */
+                //在t-8BCqxQAr93 会议室 和 t-e2Kb2iU 隧道 两个场景里调节,因为它们的spacing相差较大,观察会议室墙壁的龟裂程度
+                this.temp.sizeFitToLevel[str] = this.material.size
+            }
         }else{
-            let base = this.material.spacing / Math.pow(2, this.nodeMaxLevel) //点云大小在level为0时设置为spacing,每长一级,大小就除以2
-            
+            //let base = this.material.spacing / Math.pow(2, this.nodeMaxLevel) //点云大小在level为0时设置为spacing,每长一级,大小就除以2
+            let base = 0.05; 
             this.material.size = base * 5 * num /* * window.devicePixelRatio  */
         }
         
@@ -1833,25 +1974,32 @@ export class PointCloudOctree extends PointCloudTree {
         if (num == 1) {
             this.material.opacity = 1
         } else {
-            if(Potree.settings.sizeFitToLevel){//按照点云质量来调整的版本:
-                let base = this.material.spacing / Math.pow(1.4, this.maxLevel) //随着level提高,点云重叠几率增多
-                let minBase = this.material.spacing / Math.pow(1.4, this.nodeMaxLevel)
-                let ratio = Math.min(1 / base, 1 / minBase / 3) //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
-                this.material.opacity = base * ratio * num
-                if(!canMoreThanOne){
-                    this.material.opacity = THREE.Math.clamp(this.material.opacity, 0, 0.999) //到1就不透明了(可能出现一段一样)
-                }
-            
+            let str = (Potree.settings.sizeFitToLevel?'sizeFit:':'')+ (canMoreThanOne ? 'canMoreThanOne:':'') +this.temp.pointOpacity+':'+this.maxLevel+':'+this.nodeMaxLevel
+            let value = this.temp.opacity[str]  //储存。防止每次渲染(反复切换density)都要算。
+            if(value){
+                this.material.opacity = value
             }else{
-                let base = this.material.spacing / Math.pow(1.8, this.maxLevel) 
-                let minBase = this.material.spacing / Math.pow(1.8, this.nodeMaxLevel)
-                //console.log(1 / base, 1 / minBase / 6)
-                let ratio = Math.min(1 / base, 1 / minBase / 6) //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
-                this.material.opacity = base * ratio * num
-                if(!canMoreThanOne){
-                    this.material.opacity = THREE.Math.clamp(this.material.opacity, 0, 0.999) //到1就不透明了(可能出现一段一样)
+                if(Potree.settings.sizeFitToLevel){//按照点云质量来调整的版本:
+                    let base = this.material.spacing / Math.pow(1.4, this.maxLevel) //随着level提高,点云重叠几率增多
+                    let minBase = this.material.spacing / Math.pow(1.4, this.nodeMaxLevel)
+                    let ratio = Math.min(1 / base, 1 / minBase / 3) //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
+                    this.material.opacity = base * ratio * num
+                    if(!canMoreThanOne){
+                        this.material.opacity = THREE.Math.clamp(this.material.opacity, 0, 0.999) //到1就不透明了(可能出现一段一样)
+                    }
+                }else{
+                    let base = this.material.spacing / Math.pow(1.8, this.maxLevel) 
+                    let minBase = this.material.spacing / Math.pow(1.8, this.nodeMaxLevel)
+                    //console.log(1 / base, 1 / minBase / 6)
+                    let ratio = Math.min(1 / base, 1 / minBase / 6) //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
+                    this.material.opacity = base * ratio * num
+                    if(!canMoreThanOne){
+                        this.material.opacity = THREE.Math.clamp(this.material.opacity, 0, 0.999) //到1就不透明了(可能出现一段一样)
+                    }
                 }
+                this.temp.opacity[str] = this.material.opacity
             }
+                
             //缺点:防止颜色过亮主要是相机离远时,当在漫游点处由于离点云太近,可能会导致高质量点云看起来很暗。
         }
         //console.log('changePointOpacity ' + this.dataset_id + ', num : ' + num + ' , opacity : ' + this.material.opacity) //检查是否做到了低质量时num==opacity,中质量opacity稍小于num,高质量更小

+ 7 - 6
src/Potree.js

@@ -190,14 +190,15 @@ export async function loadMapEntity(datasetId, force){
         if(floorplanType != Potree.settings.floorplanType[dataset_id]) return //如果请求的floorplanType不是当前最新的floorplanType就返回
         
         var map = viewer.mapViewer.mapLayer.maps.find(e => e.name == 'floorplan_'+ dataset_id)
-        if(map){
+        if(map){  
             viewer.mapViewer.mapLayer.removeMap(map)
-        }else{
-            
-        }
-        
-        var map = viewer.mapViewer.mapLayer.addMapEntity(data.data || data,  dataset_id)
+        } 
         
+        var mapNew = viewer.mapViewer.mapLayer.addMapEntity(data.data || data,  dataset_id)
+        if(map){
+            mapNew.visibleReasons = map.visibleReasons 
+            mapNew.unvisibleReasons = map.unvisibleReasons 
+        }
         loaded ++; 
     } 
     

+ 12 - 11
src/materials/DepthBasicMaterial.js

@@ -56,27 +56,27 @@ export default class DepthBasicMaterial extends THREE.ShaderMaterial{
              
         setSize( {viewport} )
         
-        viewer.addEventListener('resize',(e)=>{
-            if(!e.viewport || e.viewport.name != 'mapViewport'){//地图不需要
+        viewer.addEventListener('resize',(e)=>{ 
+            if(!e.viewport || e.viewport.camera.isPerspectiveCamera){//地图不需要
                 setSize(e)
                 //console.log(this.name +  viewportOffset.toArray())     
             } 
         })  
-    
+      
         
         if(this.useDepth){  
             
-            viewer.addEventListener('camera_changed', (e)=>{
+            /* viewer.addEventListener('camera_changed', (e)=>{
                 if(e.viewport.name != 'mapViewport') this.updateDepthParams(e) 
-            }) 
+            }) */ 
          
-            /* viewer.addEventListener("render.begin", (e)=>{//before render  如果有大于两个viewport的话可能要
-                if(e.viewport.name != 'mapViewport') this.updateDepthParams({camera:e.viewport.camera})
-            }) */
+            viewer.addEventListener("render.begin", (e)=>{//before render  如果有大于两个viewport的话,不同viewport用不同的depthTex
+                if(e.viewport.camera.isPerspectiveCamera) this.updateDepthParams(e)
+            })
             
             this.updateDepthParams()
         }
-        
+         
         
         //点云变化时要一直触发updateDepthParams??
         //viewer.once("render.pass.end",this.updateDepthParams.bind(this))
@@ -84,8 +84,9 @@ export default class DepthBasicMaterial extends THREE.ShaderMaterial{
     
     updateDepthParams(e={}){//主要用于点云遮住mesh
         if(this.useDepth){ 
-            var camera = e.camera || viewer.scene.getActiveCamera(); 
-            this.uniforms.depthTexture.value = viewer.getPRenderer().rtEDL.depthTexture   //其实只赋值一次就行
+            var viewport = e.viewport || viewer.mainViewport;
+            var camera = viewport.camera;
+            this.uniforms.depthTexture.value = viewer.getPRenderer().getRtEDL(viewport).depthTexture   //其实只赋值一次就行
             this.uniforms.nearPlane.value = camera.near;
             this.uniforms.farPlane.value = camera.far;
             

+ 1 - 1
src/materials/shaders/depthBasic.fs

@@ -49,7 +49,7 @@ void main() {
         float fragDepth = convertToLinear(gl_FragCoord.z);
 
         // The coordinates of the current fragment in the depth texture
-        vec2 depthTxtCoords = vec2(gl_FragCoord.x-viewportOffset.x,  gl_FragCoord.y) / resolution;
+        vec2 depthTxtCoords = vec2(gl_FragCoord.x-viewportOffset.x,  gl_FragCoord.y - viewportOffset.y) / resolution;
      
         // The linear depth value of the pixel occupied by this fragment in the depth buffer
         float textureDepth = convertToLinear(texture2D(depthTexture, depthTxtCoords).r);

+ 51 - 23
src/modules/Images360/Images360.js

@@ -130,12 +130,13 @@ export class Images360 extends THREE.EventDispatcher{
         
 
         let click = (e) => {//不用"mouseup" 是因为 mouseup有drag object时也会触发
+            if(Potree.settings.unableNavigate || this.flying  || !e.isTouch && e.button != THREE.MOUSE.LEFT || e.drag &&  e.drag.object)return //拖拽结束时不算
+            
             if( e.hoverViewport == viewer.mapViewer.viewports[0]){
                 return viewer.mapViewer.dispatchEvent(e/* {type:'global_click',e } */) 
             }
             
              
-            if(Potree.settings.unableNavigate || this.flying  || !e.isTouch && e.button != THREE.MOUSE.LEFT || e.drag &&  e.drag.object)return //拖拽结束时不算
              
             /* if(currentlyHovered && currentlyHovered.pano){
 				this.focusPano(currentlyHovered.pano);
@@ -153,6 +154,12 @@ export class Images360 extends THREE.EventDispatcher{
                 this.updateClosestPano(e.intersectPoint)
             }
 		});
+        
+        
+        this.addEventListener('markerHover',(e)=>{
+            this.updateClosestPano(e.pano, e.hovered)
+        })
+        
 
 
         if(!Potree.settings.isOfficial){
@@ -360,6 +367,10 @@ export class Images360 extends THREE.EventDispatcher{
                             this.elDisplayModel.value = mode == 'showPointCloud' ? ">>全景" : '>>点云'
                         }
                          
+                        this.panos.forEach(e=>{
+                            viewer.updateVisible(e, 'modeIsShowPanos', mode == 'showPanos', 1,  mode == 'showPanos' ? 'add':'cancel') // 
+                        })
+                         
                          
                         this.dispatchEvent({type:'endChangeMode',mode})  
                         console.log('setModeSuccess: ' + mode)       
@@ -468,6 +479,7 @@ export class Images360 extends THREE.EventDispatcher{
 
     set flying(v){//正在飞向pano
         this.flying_ = !!v
+        //console.log('this.flying_ ', !!v )
         //this.emit('flying', this.flying_)
         let config = Potree.config.displayMode[Potree.settings.displayMode]
         viewer.mainViewport.unableChangePos = !config.canLeavePano || !!v  
@@ -569,9 +581,9 @@ export class Images360 extends THREE.EventDispatcher{
         if(!this.currentPano){
             return this.focusPano(toPano) 
         }
-        
+        //console.log('flyToPano:', toPano.pano.id)
         let done = (makeIt)=>{
-            //console.log('done '+ !!toPano.deferred)
+            //console.log('flyToPano done ', toPano.pano.id, makeIt )
             toPano.deferred && toPano.deferred.resolve(makeIt)
             if(makeIt) {
                 toPano.callback && toPano.callback()
@@ -593,9 +605,10 @@ export class Images360 extends THREE.EventDispatcher{
         var pointcloudVisi = config.atPano.showPoint  //viewer.scene.pointclouds[0].visible
         
         
-        var pano = toPano.pano 
-        let maxTime = this.isAtPano() ? Potree.config.transitionsTime.panoToPanoMax : Potree.config.transitionsTime.flyIn 
-        var duration = toPano.duration == void 0 ? (100+Math.min(Potree.config.transitionsTime.flyTime * this.position.distanceTo(pano.position),   maxTime)) : toPano.duration 
+        var pano = toPano.pano
+        let T = Potree.config.transitionsTime
+        let maxTime = this.isAtPano() ? T.panoToPanoMax : T.flyIn 
+        var duration = toPano.duration == void 0 ? (T.flyMinTime+Math.min(T.flytimeDistanceMultiplier * this.position.distanceTo(pano.position), maxTime)) : toPano.duration 
         toPano.duration = duration
         //console.warn("flyto "+pano.id + ' duration: ' + duration )     
         
@@ -603,7 +616,7 @@ export class Images360 extends THREE.EventDispatcher{
         //不飞的话是否不要执行这段?
         if(config.atPano.showSkybox || config.atPano.pointUsePanoTex){
             if(this.checkAndWaitForPanoLoad(pano, toPano.basePanoSize || this.basePanoSize, ()=> {
-                //console.log('setTimeout 1 flyToPano')
+                    //console.log('setTimeout 1 flyToPano')
                     setTimeout( ()=>{
                         this.flyToPano(toPano)
                     },1)
@@ -982,12 +995,16 @@ export class Images360 extends THREE.EventDispatcher{
         if(!Potree.settings.ifShowMarker){//不显示marker的时候mousemove没更新鼠标最近点所以更新
             this.updateClosestPano(viewer.inputHandler.intersectPoint)
         }
-        
+        //console.log('flyToPanoClosestToMouse',this.closestPano)
         
         if (this.closestPano) {
+            let pano = this.closestPano 
             return this.flyToPano({
-                pano: this.closestPano
+                pano, callback:()=>{
+                    this.updateClosestPano(this.closestPano,false) 
+                } 
             });
+            
         } 
         var direction = this.viewer.inputHandler.getMouseDirection().direction;
         this.flyDirection(direction)
@@ -1038,34 +1055,45 @@ export class Images360 extends THREE.EventDispatcher{
 		
     }
 
-    updateClosestPano(intersect) {//距离reticule最近的点  可以是null
-        if(this.flying)return; 
-        intersect = intersect && intersect.location
-        if(!intersect)return
+    updateClosestPano(intersect, state) {//距离reticule最近的点  可以是null
+        
          
-        var filterFuncs = [];
      
-        if(this.isAtPano() ){ 
-            filterFuncs.push(Images360.filters.not(this.currentPano));
+        /* if(this.isAtPano() ){ 
+             filterFuncs.push(Images360.filters.not(this.currentPano));
             
             //当静止在漫游点时closestPano只限制在每个漫游点附近,而在观看整个模型时,范围夸大,识别为离鼠标最近的漫游点。 (故而要排除flying时)
  			filterFuncs.push(Images360.filters.inFloorDirection(this.position, viewer.scene.view.direction, .25))//许钟文改
             filterFuncs.push(Images360.filters.isCloseEnoughTo(intersect, 0.35));
-            filterFuncs.push(Images360.filters.isEnabled())
+            filterFuncs.push(Images360.filters.isEnabled())  
         }else{
 			 
+        } */
+        var pano
+        if(this.isAtPano() ){
+            if(intersect instanceof Panorama){
+                pano = state ? intersect : null
+            }else{
+                return 
+            }
+        }else{
+            if(this.flying)return; 
+            var filterFuncs = [];
+            intersect = intersect && intersect.location
+            if(!intersect)return
+            pano = Common.find(this.panos,  filterFuncs, [Images360.sortFunctions.floorDistanceToPoint(intersect)]);
         }
         
         
-        var pano = Common.find(this.panos,  filterFuncs, [Images360.sortFunctions.floorDistanceToPoint(intersect)]);
+        
+        
         if (pano != this.closestPano) {
             pano && (this.isPanoHover = !0);
-            
-            
+             
             this.closestPanoChanging(this.closestPano, pano) // 高亮marker
             //console.log('closestPano '+ (pano ? pano.id : 'null' )) 
             this.closestPano = pano;
-        } else {
+        } else { 
             this.isPanoHover = !1;
         }
     }
@@ -1075,8 +1103,8 @@ export class Images360 extends THREE.EventDispatcher{
     closestPanoChanging(oldPano, newPano){
         if(!Potree.settings.ifShowMarker)return
         
-        oldPano && oldPano.hoverOff()
-        newPano && newPano.hoverOn()
+        oldPano && oldPano.hoverOff({byImages360:true})
+        newPano && newPano.hoverOn({byImages360:true})
         
         
     }

+ 34 - 1
src/modules/Images360/Panorama.js

@@ -87,8 +87,19 @@ class Panorama extends THREE.EventDispatcher{
                 this.label && (this.label.visible = e.visible)//截图时隐藏下
             }
         })
+        /* 
+        漫游点可见性:
+            level       reason                           类型
+            2(最高)buildingChange(不在此楼层)        unvisible   
+            1       modeIsShowPanos(漫游模式)          visible 
+            0       pointcloudVisi(隐藏了数据集)       unvisible
         
-        
+         */
+         
+         
+         
+         
+         
         //全景图和Cube的水平采样起始坐标相差90度 
         
 
@@ -216,6 +227,26 @@ class Panorama extends THREE.EventDispatcher{
         this.images360.node.add(marker)
         Potree.settings.isTest && this.createTextLabel()
         
+        
+        /* let mouseover = (e)=>{ 
+            if(!e.byMap){
+                pano.mapMarker.material = panoMarkerMats.selected
+                if(!e.byMainView) pano.dispatchEvent({type: "hoverOn", byMap:true})
+                this.needRender = true    
+            }
+        }
+        
+        let mouseleave = (e)=>{
+            if(!e.byMap){
+                pano.mapMarker.material = panoMarkerMats.default
+                if(!e.byMainView) pano.dispatchEvent({type: "hoverOff", byMap:true})
+                this.needRender = true
+            }
+        } */
+         
+        
+        marker.addEventListener('mouseover', this.hoverOn.bind(this));  
+        marker.addEventListener('mouseleave', this.hoverOff.bind(this)); 
     }
     
     
@@ -256,6 +287,7 @@ class Panorama extends THREE.EventDispatcher{
         //console.log("hoverOn  " + this.id  )
         transitions.start(lerp.property(this.marker.material, "opacity", 1), 250)  
 		if(!e.byMap) this.dispatchEvent({type:'hoverOn', byMainView:true})
+        if(!e.byImages360) this.images360.dispatchEvent({type:'markerHover', hovered:true, pano:this})
     }
 
  
@@ -265,6 +297,7 @@ class Panorama extends THREE.EventDispatcher{
         //console.log("hoverOff  " + this.id  )
         transitions.start(lerp.property(this.marker.material, "opacity", 0.5), 250) 
         if(!e.byMap) this.dispatchEvent({type:'hoverOff',  byMainView:true})
+        if(!e.byImages360) this.images360.dispatchEvent({type:'markerHover', hovered:false, pano:this})
     }
     
     

+ 65 - 22
src/modules/clipModel/Clip.js

@@ -15,12 +15,12 @@ var Clip = {
     changeCallback(force){ 
         if(Potree.settings.isOfficial){  
             Common.intervalTool.isWaiting('clipSelectedDatasets', ()=>{ //延时update,防止卡顿
-                let pointclouds = this.getIntersectPointcloud()
-                let selectedDatasets = pointclouds.map(e=>e.dataset_id) 
-                if(force || Common.getDifferenceSet(selectedDatasets,this.selectedDatasets).length){  
-                    this.selectedDatasets = selectedDatasets 
+                let pointclouds = this.getIntersectPointcloud() 
+                if(force || Common.getDifferenceSet(pointclouds,this.selectedDatasets).length){  
+                    this.selectedDatasets = pointclouds 
                     //console.error('clipSelectedDatasets',selectedDatasets)
-                    this.bus.dispatchEvent({type:'updateSelectedDatasets', selectedDatasets})
+                    this.bus.dispatchEvent({type:'updateSelectedDatasets', selectedDatasets:pointclouds.map(e=>e.dataset_id) })
+                    force = false
                     return true 
                 } 
             },  300)  
@@ -43,7 +43,7 @@ var Clip = {
         let target = this.getTarget(bound.getCenter(new THREE.Vector3())); //navvis的位置xy是用相机位置 this.ViewService.mainView.getCamera().position  我觉得也可以用第一个漫游点的,或者最接近bound中心的漫游点
         let scale = new THREE.Vector3(defaultBoxWidth,defaultBoxWidth, boundSize.z)//z和navvis一样
         
-        let eyeDir = viewer.scene.view.direction.clone().setZ(-boundSize.z/3).multiplyScalar(-defaultBoxWidth) 
+        let eyeDir = viewer.scene.view.direction.clone().setZ(0/* -boundSize.z/3 */).multiplyScalar(-defaultBoxWidth)  //为了使所在楼层不变,不修改z
 
         //let eyeDir = scale.clone().setZ(boundSize.z/3).multiplyScalar(1.3) 
         let position = new THREE.Vector3().addVectors(target, eyeDir)
@@ -132,7 +132,7 @@ var Clip = {
         Potree.settings.unableNavigate = true
         Potree.settings.ifShowMarker = false
         viewer.updateVisible(viewer.measuringTool.scene, 'clipModel', false)   
-        viewer.updateVisible(viewer.mapViewer.cursor, 'clipModel', false)//隐藏地图游标
+        //viewer.updateVisible(viewer.mapViewer.cursor, 'clipModel', false)//隐藏地图游标
         viewer.inputHandler.toggleSelection(this.box);
         viewer.inputHandler.fixSelection = true
         viewer.transformationTool.frame.material.color.set(Potree.config.clip.color)//navvis 15899953 
@@ -140,16 +140,27 @@ var Clip = {
         
         {
             this.events = {
-                flyToDataset : ()=>{
+                flyToPos : (e)=>{ 
+                    let dis = 2
+                    let target = e.position
+                    //position = new THREE.Vector3().subVectors(target, this.scene.view.direction)
                     
-                },
-                focusEntity : ()=>{
+                    //永远朝向框的中心
+                    /* let dir = new THREE.Vector3().subVectors(this.box.position, e.position).normalize()
+                    position = new THREE.Vector3().subVectors(target, dir) */
                     
-                },
+                  
+                    target = this.box.position
+                    position = e.position
+                    //为了方便缩放操作,直接使用box中心作为target
+                    
+                    
+                    let duration = 1000
+                    viewer.scene.view.setView({position,  duration,  target})
+                } 
             }
             
-            this.bus.addEventListener('flyToDataset',this.events.flyToDataset)
-            this.bus.addEventListener('focusEntity',this.events.focusEntity)
+            this.bus.addEventListener('flyToPos',this.events.flyToPos) 
         }
         this.editing = true
         
@@ -166,15 +177,14 @@ var Clip = {
         Potree.settings.unableNavigate = false
         Potree.settings.ifShowMarker = this.previousView.ifShowMarker
         viewer.updateVisible(viewer.measuringTool.scene, 'clipModel', true)  
-        viewer.updateVisible(viewer.mapViewer.cursor, 'clipModel', true) 
+        //viewer.updateVisible(viewer.mapViewer.cursor, 'clipModel', true) 
         viewer.setView(this.previousView)
         viewer.setLimitFar(true)
         viewer.setPointStandardMat(false) 
         
         
         {
-            this.bus.removeEventListener('flyToDataset',this.events.flyToDataset)
-            this.bus.removeEventListener('focusEntity',this.events.focusEntity)
+            this.bus.removeEventListener('flyToPos',this.events.flyToPos) 
             this.events = null 
         }
         this.editing = false
@@ -216,24 +226,50 @@ var Clip = {
         
     }, */
     
-    download:function(){
+    download:function(notCrop){
         var visiPointclouds = viewer.scene.pointclouds.filter(e=> viewer.getObjVisiByReason(e, 'datasetSelection'))
         let data = {   
             transformation_matrix: visiPointclouds.map((cloud)=>{
-                return {
-                    id: cloud.dataset_id,
-                    matrix: this.getTransformationMatrix(cloud).elements,
+                let data = {
+                    id: cloud.dataset_id, 
+                    matrix : this.getTransformationMatrix(cloud).elements, 
                     modelMatrix:(new THREE.Matrix4).copy(cloud.transformMatrix).transpose().elements
-                } 
+                }  
+                return data
             }) ,
             aabb: "b-0.5 -0.5 -0.5 0.5 0.5 0.5" //剪裁空间( 所有点在乘上这个矩阵后, 还能落在 1 * 1 * 1的box内的点就是所裁剪的
            
         }
-        console.log(data)
+        
         return data
         //https://testlaser.4dkankan.com/indoor/t-ia44BhY/api/pointcloud/crop
     },
     
+    
+    
+    downloadNoCrop(){//不剪裁  下载整个点云
+        
+        var visiPointclouds = viewer.scene.pointclouds.filter(e=> viewer.getObjVisiByReason(e, 'datasetSelection'))
+        let data = {   
+            transformation_matrix: visiPointclouds.map((cloud)=>{
+                let data = {
+                    id: cloud.dataset_id, 
+                    matrix : new THREE.Matrix4().elements, //固定值
+                    modelMatrix:(new THREE.Matrix4).copy(cloud.transformMatrix).transpose().elements
+                }  
+                return data
+            }) ,
+            aabb: "b-12742000 -12742000 -12742000 12742000 12742000 12742000" //固定剪裁空间 
+           
+        }
+        console.log(data)
+        return data
+         
+        
+        
+    },
+    
+    
     getTransformationMatrix:function(pointcloud) {//剪裁矩阵
         var invMatrix = new THREE.Matrix4().getInverse(this.box.matrixWorld) 
         return (new THREE.Matrix4).multiplyMatrices(invMatrix, pointcloud.transformMatrix).transpose()
@@ -286,6 +322,13 @@ var Clip = {
        
 
     }
+    
+    
+   
+    /* 
+    裁剪点云时,2D界面显示全部平面图,按楼层切换显示。 
+     */
+    
 }
 
 

+ 53 - 1
src/modules/datasetAlignment/Alignment.js

@@ -43,6 +43,55 @@ var Alignment = {
         viewer.fpControls.addEventListener("end",(e)=>{ 
             rotateInfo = null
         })
+        
+        
+        
+        // cursor:
+        
+        let updateCursor = (e)=>{ 
+            if(e.drag)return  //仅在鼠标不按下时更新:
+            
+            let handleState = Alignment.handleState
+            if(e.hoverViewport.alignment && handleState && e.hoverViewport.alignment[handleState]){
+                if(handleState == 'translate'){
+                    if( e.intersectPoint && e.intersectPoint.location ){ 
+                        viewer.dispatchEvent({
+                            type : "CursorChange", action : "add",  name:"movePointcloud"
+                        })
+                    }else{
+                        viewer.dispatchEvent({
+                            type : "CursorChange", action : "remove",  name:"movePointcloud"
+                        })
+                    }
+                }else if(handleState == 'rotate'){ 
+                    if( e.intersectPoint && e.intersectPoint.location ){ 
+                        viewer.dispatchEvent({
+                            type : "CursorChange", action : "add",  name:"rotatePointcloud"
+                        })
+                    }else{
+                        viewer.dispatchEvent({
+                            type : "CursorChange", action : "remove",  name:"rotatePointcloud"
+                        })
+                    }
+                }  
+            }else{
+                //清空:
+                viewer.dispatchEvent({
+                    type : "CursorChange", action : "remove",  name:"movePointcloud" 
+                })
+                viewer.dispatchEvent({
+                    type : "CursorChange", action : "remove",  name:"rotatePointcloud" 
+                })
+            }                
+        }
+        viewer.addEventListener('global_mousemove',updateCursor)  
+        viewer.addEventListener('global_drop',updateCursor)//拖拽结束  
+            
+        
+        
+        
+        
+        
     },
     
     
@@ -121,6 +170,9 @@ var Alignment = {
         
         
         this.editing = true
+        
+        viewer.updateFpVisiDatasets()
+        
     },
     leave:function(){
         this.switchHandle(null)
@@ -139,7 +191,7 @@ var Alignment = {
         }) 
         this.editing = false
         
-         
+        viewer.updateFpVisiDatasets()
         
     } 
     

+ 10 - 5
src/modules/siteModel/BuildingBox.js

@@ -74,7 +74,7 @@ let getFaceMat = (name)=>{
 				polygonOffsetUnits : -4.0,//多边形偏移单位  */
                 
                 clipDistance : 1, occlusionDistance:1, /* occlusionDistance:变为backColor距离, clipDistance:opacity到达0或者1-maxClipFactor时的距离 */  
-                maxClipFactor:0.6, backColor:"#669988"  ,
+                maxClipFactor:0.4, backColor:'#efe' //backColor:"#669988"  ,
                   
             }),
             
@@ -84,7 +84,7 @@ let getFaceMat = (name)=>{
                 opacity:0.08,
                 transparent:true, 
                 depthTest:false, 
-            }),
+            }), 
             /* roomSelect: new THREE.MeshStandardMaterial({
                 color:"#ff44ee",  metalness: 0.3, roughness:1,
                 side:THREE.DoubleSide,//BackSide,
@@ -108,7 +108,7 @@ let getFaceMat = (name)=>{
 				polygonOffsetUnits : -4.0,//多边形偏移单位  */
                 
                 clipDistance : 1, occlusionDistance:0.5, /* occlusionDistance:变为backColor距离, clipDistance:opacity到达0或者1-maxClipFactor时的距离 */  
-                maxClipFactor:0.85, backColor:"#cc99c2"  ,
+                maxClipFactor:0.6, backColor:'#ff88dd'//"#cc99c2"  ,
                  
             })
         }
@@ -488,7 +488,7 @@ export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, fl
     updateBox(){
         if(!this.box)return
         this.box.geometry.dispose()
-        var shrink = this.buildType == 'floor' ? 0.0032 : 0.0073;//防止mesh重叠冲突(给一个不寻常的数字
+        var shrink = this.buildType == 'room' ? 0.11 : this.buildType == 'floor' ?  0.082 :  0.2   ;//防止mesh重叠冲突(给一个不寻常的数字)  但离远了还是会有点闪烁
         if(this.points.length >= 3){ 
             let holes = this.holes.concat(this.parentHoles)
             let holesPoints = holes.filter(e=>e.points.length>2).map(e=>e.points)
@@ -496,7 +496,12 @@ export class BuildingBox extends ctrlPolygon{//建筑实体,包括building, fl
                 depth:this.zMax-this.zMin-shrink,
                 UVGenerator: new MetricUVGenerator()
             }) 
-            this.box.position.z = this.zMin + shrink / 2  
+            if(this.buildType == 'building' ){
+                this.box.position.z = this.zMin - shrink / 2  
+            }else{
+                this.box.position.z = this.zMin + shrink / 2 
+            }
+             
         }
     }
     

+ 68 - 55
src/modules/siteModel/SiteModel.js

@@ -20,7 +20,7 @@ var SiteModel = {
     meshGroup: new THREE.Object3D,
     inEntity : null,
     lastPos: new THREE.Vector3(Infinity,Infinity,Infinity),
-    
+    updateCadByEntity:true,
     
     init: function(){
         
@@ -102,13 +102,22 @@ var SiteModel = {
                 
                 let searchPos = Potree.settings.displayMode == 'showPanos' ? viewer.images360.currentPano : currPos
                 entity = this.pointInWhichEntity(searchPos, 'room');
- 
+                
                 if(force || this.inEntity != entity ){
+                    let oldEntity = this.inEntity
+                    this.inEntity = entity 
                     console.log('buildingChange', entity) 
-                    this.bus.dispatchEvent({type:'buildingChange',entity})
-                     
-                    this.updatePanosVisible(this.inEntity, entity)
-                    this.inEntity = entity
+                    this.bus.dispatchEvent({type:'buildingChange',entity}) 
+                    //this.updatePanosVisible(oldEntity, this.inEntity) 
+                      
+                    let lastFloor = this.currentFloor   //oldEntity ? oldEntity.buildType == 'floor' ? oldEntity : oldEntity.buildType == 'room' ? oldEntity.buildParent : null : null; //基本只会是floor或room
+                    let currentFloor = entity ? entity.buildType == 'floor' ? entity : entity.buildType == 'room' ? entity.buildParent : null : null; //基本只会是floor或room
+                    if(currentFloor != lastFloor || force){
+                        //console.log('改变了floor',lastFloor,currentFloor)
+                        this.currentFloor = currentFloor
+                        this.bus.dispatchEvent({type:'FloorChange',currentFloor}) 
+                    }
+                    
                 }
                 force = false
                 return true 
@@ -121,23 +130,28 @@ var SiteModel = {
 
 
     updateCadVisibles(floor){
-        var visiClouds = this.floorplansVisi = floor ? findDatasetsAtFloor(floor) : []
+        if(!this.updateCadByEntity)return
+        /* var visiClouds = this.floorplansVisi = floor ? findDatasetsAtFloor(floor) : []
          
-        viewer.scene.pointclouds.forEach(e=>{ 
-            var floorplan = viewer.mapViewer.mapLayer.getFloorplan(e.dataset_id)
-            var visi = visiClouds.includes(e) 
+        viewer.scene.pointclouds.forEach(pointcloud=>{ 
+            var floorplan = viewer.mapViewer.mapLayer.getFloorplan(pointcloud.dataset_id)
+            var visi = visiClouds.includes(pointcloud) 
             if(floorplan){
                 viewer.updateVisible(floorplan.objectGroup, 'buildingChange', visi) 
             }else if(!visi){
                 let changeVisi = (e)=>{
-                    viewer.updateVisible(floorplan.objectGroup, 'buildingChange', this.floorplansVisi.includes(e)) 
+                    viewer.updateVisible(e.floorplan.objectGroup, 'buildingChange', this.floorplansVisi.includes(pointcloud)) 
                     viewer.mapViewer.mapLayer.removeEventListener('floorplanLoaded',  changeVisi)
                     console.log('updateCadVisibles加载后更改显示',e)
                 } 
                 viewer.mapViewer.mapLayer.addEventListener('floorplanLoaded',  changeVisi)
             }         
         })
-        viewer.mapViewer.mapLayer.needUpdate = true  
+        viewer.mapViewer.mapLayer.needUpdate = true   */
+        
+        
+        var visiClouds = this.floorplansVisi = floor ? findDatasetsAtFloor(floor) : []
+        viewer.updateCadVisibles(visiClouds)
         
         function findDatasetsAtFloor(entity){//找当前楼层需要显示哪些数据集。
             //必要条件: 如果数据集有漫游点的话,需要包含>20%的漫游点。   (防止重叠体积很大但其实一个漫游点都不包含)
@@ -170,16 +184,12 @@ var SiteModel = {
 
 
 
-    updatePanosVisible(lastEntity, entity, force){//根据所在楼层更新marker可见性。当在楼层中时,只显示当前楼层的marker。
+    /* updatePanosVisible(lastEntity, entity, force){//根据所在楼层更新marker可见性。当在楼层中时,只显示当前楼层的marker。
         if(!entity ){//暂定:不在任何一个实体中时 显示全部漫游点(和平面图显示不同,平面图就一个都不显示) 
             viewer.images360.panos.forEach(pano=>{
-                viewer.updateVisible(pano, 'buildingChange', true)  
+                viewer.updateVisible(pano, 'buildingChange', true, 2)  
             })
-            /* //只显示当前数据集的  //但是需要改变位置就计算,太麻烦
-            var atPointcloud = viewer.pointInWhichPointcloud(viewer.images360.position)
-            atPointcloud && atPointcloud.panos.forEach(pano=>{
-                viewer.updateVisible(pano, 'buildingChange', true)  
-            }) */ 
+             
             this.updateCadVisibles(null)
         }else{
             let lastFloor = lastEntity ? lastEntity.buildType == 'floor' ? lastEntity : lastEntity.buildType == 'room' ? lastEntity.buildParent : null : null; //基本只会是floor或room
@@ -188,33 +198,26 @@ var SiteModel = {
                 //console.log('改变了floor',lastFloor,currentFloor)
                 if(lastFloor){
                     lastFloor.panos.forEach(pano=>{
-                        viewer.updateVisible(pano, 'buildingChange', false)  
+                        viewer.updateVisible(pano, 'buildingChange', false, 2)  
                     })
                      
                     
                 }else{//重置为全部不可见
                     viewer.images360.panos.forEach(pano=>{
-                        viewer.updateVisible(pano, 'buildingChange', false)  
+                        viewer.updateVisible(pano, 'buildingChange', false, 2)  
                     })
                 }
                 if(currentFloor){
                     currentFloor.panos.forEach(pano=>{
-                        viewer.updateVisible(pano, 'buildingChange', true)  
+                        viewer.updateVisible(pano, 'buildingChange', true, 2)  
                     })
                     
-                    this.updateCadVisibles(currentFloor)
-                    
-                    
-                    
+                    this.updateCadVisibles(currentFloor) 
                 }
 
-            }
-            
-            
-            
-             
+            }    
         } 
-    },
+    }, */
 
 
 
@@ -223,7 +226,9 @@ var SiteModel = {
         Potree.Log('sitemodel enter')
         this.clear()  //确保全部清空
         this.editing = true
-        this.updatePanosVisible(null, null, true)//show all
+        //this.updatePanosVisible(null, null, true)//show all
+        viewer.updateFpVisiDatasets()
+        
         
         let mapViewport = viewer.mapViewer.viewports[0]
         SplitScreen.splitScreen4Views({siteModel:true/* , viewports:[{name:'Top',viewport : mapViewport  }] */})
@@ -244,8 +249,7 @@ var SiteModel = {
         }) 
         mapViewport.layersAdd('siteModeOnlyMapVisi') //只有mapViewport能看到marker
        
-         
-         
+          
         
     },
     
@@ -275,10 +279,12 @@ var SiteModel = {
         this.clear()   
         this.editing = false
         
-    } 
+        viewer.updateFpVisiDatasets()
+    } ,
+    
     
-    ,
      
+    
     /* startSetSiteModel:function(pos, type){//开始创建空间模型(非编辑状态的,不绘制)
         if(this.editing)return //编辑中不允许重新创建
         this.clear() 
@@ -1001,7 +1007,7 @@ var SiteModel = {
     },
     
     
-    pointInWhichEntity(location, buildType, ifIgnoreHole){//返回第一个符合标准的实体,buildType是要找的建筑类型
+    pointInWhichEntity(location, buildType, ifIgnoreHole){//buildType是要找的建筑类型
         //location 可以是pano或者坐标
         //由于房间可能在building外,所以房间要另外单独识别。
         
@@ -1011,7 +1017,7 @@ var SiteModel = {
             building: 0, floor: 1, room: 2 
         }
         
-        let traverse = (parent)=>{
+        let traverse = (parent)=>{//返回第一个符合标准的实体
             let contains;
             if(location instanceof THREE.Vector3){
                 contains = parent.ifContainsPoint(location)
@@ -1030,19 +1036,34 @@ var SiteModel = {
                             return parent.buildChildren[i]
                         } */ 
                         let result1 = traverse(parent.buildChildren[i])
-                        if(result1) result1
+                        if(result1) return result1
                     }  
                 }
             }
             
         }
+        //因为建筑可能重叠,所以需要先找到最接近其中心的建筑物
+        result = Common.sortByScore(this.buildings, [], [(building)=>{   //写法类似pointInWhichPointcloud
+            let boundingBox = building.getBound()
+            let center = boundingBox.getCenter(new THREE.Vector3())
+            let position = location instanceof THREE.Vector3 ? location : location.position
+            let dis = position.distanceTo(center)
+            let size = boundingBox.getSize(new THREE.Vector3())
+            let length = size.length() / 2;
+            return length / dis 
+        }]);    
+        
+        let building = result && result[0] && result[0].score > 1 && result[0].item 
+        if(buildType == 'building' || !building)return building
+        result = traverse(building) 
+         
          
          
-        for(let i=0,len=this.buildings.length; i<len; i++){
+        /* for(let i=0,len=this.buildings.length; i<len; i++){
             result = traverse(this.buildings[i])
             
             if(result){break}
-        } 
+        }  */
          
         
         
@@ -1153,7 +1174,7 @@ var SiteModel = {
             }) 
             scores.sort((a,b)=>{ return b.score-a.score }) 
             
-            if(scores.length == 0 || scores[0].volume/cloudVolume < 0.02){//如果约等于0 
+            if(scores.length == 0 || scores[0].volume/cloudVolume < 0.0001 && scores[0].volume < 3 ){//如果约等于0 
                 pointcloud.belongToEntity = null
             }else{
                 pointcloud.belongToEntity = scores[0].entity; 
@@ -1229,24 +1250,16 @@ var SiteModel = {
             let boundingBox = entity.getBound()
             let position = boundingBox.getCenter(new THREE.Vector3())
             
-            if(viewer.controls == viewer.orbitControls){ 
-                let dis = 2
-                let target = position
-                position = new THREE.Vector3().subVectors(target, viewer.scene.view.direction)
-                viewer.scene.view.setView({position,  duration,  target})
+            if(viewer.modules.Clip.editing){
+                viewer.modules.Clip.bus.dispatchEvent({type:'flyToPos', position})
             }else{
                 if(math.closeTo(position, viewer.images360.position)) return 'posNoChange'  
                 let size = boundingBox.getSize(new THREE.Vector3())
 
             
                 viewer.scene.view.setView({position,  duration})
-                viewer.mapViewer.moveTo(position, size, duration)
-                
-                
-            }
-            
-             
-            
+                viewer.mapViewer.moveTo(position, size, duration)  
+            } 
             
         }
         return true

+ 21 - 10
src/navigation/FirstPersonControls.js

@@ -58,7 +58,7 @@ export class FirstPersonControls extends THREE.EventDispatcher {
 
         };
 
-		this.fadeFactor = 50;
+		this.fadeFactor = 20;
 		this.yawDelta = 0;
 		this.pitchDelta = 0;
 		this.translationDelta = new THREE.Vector3(0, 0, 0);
@@ -224,7 +224,7 @@ export class FirstPersonControls extends THREE.EventDispatcher {
                          //console.log('pan2', e.drag.pointerDelta)
                     }
                 } 
-                
+                this.useAttenuation = false
 			}
             
             
@@ -295,7 +295,7 @@ export class FirstPersonControls extends THREE.EventDispatcher {
                 //定点缩放, 恢复一下鼠标所在位置的位置改变量
                 let moveVec = new THREE.Vector3().subVectors(newPos,oldPos)
                 this.translationWorldDelta.add(moveVec.negate()) 
-                
+                this.useAttenuation = false
             }else{
                 let speed , direction
                  
@@ -319,7 +319,7 @@ export class FirstPersonControls extends THREE.EventDispatcher {
                     direction = this.viewer.inputHandler.getMouseDirection(e.pointer).direction  //定点缩放
                 }
                  
-               
+                this.useAttenuation = true
                 var vec = direction.multiplyScalar(speed )
                 this.translationWorldDelta.copy(vec)
                 
@@ -635,6 +635,12 @@ export class FirstPersonControls extends THREE.EventDispatcher {
                 } else if (moveDown) {
                     this.translationWorldDelta.z = -this.currentViewport.getMoveSpeed();
                 }
+                
+                
+                if(moveUp || moveDown || moveForward || moveBackward){
+                    this.useAttenuation = false
+                }
+                
             } 
 		}
 
@@ -672,7 +678,7 @@ export class FirstPersonControls extends THREE.EventDispatcher {
 				this.translationWorldDelta.y /* * delta */,
 				this.translationWorldDelta.z /* * delta */
 			);
-            this.translationWorldDelta.set(0,0,0)
+            //this.translationWorldDelta.set(0,0,0)
 		}
 
 		{ // set view target according to speed
@@ -687,12 +693,17 @@ export class FirstPersonControls extends THREE.EventDispatcher {
 		}
  
 
-        { // decelerate over time
+        if(this.useAttenuation){ //只有滚轮缩放时开启
 			let attenuation = Math.max(0, 1 - this.fadeFactor * delta);
-			/* this.yawDelta *= attenuation;
+          
+			 /*this.yawDelta *= attenuation;
 			this.pitchDelta *= attenuation; 
-			this.translationDelta.multiplyScalar(attenuation);
-			this.translationWorldDelta.multiplyScalar(attenuation);*/
-		}   
+			this.translationDelta.multiplyScalar(attenuation);*/
+			this.translationWorldDelta.multiplyScalar(attenuation);
+		}else{
+            
+            this.translationWorldDelta.set(0,0,0)
+            
+        }  
 	}
 };

+ 10 - 38
src/navigation/InputHandler.js

@@ -85,7 +85,7 @@ export class InputHandler extends THREE.EventDispatcher {
         
         {
             this.addEventListener('isMeasuring',(e)=>{ 
-                console.log('isMeasuring',e.v,e.cause)
+                //console.log('isMeasuring',e.v,e.cause)
                 this.isMeasuring = e.v 
             }) 
         }
@@ -574,7 +574,7 @@ export class InputHandler extends THREE.EventDispatcher {
 
             // check for a click 
             if(pressDistance < Potree.config.clickMaxDragDis && pressTime<Potree.config.clickMaxPressTime){
-                if(this.hoveredElements && this.hoveredElements[0]){
+                if(this.hoveredElements && this.hoveredElements[0] && this.hoveredElements[0].object._listeners['click']){
                     if (this.logMessages) console.log(`${this.constructor.name}: click ${clicked.name}`);
                     this.hoveredElements[0].object.dispatchEvent($.extend(  
                         this.getEventDesc(e,isTouch),
@@ -768,7 +768,13 @@ export class InputHandler extends THREE.EventDispatcher {
         if(!viewport)return//刚变化viewport时会找不到
          
 		
-        let intersectPoint = this.getIntersect(viewport,camera,e.onlyGetIntersect, e.pickWindowSize)
+        let intersectPoint
+        
+        
+        if(e.onlyGetIntersect || !this.drag || this.drag.object){ //没有拖拽物体,但按下鼠标了的话,不intersect
+            intersectPoint = this.getIntersect(viewport,camera,e.onlyGetIntersect, e.pickWindowSize)
+        }
+        
         if(e.onlyGetIntersect){ 
             return intersectPoint
         }
@@ -862,41 +868,7 @@ export class InputHandler extends THREE.EventDispatcher {
                 }
 
             }
-
-            //仅在鼠标不按下时更新:
-            if(!this.drag){
-                let handleState = viewer.modules.Alignment.handleState
-                if(viewport.alignment && handleState && viewport.alignment[handleState]){
-                    if(handleState == 'translate'){
-                        if( intersectPoint && intersectPoint.location ){ 
-                            viewer.dispatchEvent({
-                                type : "CursorChange", action : "add",  name:"movePointcloud"
-                            })
-                        }else{
-                            viewer.dispatchEvent({
-                                type : "CursorChange", action : "remove",  name:"movePointcloud"
-                            })
-                        }
-                    }else if(handleState == 'rotate'){ 
-                        if( intersectPoint && intersectPoint.location ){ 
-                            viewer.dispatchEvent({
-                                type : "CursorChange", action : "add",  name:"rotatePointcloud"
-                            })
-                        }else{
-                            viewer.dispatchEvent({
-                                type : "CursorChange", action : "remove",  name:"rotatePointcloud"
-                            })
-                        }
-                    }  
-                }
-            } 
-                
-             
-            
-             
- 
-            
-            
+  
             
             this.viewer.dispatchEvent($.extend(  
                 this.getEventDesc(e,isTouch),

+ 7 - 8
src/objects/tool/Measure.js

@@ -298,10 +298,10 @@ export class Measure extends ctrlPolygon{
         marker.renderOrder = 3 
         marker.markerSelectStates = {} 
         marker.addEventListener('startDragging',(e)=>{
-            if(e.drag.dragViewport.name == 'MainView')viewer.inputHandler.dispatchEvent('isMeasuring', {v:true, cause:'startDragging'})
+            if(e.drag.dragViewport.name == 'MainView')viewer.inputHandler.dispatchEvent( {type: 'isMeasuring',v:true, cause:'startDragging'})
         })
         marker.addEventListener('drop',(e)=>{
-            viewer.inputHandler.dispatchEvent('isMeasuring', {v:false, cause:'stopDragging'}  )
+            viewer.inputHandler.dispatchEvent({type: 'isMeasuring',  v:false, cause:'stopDragging'}  )
         })
         
         let edge
@@ -398,12 +398,11 @@ export class Measure extends ctrlPolygon{
     setMarkerSelected(marker, state, hoverObject){
         
         //console.warn(marker.id , state, hoverObject)
-        
-        
+         
         marker.markerSelectStates[hoverObject] = state
         let absoluteState = false
         for(var i in marker.markerSelectStates){
-            if(marker.markerSelectStates[i]){
+            if(marker.markerSelectStates[i] == 'hover'){
                 absoluteState = true; break;
             }
         }
@@ -441,7 +440,7 @@ export class Measure extends ctrlPolygon{
         
         
         if(absoluteState){
-            this.markers.forEach(e=>this.setMarkerSelected(e,true,'selectAll' ) )
+            this.markers.forEach(e=>this.setMarkerSelected(e, 'hover', 'selectAll' ) )
             
             this.edges.forEach(e=>e.material = this.getLineMat('edgeSelect')   )
 			 
@@ -456,7 +455,7 @@ export class Measure extends ctrlPolygon{
             this.closed || this.edgeLabels.forEach(e=>setLabelHightState(e, true)  )
               
         }else{
-            this.markers.forEach(e=>this.setMarkerSelected(e,false,'selectAll' ))
+            this.markers.forEach(e=>this.setMarkerSelected(e, 'unhover', 'selectAll' ))
             this.edges.forEach(e=>e.material = this.getLineMat('edgeDefault')  )
             this.areaPlane && (this.areaPlane.material = planeMats.default)
             this.setEdgesDisplay(false, hoverObject=="screenshot")
@@ -877,7 +876,7 @@ export class Measure extends ctrlPolygon{
             this.area = {value:0};
             this.areaLabel && this.areaLabel.setVisible(false)
         }
-         viewer.inputHandler.dispatchEvent('isMeasuring', {v:true, cause:'reDraw'}  )
+        viewer.inputHandler.dispatchEvent( {type:'isMeasuring', v:true, cause:'reDraw'}  )
 	            
     }
     

+ 2 - 2
src/objects/tool/MeasuringTool.js

@@ -502,11 +502,11 @@ export class MeasuringTool extends THREE.EventDispatcher{
             this.viewer.inputHandler.addEventListener('keydown', pressExit) 
         } */ 
 		let mouseover = (e) => { 
-            measure.setMarkerSelected(e.object, true, 'single'); 
+            measure.setMarkerSelected(e.object, 'hover', 'single'); 
               
         };
         let mouseleave = (e) => { 
-            measure.setMarkerSelected(e.object, false, 'single'); 
+            measure.setMarkerSelected(e.object, 'unhover', 'single'); 
         }  
           
                  

+ 3 - 3
src/objects/tool/ctrlPolygon.js

@@ -98,13 +98,13 @@ export class ctrlPolygon extends THREE.Object3D {
             
             let addHoverEvent = (e)=>{
                 let mouseover = (e) => { 
-                    this.setMarkerSelected(e.object, true, 'single'); 
+                    this.setMarkerSelected(e.object, 'hover', 'single'); 
                     viewer.dispatchEvent({
                         type : "CursorChange", action : "add",  name:"markerMove"
                     }) 
                 };
                 let mouseleave = (e) => { 
-                    this.setMarkerSelected(e.object, false, 'single'); 
+                    this.setMarkerSelected(e.object, 'unhover', 'single'); 
                     viewer.dispatchEvent({
                         type : "CursorChange", action : "remove",  name:"markerMove"
                     })
@@ -429,7 +429,7 @@ export class ctrlPolygon extends THREE.Object3D {
         
        
         
-        this.setMarkerSelected(e.drag.object, false, 'single') 
+        this.setMarkerSelected(e.drag.object, 'unhover', 'single') 
         
         this.editStateChange(false)
         

+ 1 - 1
src/objects/tool/mapClipBox.js

@@ -192,7 +192,7 @@ export class mapClipBox extends ctrlPolygon {
     
     setMarkerSelected(marker, state, hoverObject){ 
         //console.warn(marker.id , state, hoverObject)
-        if(state){
+        if(state == 'hover'){
             marker.material = this.getMarkerMaterial('select')
         }else{
             marker.material = this.getMarkerMaterial('default')

+ 4 - 2
src/settings.js

@@ -78,7 +78,8 @@ const config = {//配置参数   不可修改
         flyOut:1000,
     } */
     transitionsTime:{
-        flyTime : 180,  // 毫秒/米
+        flyMinTime : 500,  // 毫秒/米
+        flytimeDistanceMultiplier:150,
         panoToPanoMax: 2000, 
         flyIn:1000,
         flyOut:1000
@@ -108,6 +109,7 @@ const config = {//配置参数   不可修改
             maxLevelPercent: 0.6,
             pointBudget : /* 4*1000*1000// */browser.isMobile() ?  0.1*1000*1000 :  0.4*1000*1000,  //点云总最大数
         }, 
+        
         fourViewports:{//分四屏时防止卡顿
             maxLevelPercent: 0.4,  
             pointBudget :1*1000*1000, // 只要限制这个就足够 (为什么分屏focus区域不同会闪烁,navvis不会)(navvis:maxLevel:5,pointBudget:1*1000*1000)
@@ -169,7 +171,7 @@ const config = {//配置参数   不可修改
         
     },
     material:{//初始化
-        pointSize:0.4,//0.75,//0.4, 相对大小
+        pointSize: 0.1, //0.4,//0.75,//0.4, 相对大小
         minSize: 0.1,
         maxSize: 10000,
         pointSizeType: 'ATTENUATED', //'ADAPTIVE'//'ADAPTIVE' \ FIXED //ADAPTIVE的在小房间里大小会不太匹配,但在远景似乎更好

+ 28 - 7
src/start.js

@@ -49,6 +49,7 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
 
     Potree.loadDatasetsCallback = function(data, ifReload){
         if(!data || data.length == 0)return console.error('getDataSet加载的数据为空')
+           
         Potree.datasetData = data
         viewer.transform = null
         var datasetLength = data.length 
@@ -65,10 +66,10 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
             }
             
             
-            if(!ifReload){   
+            if(!ifReload){    
                 viewer.scene.view.setView({ 
-                    position:center.clone().add(new THREE.Vector3(10,5,10)), 
-                    target:center
+                    position: center.clone().add(new THREE.Vector3(10,5,10)), 
+                    target: center
                 })
                  
                 viewer.dispatchEvent({type:'loadPointCloudDone'})
@@ -76,9 +77,8 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
                 if(!Potree.settings.UserPointDensity){
                     Potree.settings.UserPointDensity = 'high'//'middle' 
                 }
-                
-                
-                Potree.Log('loadPointCloudDone  点云加载完毕', null, 10)
+                 
+                Potree.Log('loadPointCloudDone  点云加载完毕', null, 10)  
             }    
             
         }
@@ -106,6 +106,20 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
                         })
                           
                     }
+                }else{//考虑到多数据集距离很远,或者像隧道那种场景,要使视野范围内一定能看到点云,最好初始点设置在漫游点上
+                    
+                    let {boundSize, center} = viewer.bound
+                    
+                    let pano = viewer.images360.findNearestPano(center)
+                     
+                    pano && viewer.scene.view.setView({ 
+                        position: pano.position.clone().add(new THREE.Vector3(10,10,10)), 
+                        target: pano.position
+                    })
+                    
+                    
+                    
+                    
                 } 
             }
             
@@ -194,7 +208,7 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
                     if(pointcloudLoaded == datasetLength)pointcloudLoadDone()
                         
                     Potree.loadPanos(dataset.id, (data) => { 
-                        console.log('loadPanos',dataset.sceneCode, dataset.id, data)
+                        //console.log('loadPanos',dataset.sceneCode, dataset.id, data)
                         viewer.images360.addPanoData(data, dataset )
                         panosLoaded ++; 
                         if(panosLoaded == datasetLength){
@@ -246,6 +260,13 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
 
     window.THREE = THREE
     window.buttonFunction = function(){
+        
+        
+         
+        viewer.scene.pointclouds.forEach(e=>e.predictNodeMaxLevel())
+               
+        
+        
         /* 
         viewer.startScreenshot({type:'measure', measurement:viewer.scene.measurements[0]}) 
         

+ 1 - 1
src/utils.js

@@ -420,7 +420,7 @@ export class Utils {
             pickParams.y = renderer.domElement.clientHeight - mouse.y; 
         } 
          
-        
+        //console.log('getMousePointCloudIntersection')
 		
 
 		let raycaster = new THREE.Raycaster();

+ 1 - 1
src/utils/CursorDeal.js

@@ -83,7 +83,7 @@ var CursorDeal = {
                 this.currentCursorIndex = addIndex
             }  
         }else{
-            var levelMax = {index:null, cursor:null }
+            var levelMax = {index:Infinity, cursor:null }
             this.list.forEach(name=>{
                 var priorityItem = this.priorityEvent.find(e=>e[name])
                 var index = this.priorityEvent.indexOf(priorityItem)

+ 7 - 2
src/utils/SplitScreen.js

@@ -108,6 +108,7 @@ var SplitScreen = {
             
             if(!viewport){
                 viewport = new Viewport( new View(), getOrthographicCamera(prop.width, prop.height, prop.axis), prop )
+                //viewport.unableDepth = true //depthBasicMaterial等在此viewport中不开启depth
                 viewports.push(viewport) 
             }                
              
@@ -150,7 +151,7 @@ var SplitScreen = {
             //ifShowMarker : Potree.settings.ifShowMarker, 
         }
         
-        viewer.setPointStandardMat(true) //切换到标准模式(主要为了mainViewport)
+        viewer.setPointStandardMat(true,null,true) //切换到标准模式(主要为了mainViewport)  点云使用标准大小 
         
         var matBefore = { 
             opacity : new Map() 
@@ -420,7 +421,11 @@ var SplitScreen = {
             if(e.name == 'MainView'){
                 let len = boundSize.length()
                 let distance = THREE.Math.clamp(e.view.position.distanceTo(center),  len * 0.01,  len*0.3 ) //距离限制
-                viewer.focusOnObject({position:center}, 'point', duration, {distance, direction: e.view.direction,dontMoveMap:true} )//平移镜头
+                //viewer.focusOnObject({position:center}, 'point', duration, {distance, direction: e.view.direction,dontMoveMap:true} )//平移镜头
+                //为了方便定位,直接飞到中心位置:
+                e.view.setView({
+                    position:center,  duration,  quaternion: new THREE.Quaternion().setFromEuler(e.view.rotation) 
+                })
             }else{
                 this.viewportFitBound(e, boundSize, center)
             }

+ 62 - 16
src/utils/UnitConvert.js

@@ -266,16 +266,32 @@ class UoMService{
         this.UnitService = new UnitService()/* UnitService */
         
     }
-    scopedConvert (t, n, precision = 2, r, maxFactor) {
-        return  e.convert(t, n, precision, r, maxFactor)
+    scopedConvert (t, n, precision = 2, r, minFactor) {
+        return  this.convert(t, n, precision, r, minFactor)
     }
     
-    convert(number, domain, precision = 2, system, maxFactor, ifEighths = !1) { 
+    convert(number, domain, precision = 2, system, minFactor, ifEighths = !1) { 
         if (!number) return "";
-        var s = this.getMostRelevantMeasurement(domain, system || this.UnitService.currentSystem, number, maxFactor);
+        var s = this.getMostRelevantMeasurement(domain, system || this.UnitService.currentSystem, number, minFactor);
         return this.getFormattedMeasurementString(s[0], s[1], precision, ifEighths)
     }
     
+    convertBack(number, domain, precision = 2, fromSystem, minFactor ) { //从英制转到'metric'
+        if (!number) return "";
+        var d = UnitsOfMeasurement.getDefaultUnitByDomainAndSystem(domain,'metric')
+        
+        var s = this.getMostRelevantMeasurement2(domain, fromSystem, number, minFactor);
+        return this.getFormattedMeasurementString(s[0], d, precision ) 
+        
+        
+        /* 栗子:
+        viewer.unitConvert.convertBack(1, 'area', 5, 'imperial')
+        '0.09290 m²'
+        viewer.unitConvert.convertBack(1, 'Distance', 2, 'imperial')
+        '0.03 m' 
+        */
+    }
+    
     getFormattedMeasurementString(number, unit, precision, ifEighths) {
         var result 
         if(ifEighths && unit.name === UnitsOfMeasurement.FOOT[0]){
@@ -306,30 +322,39 @@ class UoMService{
         return  0 !== r ? r + "' " + s + a + '"' : "" + s + a + '"'
     }
     
-    getMostRelevantMeasurement(t, e, n, maxFactor=0) {
-        /* var a = r.values(UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(t, e))
-          , s = r.filter(a, function(t) {
+    getMostRelevantMeasurement(domain, system, number, minFactor=0) {
+        /* var a = r.values(UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(domain, system))
+          , s = r.filter(a, function(t) {  
             return t.factor >= i
         })
           , c = r.reduce(s, function(t, e) {
-            return e.fromBase(n) < t.fromBase(n) && e.fromBase(n) >= 1 ? e : t
+            return e.fromBase(number) < t.fromBase(number) && e.fromBase(number) >= 1 ? e : t
         }); */
         let a = []
-        let u = UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(t, e)
+        let u = UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(domain, system)
         for(let i in u){a.push(u[i])}
          
-        let s = a.filter(m=>m.factor >= maxFactor) 
+        let s = a.filter(m=>m.factor >= minFactor) 
          
-        //有可能会写错,看不懂原函数
         
-        let c = s.reduce(function(i, e) {//reduce计算数组元素相加后的总和
-            return e.fromBase(n) < i.fromBase(n) && e.fromBase(n) >= 1 ? e : i
+       
+        let c = s.reduce(function(prev, currentValue) {//reduce最终值是最后一次return的值 ( 没看懂这句话作用) 
+            return currentValue.fromBase(number) < prev.fromBase(number) && currentValue.fromBase(number) >= 1 ? currentValue : prev
         })
         
-        return c ? [c.fromBase(n), c] : void 0
+        return c ? [c.fromBase(number), c] : void 0
+    }
+    
+    getMostRelevantMeasurement2(domain, system, number, minFactor=0) {//add
+        let a = []
+        let u = UnitsOfMeasurement.getUnitsOfMeasurementByDomainAndSystem(domain, system)
+        for(let i in u){a.push(u[i])} 
+        let s = a.filter(m=>m.factor >= minFactor)  
+        let c = s.reduce(function(prev, currentValue) {//reduce最终值是最后一次return的值 ( 没看懂这句话作用) 
+            return currentValue.toBase(number) < prev.toBase(number) && currentValue.toBase(number) >= 1 ? currentValue : prev
+        }) 
+        return c ? [c.toBase(number), c] : void 0
     }
-   
-     
     /* ɵfac(e){
         return new (e || t)(c.ɵɵinject(l.UnitService))
     }
@@ -343,5 +368,26 @@ class UoMService{
 }
 
 
+/* 
+使用方法:
+
+
+初始化:
+    var unitConvert = new UoMService();
+ 
+    要设置的类型,两种:var unitSystem = 'metric' || 'imperial'  
+ 
+
+使用:
+
+    面积:
+        let text = viewer.unitConvert.convert(area, 'area', void 0,  unitSystem,  )  
+
+    长度:
+        var text = viewer.unitConvert.convert(distance, 'distance', void 0, unitSystem, 0.1 , true)//distance要传0.1这个factor。 最后一个参数传true代表使用八分之一表示。
+
+ */
+
+
 
 export {UoMService}

+ 40 - 22
src/viewer/EDLRenderer.js

@@ -14,7 +14,7 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 		this.edlMaterial = null;
 
 		//this.rtRegular;
-		this.rtEDL;
+		this.rtEDLs = new Map
 
 		this.gl = viewer.renderer.getContext();
         //反正也没用到,注释了:
@@ -34,20 +34,7 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 		this.edlMaterial.depthWrite = true;
 		this.edlMaterial.transparent = true;
         
-        
-        if(Features.EXT_DEPTH.isSupported()){ 
-            this.rtEDL = new THREE.WebGLRenderTarget(viewer.mainViewport.resolution2.x, viewer.mainViewport.resolution2.y, {
-                minFilter: THREE.NearestFilter,
-                magFilter: THREE.NearestFilter,
-                format: THREE.RGBAFormat,
-                type: THREE.FloatType,
-                depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
-            }); 
-            //注: 部分手机在resize时会崩溃,经检验去掉rtEDL的resize可以解决,所以更应该注释掉这个
-        }
          
-  
-
 
 		/* this.rtRegular = new THREE.WebGLRenderTarget(viewer.mainViewport.resolution2.x, viewer.mainViewport.resolution2.y, {
 			minFilter: THREE.NearestFilter,
@@ -75,10 +62,11 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
         
 	};
 
-	resize(e,  aaa){
+	resize(e ){
         if(Features.EXT_DEPTH.isSupported()){  
             let viewport = e.viewport
-            this.rtEDL.setSize(viewport.resolution2.x, viewport.resolution2.y);
+             
+            this.getRtEDL(viewport).setSize(viewport.resolution2.x, viewport.resolution2.y);
         }
 	}
 
@@ -102,8 +90,12 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
                 renderer.setRenderTarget( params.rtEDL);
                 renderer.clear() 
             }else{
-                renderer.setRenderTarget( this.rtEDL );
-                renderer.clear( true, true, true );
+                var rtEDL = this.getRtEDL(params.viewport)
+                if(rtEDL){
+                    renderer.setRenderTarget( rtEDL );
+                    renderer.clear( true, true, true );
+                }
+                
             }
         }
         
@@ -115,6 +107,32 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 		renderer.setRenderTarget(oldTarget);
 	}
  
+ 
+    getRtEDL(viewport){//根据不同viewport返回rtEDL的texture
+        if(!viewport){
+            console.warn('getRtEDL没传viewport!!!! !!!!!!!!!!')
+            viewport = viewer.mainViewport
+        }
+        var rtEDL = this.rtEDLs.get(viewport)
+        if(!rtEDL){
+            if(Features.EXT_DEPTH.isSupported()){ 
+                rtEDL = new THREE.WebGLRenderTarget(viewport.resolution2.x, viewport.resolution2.y, {
+                    minFilter: THREE.NearestFilter,
+                    magFilter: THREE.NearestFilter,
+                    format: THREE.RGBAFormat,
+                    type: THREE.FloatType,
+                    depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
+                }); 
+                //注: 部分手机在resize时会崩溃,经检验去掉rtEDL的resize可以解决,所以更应该注释掉这个
+            
+                
+                this.rtEDLs.set(viewport, rtEDL)
+            }  
+        } 
+    
+        return rtEDL
+    }
+ 
 
 	renderShadowMap(visiblePointClouds, camera, lights){
 
@@ -264,7 +282,7 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
             
             if(Features.EXT_DEPTH.isSupported()){   
                 //借用rtEDL存储深度信息 
-                viewer.renderer.setRenderTarget(params.rtEDL || this.rtEDL);
+                viewer.renderer.setRenderTarget(params.rtEDL || this.getRtEDL(params.viewport)/* this.rtEDL */);
                  
                 //pointDensity已经使用的是panorama模式,在画面边缘点云会稀疏,遮挡效果差
                 
@@ -288,7 +306,7 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
                     }
                 }  */   
                 //渲染scenePointCloud到rtEDL
-                viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, params.rtEDL || this.rtEDL, {
+                viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, params.rtEDL || this.getRtEDL(params.viewport), {
                     shadowMaps:  lights.length > 0 ? [this.shadowMap] : null,
                     clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
                     transparent: false,
@@ -342,8 +360,8 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
             projArray.set(proj.elements);
             uniforms.uProj.value = projArray;
 		 
-			uniforms.uEDLColor.value = (params.rtEDL || this.rtEDL).texture;
-			//uniforms.uEDLDepth.value = (params.rtEDL || this.rtEDL).depthTexture; //其实没用到
+			uniforms.uEDLColor.value = (params.rtEDL || this.getRtEDL(params.viewport)).texture;
+			//uniforms.uEDLDepth.value = (params.rtEDL || this.getRtEDL(params.viewport)).depthTexture; //其实没用到
 			 
 			uniforms.opacity.value = viewer.edlOpacity; // HACK
 			 

+ 2 - 1
src/viewer/View.js

@@ -255,7 +255,8 @@ export class View extends THREE.EventDispatcher{
             this.restrictPos()
 			
             info.onUpdate && info.onUpdate(1)
-            done()
+            setTimeout(done.bind(this), 1);  //延迟一下再执行  是为了让images360里的flying先为true
+            
 		}else{
 
             transitions.start(lerp.vector(this.position, endPosition, (pos, progress)=>{

+ 15 - 5
src/viewer/map/MapViewer.js

@@ -174,13 +174,16 @@ export class MapViewer extends ViewerBase{
         this.setViewLimit('standard')
             
         let viewport = new Viewport( this.view, this.camera, {
-            left:0, bottom:0, width:1, height: 1, name:'mapViewport' 
+            left:0, bottom:0, width:1, height: 1, name:'mapViewport'  
         })
         viewport.axis = ["x","y"]
         viewport.axisSign = [1,1]
         
         viewport.noPointcloud = true; //不要渲染点云
         viewport.render = this.render.bind(this)//标志给mainView渲染
+        //viewport.unableDepth = true //depthBasicMaterial等在此viewport中不开启depth
+        
+        
         
         this.viewports = [viewport]
         
@@ -354,9 +357,7 @@ export class MapViewer extends ViewerBase{
     
     fitPanosToViewport(){//使所有漫游点占满viewport 
         
-        //var w = viewer.bound.boundSize.x;
-         
-        
+        //var w = viewer.bound.boundSize.x; 
         var boundSize = viewer.images360.bound.size.clone().multiplyScalar(1.1);
         boundSize.max(new THREE.Vector3(4,4,4))
         let endPosition = viewer.images360.bound.center.clone()
@@ -374,11 +375,20 @@ export class MapViewer extends ViewerBase{
         let dis = 5 , px = 70 //地图上px像素长度代表的距离为dis  //px是手动缩放到5m后发现是这个长度
         let zoom = px / dis;
         this.camera.zoom = zoom
-        this.moveTo(viewer.images360.bound.center) 
+        this.moveTo(viewer.images360.position/* viewer.images360.bound.center */) 
         this.camera.updateProjectionMatrix()
 
     }
     
+    fitToDatasets(datasets){
+        let bound = new THREE.Box3; 
+        datasets.forEach(e=>bound.union(e.bound))
+        let center = bound.getCenter(new THREE.Vector3)
+        let size = bound.getSize(new THREE.Vector3)
+        
+        this.moveTo(center, size, 200 ) //给duration是为了顺应视口大小改变,缓冲
+    }
+    
     moveTo(endPosition, boundSize, duration=0, easeName){//前两个参数有xy即可
         endPosition = new THREE.Vector3(endPosition.x,endPosition.y,Potree.config.map.cameraHeight)
         

+ 258 - 68
src/viewer/viewer.js

@@ -84,7 +84,7 @@ export class Viewer extends ViewerBase{
             CamAniEditor
         }
         
-        this.testingMaxLevel = true
+        //this.testingMaxLevel = true
         
          
         console.log('create viewer')
@@ -95,6 +95,9 @@ export class Viewer extends ViewerBase{
         this.unitConvert = new UoMService();
         mapArea = mapArea_
         this.visible = true
+        this.fpVisiDatasets = []
+        this.atDatasets = []
+        
 		//-------------
         
         var supportExtFragDepth = !!Features.EXT_DEPTH.isSupported() ;//iphoneX居然不支持
@@ -487,7 +490,7 @@ export class Viewer extends ViewerBase{
                         
                         pointDensity = density
                         
-                        this.setPointLevel()
+                        this.setPointLevels()
                         
                         
                     }
@@ -508,35 +511,7 @@ export class Viewer extends ViewerBase{
                     }
                 }
             })
-             
-            this.addEventListener('updateNodeMaxLevel',(e)=>{
-                
-                if(!viewer.testNodeLevelTimer && viewer.testingMaxLevel  ){
-                    viewer.testNodeLevelTimer = setTimeout(()=>{//先加载一段时间最高level的点云。但希望不会刚好附近的点云都没有达到最高的level,否则就要走一段才能了。
-                        viewer.testingMaxLevel = false
-                        console.log('结束testingMaxLevel')
-                        
-                        this.setPointLevel()//重新计算
-                    },3000) 
-                    viewer.beginTestTime = Date.now()
-                }
-                console.log('updateNodeMaxLevel ' +  e.pointcloud.dataset_id + " : "+ e.nodeMaxLevel)                
-                if(e.nodeMaxLevel >= 10 && viewer.testingMaxLevel){//10的时候差不多能加载到11和12了。假设最高只有12的话,就到10就可以。不过大多数场景都到不了10,也不知有没有大于10的,如果没有,这里可以写5. 见过最小是1
-                    viewer.testingMaxLevel = false
-                    console.log('提前结束testingMaxLevel,用时:'+(Date.now()-viewer.beginTestTime))
-                    //我的电脑用时大概1500
-                }
-                 
-                this.setPointLevel()//重新计算
-                
-                
-                if(!Potree.settings.sizeFitToLevel){
-                    e.pointcloud.changePointSize()
-                    
-                }
-                
-                //见过最小加载到的nodeMaxLevel是4
-            })
+           
             
         }
         {
@@ -560,38 +535,222 @@ export class Viewer extends ViewerBase{
         }
         
         
+        this.addEventListener('allLoaded',  this.testPointcloudsMaxLevel.bind(this))
+        
+        {
+            
+            //更新所在数据集
+            var lastPos = new THREE.Vector3(Infinity,Infinity,Infinity)
+            this.addEventListener('camera_changed', e => {
+                Common.intervalTool.isWaiting('atWhichDataset', ()=>{ //延时update,防止卡顿
+                    let currPos = viewer.scene.getActiveCamera().position
+                 
+                    if(!currPos.equals(lastPos)){
+                        lastPos.copy(currPos)
+                        
+                        var at = this.scene.pointclouds.filter(e=>e.ifContainsPoint(currPos)) 
+                        
+                        if(Common.getDifferenceSet(at, this.atDatasets).length){
+                            //console.log('atDatasets', at) 
+                            this.atDatasets = at
+                            this.updateFpVisiDatasets()
+                            this.dispatchEvent({type:'pointcloudAtChange',pointclouds:at}) 
+                        }
+                         
+                        return true 
+                    }
+                }, 500)  
+
+            }) 
+            
+        } 
         
+        this.addEventListener('switchFloorplanSelect',(e)=>{//进入平面图设置后 切换选中的数据集
+            this.selectedFloorplan = e.pointcloud;  //绝对显示
+            this.updateFpVisiDatasets()
+            let pointclouds;
+            if(e.pointcloud){
+                pointclouds = [e.pointcloud]
+            }else if(this.fpVisiDatasets.length){
+                pointclouds = this.fpVisiDatasets
+            }
+            
+            pointclouds && this.mapViewer.fitToDatasets(pointclouds) 
+            
+        })
         
+        
+        this.modules.SiteModel.bus.addEventListener('FloorChange',()=>{
+             this.updateFpVisiDatasets()
+        }) 
+        
+        
+        /* this.modules.Clip.bus.addEventListener('updateSelectedDatasets',()=>{
+             this.updateFpVisiDatasets()
+        }) */
+        
+        this.mapViewer.mapLayer.addEventListener('floorplanLoaded',()=>{
+             this.updateCadVisibles(this.fpVisiDatasets, true)   //加载完成后重新更新下
+        })
+         
          
 	}
 
+
     
     
+
+    updatePanosVisibles(currentFloor, pointclouds){//显示数据集和当前楼层的所有panos(为了显示出平面图中所有漫游点。漫游点个数>=平面图中包含的)
+        viewer.images360.panos.forEach(pano=>{
+            let visible = currentFloor && currentFloor.panos.includes(pano) || pointclouds.some(e=>e.panos.includes(pano));
+            viewer.updateVisible(pano, 'buildingChange', visible, 2)  
+        })
+    }
     
     
-    setPointLevel(){
-        var pointDensity = Potree.settings.pointDensity
-        var config = Potree.config.pointDensity[pointDensity];
-        if(!config)return
-        this.scene.pointclouds.forEach(e=>{
-            if(this.testingMaxLevel){
-                e.maxLevel = 12;//先加载到最大的直到测试完毕。由于5个level为一组来加载,所以如果写4最高能加载到5,如果写5最高能加载到下一个级别的最高也就是10
-                //console.log('maxLevel: '+e.maxLevel +  ' testingMaxLevel中 '  )                                
-            }else{
-                let percent = config.percentByUser && Potree.settings.UserDensityPercent != void 0  ? Potree.settings.UserDensityPercent : config.maxLevelPercent  
-                e.maxLevel = Math.round( percent * e.nodeMaxLevel); 
-                //console.log('maxLevel: '+e.maxLevel +  ',   density : '+Potree.settings.pointDensity,  ",  percent :"+percent);
+    updateFpVisiDatasets(){
+        
+        
+        
+        let Clip = this.modules.Clip
+        let SiteModel = this.modules.SiteModel
+        let Alignment = this.modules.Alignment
+        var currentFloor = SiteModel.currentFloor;
+        
+        /* if(Clip.editing){
+            
+            this.updateCadVisibles(Clip.selectedDatasets)
+            
+            
+        }else  */if(this.selectedFloorplan){//平面图设置中
+            let pointclouds = [this.selectedFloorplan]
+            this.updateCadVisibles(pointclouds)
+        }else if(SiteModel.editing || Alignment.editing){//只显示勾选的,也就是显示的点云的
+            let pointclouds = this.scene.pointclouds.filter(p => this.getObjVisiByReason(p,'datasetSelection')  ); 
+            this.updateCadVisibles(pointclouds)
+            this.updatePanosVisibles(currentFloor, pointclouds)
+        }else{ 
+            let pointclouds = currentFloor ? this.findPointcloudsAtFloor(currentFloor) : []
+            
+            if(pointclouds == 0){//如果当前不在任何楼层或楼层中无数据集,就用当前所在数据集
+                pointclouds = this.atDatasets
+            }
+             
+            this.updateCadVisibles(pointclouds)
+            this.updatePanosVisibles(currentFloor, pointclouds)
+        }
+    }
+    
+    
+    findPointcloudsAtFloor(entity){//找当前楼层需要显示哪些数据集。
+        //必要条件:数据集的belongToEntity 在这个entity内(否则会出现点击数据集飞过去平面图却不显示)。or 如果数据集有漫游点的话,需要包含>20%的漫游点。   (防止重叠体积很大但其实一个漫游点都不包含)
+        //充分条件(在符合必要条件之后还应该满足至少一个充分条件): 重叠体积>50%   或   包含>50%的漫游点 
+         
+        
+        const ratio1 = 0.2, ratio2 = 0.5, ratio3 = 0.5
+        var pointclouds = viewer.scene.pointclouds.filter(e=>{
+            
+            
+            if(e.belongToEntity && (e.belongToEntity == entity || e.belongToEntity.buildParent == entity)){//必要条件1
+                return true
+            }
+            
+            if(e.panos.length){//必要条件2
+                var insidePanos = e.panos.filter(a=>entity.ifContainsPoint(a.position));
+                let panoCountRatio = insidePanos.length / e.panos.length
+                if(panoCountRatio < ratio1){ 
+                    return false
+                }
                 
-                if(Potree.settings.sizeFitToLevel){
-                    e.changePointSize() 
+                if(panoCountRatio > ratio2)return true 
+            } 
+             
+             
+            let volume = entity.intersectPointcloudVolume(e);
+            let volumeRatio = volume / entity.getVolume(true) //注:hole加入计算
+            if(volumeRatio > ratio3){
+                return true 
+            } 
+        })
+        return pointclouds
+    }
+
+    updateCadVisibles(visiClouds, force){
+        let oldVisi = this.fpVisiDatasets
+        var visiClouds = this.fpVisiDatasets = visiClouds
+        
+        if(!force){
+            var difference = Common.getDifferenceSet(oldVisi , visiClouds) 
+            if(difference.length == 0)return
+        }
+        
+        
+        viewer.scene.pointclouds.forEach(pointcloud=>{ 
+            var floorplan = viewer.mapViewer.mapLayer.getFloorplan(pointcloud.dataset_id)
+            var visi = visiClouds.includes(pointcloud) 
+            if(floorplan){
+                viewer.updateVisible(floorplan.objectGroup, 'buildingChange', visi) 
+            }/* else if(!visi){   
+                let changeVisi = (e)=>{
+                    viewer.updateVisible(e.floorplan.objectGroup, 'buildingChange', this.fpVisiDatasets.includes(pointcloud)) 
+                    viewer.mapViewer.mapLayer.removeEventListener('floorplanLoaded',  changeVisi)
+                    console.log('updateCadVisibles加载后更改显示',e)
                 } 
-                e.changePointOpacity()
-            }  
+                viewer.mapViewer.mapLayer.addEventListener('floorplanLoaded',  changeVisi)
+            } */  
+            //已经添加了全局的  floorplanLoaded后会updateCadVisibles,这段就删了
+        })
+        viewer.mapViewer.mapLayer.needUpdate = true  //可能需要更新加载的level程度
+        viewer.mapViewer.needRender = true //若上句不触发加载也要立即重新绘制
+    }
+
+
+    //更新所在数据集
+             
+    testPointcloudsMaxLevel(){ //所有点云都无需testMaxNodeLevel 就停止
+        let camera_changed,  count = 0
+        let test = ()=>{
+            camera_changed = true
+            
+            
+            Common.intervalTool.isWaiting('testPointcloudsMaxLevel', ()=>{  
+                if(!camera_changed && count>10 )return //只有当camera_changed后才继续循环, 除了最开始几次需要连续加载下
+                camera_changed = false
+                count ++;
+                //console.log('testPointcloudsMaxLevel中')
+                
+                var success = true    
+                viewer.scene.pointclouds.forEach(e=>{
+                    var wait = e.testMaxNodeLevel()
+                    if(wait){
+                        success = false; 
+                    }
+                })
+                  
+                if(!success)return true //没有全部加载完,继续循环      
+                else {
+                    this.removeEventListener('camera_changed',test)
+                    console.log('testPointcloudsMaxLevel结束')
+                }
+                
+            }, count<5 ? 150 : 500) 
+        }            
+        this.addEventListener('camera_changed',test) 
+        test()
+        
+        /*  检验:
+            viewer.scene.pointclouds.sort((a,b)=>a.nodeMaxLevelPredict.min - b.nodeMaxLevelPredict.min).forEach(e=>console.log(e.nodeMaxLevel, e.nodeMaxLevelPredict.min))
+        
+         */
+        
+    }
+    
+    
+    
+    setPointLevels(){ 
+        this.scene.pointclouds.forEach(e=>{
+            e.setPointLevel()
         })  
-        /* if(!viewer.testingMaxLevel && Potree.sdk){
-            Potree.sdk.scene.changePointSize()
-            Potree.sdk.scene.changePointOpacity()
-        } */
     }
 
 
@@ -2857,7 +3016,7 @@ export class Viewer extends ViewerBase{
         
         
         
-        var screenshot = ()=>{
+        var screenshot = ()=>{ 
             
             useMap && (viewer.mapViewer.needRender = true)
             
@@ -3203,7 +3362,7 @@ export class Viewer extends ViewerBase{
         } else if (type == 'tag' || type == 'point') {
             //dimension = 1  
             target.copy(object.position)
-            let bestDistance = o.distance || 2 
+            let bestDistance = o.distance || 3 
             
             if(!o.dontMoveMap){ 
                 //console.log('mapFocusOn: '+target.toArray()) 
@@ -3295,16 +3454,14 @@ export class Viewer extends ViewerBase{
                 })
             }else return false
         }else{ 
-            
-            if(this.controls == this.orbitControls){ 
-                let dis = 2
-                let target = center
-                position = new THREE.Vector3().subVectors(target, this.scene.view.direction)
-                viewer.scene.view.setView({position,  duration,  target})
+            if(this.modules.Clip.editing){
+                this.modules.Clip.bus.dispatchEvent({type:'flyToPos', position:center})
             }else{
                 if(math.closeTo(center, this.images360.position)) return 'posNoChange'
                 position = center
                 viewer.scene.view.setView({position,  duration })
+               
+                viewer.mapViewer.moveTo(position.clone(), null/* boundSizeMap */, duration)
             }  
         }            
         
@@ -3568,36 +3725,63 @@ export class Viewer extends ViewerBase{
     
      
     //设置点云为标准模式 
-    setPointStandardMat(state, pointDensity){
-        //console.log('setPointStandardMat',state)
+    setPointStandardMat(state, pointDensity, fitPointsize){
+        console.log('setPointStandardMat',state)
         if(state){
             if(this.pointStatesBefore){
                 return console.error('已设置过pointStatesBefore!')
             }
-            this.pointStatesBefore = {opacity : new Map(), density:Potree.settings.pointDensity }
+            this.pointStatesBefore = {
+                opacity : new Map(), 
+                size: new Map(), 
+                density:Potree.settings.pointDensity,
+                useEDL:this.getEDLEnabled(), 
+                shape: viewer.scene.pointclouds[0].material.shape
+            }
+            
             viewer.scene.pointclouds.forEach(e=>{
                 this.pointStatesBefore.opacity.set(e, e.temp.pointOpacity)  //因为更改pointDensity时会自动变opacity,所以这项最先获取
-                this.pointStatesBefore.colorType = e.material.activeAttributeName;
+                this.pointStatesBefore.colorType = e.material.activeAttributeName; 
+                fitPointsize && this.pointStatesBefore.size.set(e,e.temp.pointSize) //这项不一定有用,因为会被后期覆盖
             }) 
             
             if(pointDensity)Potree.settings.pointDensity = pointDensity //万一之后切换到全景模式怎么办 
+            if(fitPointsize)Potree.settings.sizeFitToLevel = true 
             
             viewer.scene.pointclouds.forEach(e=>{   
                 e.material.activeAttributeName = 'rgba'; 
-                e.changePointOpacity(1) 
+                e.material.shape = Potree.PointShape['SQUARE']
+                fitPointsize && e.changePointSize(Potree.config.material.pointSize, true) 
+                e.changePointOpacity(1)      
             })
+            
+            viewer.setEDLEnabled(false)
+            
         }else{
             if(!this.pointStatesBefore){
                 return console.error('未设置过pointStatesBefore!')
             }
+            Potree.settings.sizeFitToLevel = false
             if(pointDensity)Potree.settings.pointDensity = this.pointStatesBefore.pointDensity
             
+            
             viewer.scene.pointclouds.forEach(e=>{   
                 e.material.activeAttributeName = this.pointStatesBefore.colorType
                 e.changePointOpacity(this.pointStatesBefore.opacity.get(e)) 
+                e.material.shape = this.pointStatesBefore.shape
+                
+                let size = this.pointStatesBefore.size.get(e)
+                if(size) e.changePointSize(size)
+                
+                
             })
+            viewer.setEDLEnabled(this.pointStatesBefore.useEDL)
             
             this.pointStatesBefore = null
+            
+            
+            
+            
         }
         
         
@@ -3625,7 +3809,7 @@ export class Viewer extends ViewerBase{
             (pointcloud)=>{ 
                 var size = pointcloud.pcoGeometry.tightBoundingBox.getSize(new THREE.Vector3)
                 var center = pointcloud.bound.getCenter(new THREE.Vector3)
-                var length = size.length()
+                var length = size.length() / 2
                 var dis = pos.distanceTo(center);
                 return length / dis  //到数据集中心的距离占数据集大小越小越好
             }
@@ -4044,7 +4228,7 @@ export class Viewer extends ViewerBase{
             info.plane = plane
             plane.boundingBox = new THREE.Box3(new THREE.Vector3(0,-0.5,0),new THREE.Vector3(1,-0.4,0.2))
             video.addEventListener('loadeddata', function(e) {
-                 video.play()
+                 video.play() 
                  if(!info.visibles/* ||!viewer.images360.currentPano || info.visibles.includes(viewer.images360.currentPano.id) */){
                      plane.material.opacity = 1
                  } 
@@ -4060,9 +4244,15 @@ export class Viewer extends ViewerBase{
                     if(info.visibles.includes(e.toPano.pano.id)){ //出现 
                         setTimeout(()=>{
                             plane.visible = true; 
-                                    
+                            video.currentTime = 0        
                             video.play();
-                            video.currentTime = 0
+                            if(video.paused){
+                                var startPlay = ()=>{
+                                    plane.visible && video.play() 
+                                    this.removeEventListener('global_mousedown', startPlay)
+                                }
+                                this.addEventListener('global_mousedown', startPlay)
+                            }
                             Potree.settings.zoom.enabled = false
                             
                             transitions.start(lerp.property(plane.material, "opacity", 1 ) , e.toPano.duration*0.4 , ()=>{

+ 4 - 2
改bug的历史.txt

@@ -1,7 +1,9 @@
 
+2022-05-12 
 
-
-
+为什么lineMaterial 在四屏中  setSize后,遮挡失效,要移动一下镜头才恢复? 但是在双屏中没事。 updateDepthParams()也没用。 
+	只要有第三个viewport高度不为0,就会这样。 那估计是edl在别的屏幕渲染了
+	因为不同viewport需要用不同的rtEDL  
 
 
 2022-04-24