Browse Source

修复点云渲染透明度没恢复导致贴图渲染打开了blend的bug
还有tile的方向写错了

xzw 3 years ago
parent
commit
9e0aee5cb7
44 changed files with 1856 additions and 412 deletions
  1. 15 11
      libs/three.js/build/three.module.js
  2. 32 16
      libs/three.js/lines/LineMaterial.js
  3. 102 29
      note笔记笔记笔记.txt
  4. 9 0
      src/Features.js
  5. 7 1
      src/LRU.js
  6. 652 5
      src/PointCloudOctree.js
  7. 1 0
      src/PointCloudTree.js
  8. 47 6
      src/PotreeRenderer.js
  9. 1 0
      src/Potree_update_visibility.js
  10. 2 2
      src/TextSprite.js
  11. 16 0
      src/loader/BinaryLoader.js
  12. 20 17
      src/materials/DepthBasicMaterial.js
  13. 2 2
      src/materials/PointCloudMaterial.js
  14. 36 19
      src/modules/Images360/Images360.js
  15. 25 10
      src/modules/Images360/Panorama.js
  16. 29 6
      src/modules/Images360/tile/PanoRenderer.js
  17. 1 1
      src/modules/Images360/tile/QualityManager.js
  18. 11 3
      src/modules/Images360/tile/TileDownloader.js
  19. 17 9
      src/modules/Images360/tile/TilePrioritizer.js
  20. 3 0
      src/modules/datasetAlignment/Alignment.js
  21. 2 2
      src/modules/siteModel/SiteModel.js
  22. 12 18
      src/navigation/FirstPersonControls.js
  23. 16 7
      src/navigation/InputHandler.js
  24. 87 14
      src/navigation/OrbitControls.js
  25. 45 10
      src/navigation/Reticule.js
  26. 16 9
      src/navigation/RouteGuider.js
  27. 67 31
      src/settings.js
  28. 75 9
      src/start.js
  29. 35 6
      src/utils/DrawUtil.js
  30. 21 8
      src/utils/Magnifier.js
  31. 5 5
      src/utils/Measure.js
  32. 36 12
      src/utils/MeasuringTool.js
  33. 5 7
      src/utils/PointCloudSM.js
  34. 2 2
      src/utils/SplitScreen.js
  35. 7 0
      src/utils/TransformationTool.js
  36. 24 18
      src/utils/ctrlPolygon.js
  37. 1 1
      src/utils/mapClipBox.js
  38. 59 43
      src/viewer/EDLRenderer.js
  39. 2 2
      src/viewer/Scene.js
  40. 7 4
      src/viewer/map/Map.js
  41. 126 33
      src/viewer/map/MapViewer.js
  42. 1 1
      src/viewer/sidebar.js
  43. 147 27
      src/viewer/viewer.js
  44. 30 6
      src/viewer/viewerBase.js

+ 15 - 11
libs/three.js/build/three.module.js

@@ -23684,19 +23684,23 @@ function WebGLRenderer( parameters ) {
 
 		_width = width;
 		_height = height;
+        
+        //if(!window.unableSetSize){ 
+            _canvas.width = Math.floor( width * _pixelRatio );
+            _canvas.height = Math.floor( height * _pixelRatio );
+        
+        
+        
+            if ( updateStyle !== false ) {
 
-		_canvas.width = Math.floor( width * _pixelRatio );
-		_canvas.height = Math.floor( height * _pixelRatio );
-
-		if ( updateStyle !== false ) {
-
-			_canvas.style.width = width + 'px';
-			_canvas.style.height = height + 'px';
-
-		}
-
-		this.setViewport( 0, 0, width, height );
+                _canvas.style.width = width + 'px';
+                _canvas.style.height = height + 'px';
 
+            }
+            
+            
+            this.setViewport( 0, 0, width, height );
+        //}
 	};
 
 	this.getDrawingBufferSize = function ( target ) {

+ 32 - 16
libs/three.js/lines/LineMaterial.js

@@ -344,11 +344,13 @@ var LineMaterial = function ( parameters ) {
 		clipping: true // required for clipping support
 
 	} );
-
+    this.supportExtDepth = parameters.supportExtDepth
+    
+    
 	this.dashed = false;
     this.lineWidth_ = 0
-    
-
+   
+   
 
 	Object.defineProperties( this, {
         dashed:{//add
@@ -380,6 +382,9 @@ var LineMaterial = function ( parameters ) {
 			},
 
 			set: function ( value ) {
+                
+                value = value && !!this.supportExtDepth
+                
                 if(value != this.useDepth){ 
                     if(value){
                         this.defines.useDepth = ''
@@ -402,6 +407,10 @@ var LineMaterial = function ( parameters ) {
 			},
 
 			set: function ( value ) {
+                
+                value = value && !!this.supportExtDepth
+                
+                
                 if(value != this.dashWithDepth){ 
                     if(value){
                         this.defines.DASH_with_depth = '' 
@@ -562,15 +571,9 @@ var LineMaterial = function ( parameters ) {
 	} );
 
 	this.setValues( parameters );
- 
-
-    //add
-    this.updateDepthParams()
     
-    viewer.addEventListener('camera_changed', (e)=>{
-        if(e.viewport.name != 'mapViewport') this.updateDepthParams(e) 
-    })   
-
+    
+    
     let setSize = (e)=>{ 
         let viewport = e.viewport
         let viewportOffset = viewport.offset || new Vector2() 
@@ -585,18 +588,31 @@ var LineMaterial = function ( parameters ) {
 
 
     viewer.addEventListener('resize',(e)=>{
-        if(!e.viewport || e.viewport.name != 'mapViewport'){
+        //if(!e.viewport || e.viewport.name != 'mapViewport'){
             setSize(e)
             //console.log(this.name +  viewportOffset.toArray())     
-        } 
+        //} 
     })  
+
     
     
-    /* viewer.addEventListener("render.begin", (e)=>{//before render  如果有大于两个viewport的话可能要
-        if(e.viewport.name != 'mapViewport') this.updateDepthParams({camera:e.viewport.camera})
-    }) */
+    if(this.supportExtDepth){
+     
+        //add
+        this.updateDepthParams()
+        
+        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})
+        }) */
 
+    }
 
 
 

+ 102 - 29
note笔记笔记笔记.txt

@@ -69,7 +69,7 @@ setView 旋转改成4dkk那种
 
 是否可以监听到场景的变化,变化了才渲染。要监听所有材质变化、object改变。
 
-
+moveSpeed 、 地图的自适应缩放
 ---------
 Bug	|
 ---------
@@ -88,21 +88,10 @@ Bug	|
   
 
 空间模型 这里要显示的是自定义的平面图,但是如果没有自定义的,应该是不显示这个选项的
-
- 
  
-
 地图坐标矫正??
-
  
-
-
-
-
-
  
-
-测量线点有时出来的很慢
 截图的等待全景图加载的地方写全  现在暂时用的延时
  
 
@@ -122,60 +111,144 @@ Bug	|
 分享的测量线地图上的端点大小有时大有时小 偶现
  
   
-四个屏时会不停调整size opacity
+
 
 ----
 
-春节过后改的or下周:
+ 
+ 
+ 
+
+ 
+
+导航距离很短时,只得到一个点时,地图上的箭头好像偏离了起点终点?  
+ 
+
+我发现navvis的只要一进测量,细节程度自动变为8.退出后也不还原。(故放大镜里不稀疏) 
+ macbook触摸板的也没有检查。 还不知道navvis的表现如何
 
-显示mini视角 - 地图opacity变为0 获取个事件 使关闭渲染。
+ 
 
-漫游飞行的时候增加点云pointBudget, 或者创建少量的鳞片矩形(但非朝向相机,而是使用normal)
 
+试了下双指同时平移和缩放,结果太难了,做不到。但是三个指头平移可以。四指转三指为何漂移
 
+ 
+ 
+我的se打开是空白的!!连调试都不行。不过navvis也是空白
 
+ 
+检查四倍放大的闪退。手机
 
 
 
 
-导航距离很短时,只得到一个点时,地图上的箭头好像偏离了起点终点?  
-导航地图上的margin再检查下 似乎没问题
 
-我发现navvis的只要一进测量,细节程度自动变为8.退出后也不还原。(故放大镜里不稀疏) 
 
 
+ 
+click是否要判断时间,如果按下到抬起时间过长不算click,navvis就是
 
-触屏的设备还不支持。macbook触摸板的也没有检查。 还不知道navvis的表现如何
 
-根据鼠标所在位置来放大。 触屏时根据双指位置来缩放(缩放就是定点平移),全景图也要放大
 
+为什么有的mesh位置不准确,当前这个场景地面抬高了。
+很多碎片。
+
+
+
+
+
+好像还是会点着点着就不能测量了。  
+另外右侧为何还是禁止的reticule
+
+
+测量截图的无法loading贴图结束了   未加载
 
-试了下双指同时平移和缩放,结果太难了,做不到。但是三个指头平移可以。四指转三指为何漂移
 
  
- 
-我的se打开是空白的!!连调试都不行。不过navvis也是空白
 
 
 
 
+关于测量线截图1024时常get不到的情况:(奇怪为什么之前不会这样?)
+原因: uploadTile中,如果某个tile的子集(如1024的子集是四个2048)已经加载好了,那么该tile就不会触发加载,也就不会发送加载成功的消息。
+所以最好还是只请求加载512.除非首次加载就请求高分辨率。(是不是我写漏了啥?因为4dkk 飞进去不会)
 
 
-检查四倍放大的闪退。手机
+在map中reticule变为禁止后,再回到场景里点击,恢复成非禁止会延迟。可能因为click完才会恢复??
+另外地图上reticule变化透明度时没有更新
+
+
+
+
+手机测量线的遮挡失效 和 useEdl一样 EXT_frag_depth不可用
+
+
+
+
+
+
+
+
+关于iphone离开网页一段时间后再回来,重启(or显示内存不足)的bug: 
+	·t-6UoYGXbWhi 这个场景(最不容易崩溃 只有一个pano)的无此问题
+	·隧道。。第一次测会,第二次就不会了奇怪。。。(但有时候打开是报网络错误)
+
+	·我的手机是可能白屏(清除缓存后不会了)
+	·微信会(可能是应用问题,因为应用也容易关闭)	
+
 
 
 
 
+	
+关于 丽篮电脑和我的手机t-FhDWmV5xur场景在海拔模式下 某个漫游点刚进入场景全景图有一面(立方体中的一面)亮度超高的bug:
+·只有带了token才会 或许是因为token占用了什么时间?
+	https://uat-laser.4dkankan.com/uat/index.html?m=t-FhDWmV5xur&lang=zh&token=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxODgxOTI3MjIwOCIsInVzZXJOYW1lIjoiMTg4MTkyNzIyMDgiLCJpYXQiOjE2NDU3NTI0MzYsImp0aSI6IjYwYTJiYjlhLTIyN2MtNGVhMi1iNWFkLWZhODIwMDk3ZDU3MSJ9.mlUUeIyPVYLGqeLGuu_gZzkDwotpgb_704BNe2kPlPY#/
+	开头多了DevTools 无法加载来源映射:无法加载 webpack:///spug/spug_api/repos/29_1660_20220224180315/node_modules/mitt/dist/mitt.mjs.map 的内容:HTTP 错误:状态代码 404,net::ERR_UNKNOWN_URL_SCHEME 等打印
+·发现此场景的部分漫游点的id和originID不一致。 且原4dkk场景漫游点id从0-24(但少一个18), 而此激光场景缺少了originId为0 的点。	
+对应: 
+	id     originID
+	 0  --  19  (多了一个19,正确应该是0。故而贴图错误)
+ 	18  --  19  (对的)
+ 	19  --  20
+ 	20  --  21
+ 	21  --  22
+ 	22  --  23
+ 	23  --  24
+刷新id又正常了???
+手机上看不发白了(电量原因吗) 手动改data[0].file_id = '00019' 也不发白
+手机加了test就可以,不加就会有问题。 
+我发现和海拔没有关系,只和透明度有关系。只要透明度不是1,刷新就会这样(所以之前的海拔是错误信息,为什么我没自己验证一下呜呜)
 
-为了适应触屏,测量估计要改成和navvis一样,没完成前不闭合,点击到开始点时才闭合。
-否则移动端得加一个结束按钮
 
 
 
 
-测量时的拖拽画面
 
 
-getScaleForConstantSize 使用resolution吧,否则手机会变小。
 
+
+ 
+有时候加载全景图一直loading。 
+
+·六张512的有一张未打印出加载成功(但实际在网络里查看是加载了的,tileDownloader也有值),然后就去加载更高分辨率去了,没发送成功。
+·没通知成功的原因是uploadTile那张512时已经加载好了子集1024,就跳过了。
+·原来是预加载的dir写错了。但是只是预加载的话大概率不会发生此bug而已。这依旧是个漏洞。
+
+
+ 试试1024加载 {basePanoSize:1024}
+
+
+
+
+ 
+
+
+
+
+
+
+
+为什么pano的label被marker遮住
+ 
  

+ 9 - 0
src/Features.js

@@ -67,6 +67,15 @@ export const Features = (function () {
 			}
 
 		},
+        //add:
+        EXT_DEPTH:{
+            isSupported: function () {
+                return gl.getExtension('EXT_frag_depth');
+            }
+        },
+        
+         
+        
 		//WEBGL2: {
 		//	isSupported: function(){
 		//		return gl instanceof WebGL2RenderingContext;

+ 7 - 1
src/LRU.js

@@ -147,7 +147,13 @@ class LRU{
 		} */ 
         
         //改成navvis的,使用pointBudget,否则四屏点云闪烁。
-        for (; this.numPoints > viewer.viewports.length * 2 * Potree.pointBudget;  ) {//要根据屏幕数量来增加pointBudget
+        
+        
+        let max = /* this.pageVisible ?  */viewer.viewports.length * 2 * Potree.pointBudget// : 1000
+        
+        
+        
+        for (; this.numPoints > max;  ) {//要根据屏幕数量来增加pointBudget
             var node = this.getLRUItem();
             node && this.disposeSubtree(node)
         }

+ 652 - 5
src/PointCloudOctree.js

@@ -4,7 +4,37 @@ import {PointCloudTree, PointCloudTreeNode} from "./PointCloudTree.js";
 import {PointCloudOctreeGeometryNode} from "./PointCloudOctreeGeometry.js";
 import {Utils} from "./utils.js";
 import {PointCloudMaterial} from "./materials/PointCloudMaterial.js";
+import math from "./utils/math.js";
 
+import {MeshDraw} from "./utils/DrawUtil.js";
+import searchRings from "./utils/searchRings.js";
+import {TextSprite} from './TextSprite'
+
+
+
+
+const planeGeo = new THREE.PlaneBufferGeometry(1,1);
+ 
+
+const planeMats = new Map()
+
+let getPlaneMat = (group, removed)=>{
+    let mat = planeMats.get(group)
+    if(mat)return mat
+   
+   
+    var planeMat = new THREE.MeshBasicMaterial({
+        //color:  level == 'removed' ?  "#f00" : new THREE.Color(1 - level*0.2,  1,1),
+        color: (new THREE.Color()).setHSL(Math.random(), 0.5, 0.9) ,
+        //color: (new THREE.Color()).setHSL(removed ? 0 : 0.6, Math.random(), 0.9/* Math.random() */) ,
+        
+        transparent:true,
+        side:2,
+        opacity: removed  ? 0.3 : 0.9,
+    })
+    planeMats.set(group, planeMat)  
+    return planeMat
+}
 
 export class PointCloudOctreeNode extends PointCloudTreeNode {
 	constructor () {
@@ -236,7 +266,7 @@ export class PointCloudOctree extends PointCloudTree {
 		// if(geometryNode.name === "r40206"){
 		//	console.log("creating node for r40206");
 		// }
-		let sceneNode = new THREE.Points(geometryNode.geometry, this.material);
+		let sceneNode = new THREE.Points(geometryNode.geometry, this.material);  //好像没什么用
 		sceneNode.name = geometryNode.name;
 		sceneNode.position.copy(geometryNode.boundingBox.min);
 		sceneNode.frustumCulled = false;
@@ -303,8 +333,597 @@ export class PointCloudOctree extends PointCloudTree {
 		};
 		geometryNode.oneTimeDisposeHandlers.push(disposeListener);
 
+        
+        //this.buildTexMesh(geometryNode,sceneNode)
+
+
+
 		return node;
 	}
+    
+    
+    
+    
+    
+    buildTexMesh(geometryNode,sceneNode){
+         
+        //  viewer.scene.pointclouds.forEach(a=>a.areaPlanes.forEach(e=>e.material = viewer.images360.cube.material))  
+       
+        let startTime = Date.now()
+        
+            
+        if(!this.splitSprites){
+            let splitSprites = new THREE.Object3D
+            splitSprites.name = 'splitSprites_'+this.name 
+            splitSprites.matrixAutoUpdate = false  //同pointcloud一样不自动更新,直接使用
+            splitSprites.matrix.copy(this.matrix)
+            splitSprites.matrixWorld.copy(this.matrixWorld)
+            this.splitSprites = splitSprites
+            viewer.scene.scene.add(splitSprites) 
+            
+            
+            this.areaPlanes = []
+        }
+          
+        
+        if(this.texMeshUseLevel == void 0 || geometryNode.level == this.texMeshUseLevel){//只需要某一层level的点
+            
+            //let spritesGeo = new THREE.BufferGeometry();
+          
+            let scaleRatio =  1.4 //稍微放大些,填满缝隙
+            let spriteWidth1 =  this.material.spacing  / Math.pow(2, geometryNode.level) 
+            if(spriteWidth1 > 3)return
+            let spriteWidth = spriteWidth1 * scaleRatio  
+            
+            if(this.texMeshUseLevel == void 0 ){
+                this.texMeshUseLevel = geometryNode.level
+                console.log('texMeshUseLevel ',geometryNode.level)
+            }
+            
+            
+            let splitSprites = new THREE.Object3D
+            splitSprites.name = 'sub_splitSprites_'+geometryNode.name
+            splitSprites.position.copy(sceneNode.position)
+            splitSprites.rotation.copy(sceneNode.rotation)
+            this.splitSprites.add(splitSprites)
+            
+            
+             
+            
+            let geometry = geometryNode.geometry
+            let count = geometry.attributes.position.count
+            
+            
+            let end = Math.min(count, 850)
+            let start = Math.min(0, end) 
+            
+             
+            console.warn('check points count:', end-start)
+            
+            let position = geometry.attributes.position.array
+            let normal = geometry.attributes.normal.array
+            let i
+            let up = new THREE.Vector3(0,1,0) , zeroVec = new THREE.Vector3 //up写成z向上居然结果一样
+            
+            let positions = [];
+            let normals = [];
+            let newPositions = [];
+            let newIndices = []
+            let groupMaxPointCount = 2000 ;//太多找环会崩
+            
+            let minDisSquare =  Math.pow(spriteWidth1 * 1.8 , 2 ) //这个数太小就连不上啦 1.65太小
+            let minDot = Math.cos(THREE.Math.degToRad(10))//括号内是最小偏差角度, 20太大。太大的话会将立方体的相邻两面视为一个面。
+            
+            //根据相邻点位置和角度是否相近来分组。有风险:两大区域可能因为一个模棱两可中间点连接在一起。
+            
+            let closeGroups = []
+            let groupTolerateMaxPoint = 4//组内点<=这个数的最后会被删除
+            let removedCount = 0
+            let useGroupCount = 0
+            let pointDebug = true
+             
+            
+            for(i=start;i<end;i++){
+                let pos = new THREE.Vector3(position[3*i], position[3*i+1], position[3*i+2] );
+                let nor = new THREE.Vector3(normal[3*i],normal[3*i+1],normal[3*i+2]);
+                pos.nor = nor
+                pos.index = i
+                positions.push(pos)
+                normals.push(nor)
+                
+               
+                    let groups = closeGroups.filter(group=>{ 
+                        if(group.length>groupMaxPointCount)return //满员了
+                        var hasClosed = group.some(p=>{ 
+                            var dis = p.distanceToSquared(pos)
+                            var dot = p.nor.dot(nor)
+                            if(dis<minDisSquare && dot>minDot){
+                                //return   dis / minDisSquare + (Math.abs(p.nor.x - nor.x) + Math.abs(p.nor.y - nor.y) + Math.abs(p.nor.z - nor.z)) < 1.7
+                                return   dis / minDisSquare - p.nor.dot(nor) < 0
+                            }      
+                        })
+                        return hasClosed
+                    })
+                    
+                    if(groups.length == 0){//创建一个新的
+                        var newGroup = []
+                        closeGroups.push(newGroup)
+                        groups = [newGroup]
+                    }
+                    
+                    if(groups.length == 1){//直接加入原有的 
+                        pos.belongTo = groups[0]; 
+                    }else if(groups.length>1){ // comebine多个组成一个  
+                        let newBigGroup = [];
+                        groups.forEach(e=>{
+                            newBigGroup.push(...e)
+                            let index = closeGroups.indexOf(e);
+                            closeGroups.splice(index, 1)
+                        })
+                        closeGroups.push(newBigGroup)
+                        pos.belongTo = newBigGroup
+                        newBigGroup.forEach(e=>{e.belongTo = newBigGroup})   
+                    } 
+
+                    pos.belongTo.push(pos)                   
+                
+            }    
+             
+            
+            
+            closeGroups.forEach((points,index)=>{//建造面 
+                if(points.length <= groupTolerateMaxPoint ){
+                    
+                    
+                    /* let sprite = new THREE.Mesh(planeGeo, getPlaneMat(pos.belongTo, true))
+                        sprite.lookAt(nor);
+                        sprite.position.copy(pos)
+                        sprite.scale.set(spriteWidth,spriteWidth,spriteWidth)
+                        sprite.name = geometryNode.name+'_index'+i
+                        splitSprites.add(sprite)
+                    removedCount ++; */
+                    
+                    
+                    removedCount += points.length;
+                    return
+                }
+                useGroupCount ++
+                
+                points.sort(function(a,b){ 
+                    return a.index - b.index
+                })
+              
+                console.log(`开始解析 ${geometryNode.name} - 第${index}组,总第${points[0].index}个点,组内有${points.length}个点`)
+                
+                let planeMat = getPlaneMat(points, true)
+                
+                
+                if(pointDebug){
+                    points.forEach((p,i)=>{
+                        var label = new TextSprite({ 
+                           text : index+"-"+i+" ("+p.index+")"+geometryNode.name, dontFixOrient:true,
+                           backgroundColor: {r: planeMat.color.r*255, g: planeMat.color.g*255, b: planeMat.color.b*255, a:0.6},
+                        });
+                        label.lookAt(p.nor);
+                        label.position.copy(p)
+                        label.scale.set(spriteWidth/3, spriteWidth/3, spriteWidth/3)
+                        splitSprites.add(label) 
+                        
+                        /* let sprite = new THREE.Mesh(planeGeo,planeMat)
+                        sprite.lookAt(p.nor);
+                        sprite.position.copy(p)
+                        sprite.scale.set(spriteWidth/3,spriteWidth/3,spriteWidth/3)
+                        sprite.name = geometryNode.name+'_group'+index+"_"+ i
+                        splitSprites.add(sprite) */
+                    })
+                
+                }
+                    
+                    
+                
+                var avePos = points.reduce(function(total, currentValue){
+                    return total.add(currentValue)
+                }, new THREE.Vector3).multiplyScalar(1/points.length)
+                
+                
+               
+                let planeNormals = []
+               
+                
+                
+                {//获得planeNormals
+                    //随机找两个距离远的点算normal。 按距离排序后, //抽取若干个点,然后算两两之间的法线,其中距离远的多抽取几个。
+                    var sortPoints = points.slice(0).sort(function(a,b){ 
+                        return a.distanceToSquared(avePos) - b.distanceToSquared(avePos)
+                    })//从小到大
+                    var pickPoints 
+                    
+                    var length = sortPoints.length
+                    if(length>=7){
+                        var ratio = [0.02,0.15,0.4,0.55,0.7,0.86,0.99];
+                        var index = ratio.map(e=>Math.round(e * (length-1)))
+                        //console.log('index ',index)
+                        pickPoints = index.map(e=>sortPoints[e])
+                    }else{
+                        pickPoints = sortPoints
+                    }
+                    //console.log('pickPoints', pickPoints)
+                    let num = pickPoints.length
+                    
+                    for(let i=0;i<num;i++){//任意一个三角形能算出一个normal 
+                        for(let j=i+1;j<num;j++){
+                            for(let u=j+1;u<num;u++){
+                                var p1 = pickPoints[i]
+                                var p2 = pickPoints[j]
+                                var p3 = pickPoints[u]
+                                    
+                                let vec1 = new THREE.Vector3().subVectors(p1,p3)
+                                let vec2 = new THREE.Vector3().subVectors(p2,p3)
+                                let nor = vec1.cross(vec2).normalize()
+                                 
+                                if(planeNormals[0]){
+                                    if(nor.dot(planeNormals[0])<0)nor.negate()  //反向下
+                                }
+                                //console.log('nor',nor)
+                                planeNormals.push(nor)
+                                
+                            }
+                        }
+                    } 
+                    
+                }
+                
+                 
+                
+                
+                var aveNor = planeNormals.reduce(function(total, currentValue){
+                    return total.add(currentValue)
+                }, new THREE.Vector3).normalize() 
+                
+                console.log('aveNor',aveNor, 'avePos' ,avePos)
+                {
+                    var label = new TextSprite({ 
+                        //index+"-"+i+" ("+p.index+")"+geometryNode.name
+                    
+                       text : `我是${index}组  ${geometryNode.name} 中心点`, dontFixOrient:true,
+                       backgroundColor: {r: planeMat.color.r*255, g: planeMat.color.g*255, b: planeMat.color.b*255, a:0.6},
+                    });
+                    label.lookAt(aveNor);
+                    label.position.copy(avePos)
+                    label.scale.set(spriteWidth, spriteWidth, spriteWidth)                 
+                    splitSprites.add(label) 
+                }
+                
+                var facePlane = new THREE.Plane().setFromNormalAndCoplanarPoint(aveNor, avePos )
+                
+                var coplanarPoints = points.map(p=> facePlane.projectPoint(p, new THREE.Vector3() ))
+                 
+                
+                
+                var originPoint0 = coplanarPoints[0].clone() 
+                var qua = math.getQuaBetween2Vector(facePlane.normal, new THREE.Vector3(0,0,1), new THREE.Vector3(0,0,1));
+                let points2d = coplanarPoints.map(e=>e.clone().applyQuaternion(qua)) 
+                let quaInverse = qua.clone().invert() 
+                    
+                //--------------------   
+                    
+                let lines = []
+                
+                points2d.forEach((p,j)=>{
+                    p.id = j
+                    for(let i=0;i<j;i++){
+                        if(p.distanceToSquared(points2d[i])<minDisSquare){
+                            lines.push({p1:i,p2:j})
+                        }
+                    }  
+                })  
+                     
+                console.log('points count:',points2d.length,  'lines:',lines)
+                var rings = searchRings({
+                    points:points2d,
+                    lines, 
+                    onlyGetOutRing:true,
+                    precision: Math.max(spriteWidth1/10, 0.01)
+                })    
+                console.log( 'rings:', rings )//mesh间可能重叠 但换上贴图材质应该看不出(但只要searchRings时getSliceLines就不会重叠)
+                if(!rings)return
+                let planeMat2 = planeMat.clone(); planeMat2.opacity = 0.5; 
+                var firstPos =  points2d[0].clone()
+                    firstPos.z = 0                  //因为shape只读取了xy,所以位移下, 再算出最终位置,得到差距
+                    firstPos.applyQuaternion(quaInverse)      
+                var vec = originPoint0.clone().sub(firstPos)   
+                
+                rings.forEach(ring=>{
+                    var shapeGeo = MeshDraw.getShapeGeo(ring.points)
+                    var areaPlane = new THREE.Mesh(shapeGeo, planeMat2)  
+                    
+                    
+                    areaPlane.quaternion.copy(quaInverse) 
+                    areaPlane.position.copy(vec)       
+                    areaPlane.name = 'areaPlane_'+index
+                    splitSprites.add(areaPlane)
+                    this.areaPlanes.push(areaPlane)
+                })
+                
+                
+                 
+            }) 
+            console.log(geometryNode.name, '中:')
+            console.log('removed point count: ', removedCount/* splitSprites.children.length */)
+            console.log(closeGroups) 
+            console.log('comebine mesh Len:', useGroupCount)
+            
+            
+            /* 
+            spritesGeo.setAttribute('position', new THREE.Float32BufferAttribute(new Float32Array(newPositions), 3));
+            spritesGeo.setIndex( newIndices );
+            
+            
+            
+            let sprites = new THREE.Mesh(spritesGeo, getPlaneMat('use'))
+            sprites.name = geometryNode.name 
+            sprites.position.copy(sceneNode.position)
+            sprites.rotation.copy(sceneNode.rotation)
+             
+            sceneNode.sprites = sprites
+            sprites.pointsNode = sceneNode
+            
+            if(geometryNode.level == 0){
+                let root = new THREE.Object3D;
+                root.name = 'spriteNodeRoot'
+                 
+                
+                root.matrixAutoUpdate = false  //同pointcloud一样不自动更新,直接使用
+                root.matrix.copy(this.matrix)
+                root.matrixWorld.copy(this.matrixWorld)
+                viewer.scene.scene.add(root)  
+                this.spriteNodeRoot = root
+            } 
+            this.spriteNodeRoot.add(sprites)  */
+              
+            console.log('computeTime: ' + (Date.now() - startTime)) 
+        }  
+       
+        
+        
+        
+        
+        //-----------以下作废======================-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+        
+        
+        
+        
+        
+        
+        
+        if(geometryNode.level <= -1){ 
+            let startTime = Date.now()
+            let splitSprites = new THREE.Object3D
+            splitSprites.name = 'splitSprites_'+geometryNode.name
+            splitSprites.matrixAutoUpdate = false  //同pointcloud一样不自动更新,直接使用
+            splitSprites.matrix.copy(this.matrix)
+            splitSprites.matrixWorld.copy(this.matrixWorld)
+            viewer.scene.scene.add(splitSprites) 
+            
+            
+            let spritesGeo = new THREE.BufferGeometry();
+          
+            let scaleRatio =  1.4 //稍微放大些,填满缝隙
+            let spriteWidth1 =  this.material.spacing  / Math.pow(2, geometryNode.level)
+            let spriteWidth = spriteWidth1 * scaleRatio 
+            console.log('spriteWidth:',spriteWidth)
+            
+            
+            
+            const removeChip = true
+            
+            
+            let geometry = geometryNode.geometry
+            let count = geometry.attributes.position.count
+            
+            count = 1000
+            
+            
+            let position = geometry.attributes.position.array
+            let normal = geometry.attributes.normal.array
+            let i
+            let up = new THREE.Vector3(0,1,0) , zeroVec = new THREE.Vector3 //up写成z向上居然结果一样
+            
+            let positions = [];
+            let normals = [];
+            let newPositions = [];
+            //let newNormals = [];
+            let newIndices = []
+            let cornerPoints = [new THREE.Vector3(-1,1,0),new THREE.Vector3(1,1,0),new THREE.Vector3(-1,-1,0),new THREE.Vector3(1,-1,0) ] 
+            let indices = [0, 2, 1, 2, 3, 1] 
+            cornerPoints.forEach(e=>e.multiplyScalar(spriteWidth/2))
+            
+            
+            
+            let minDisSquare =  spriteWidth1 * spriteWidth1 * 1.5 
+       
+            
+            let closeGroups = []
+            let groupTolerateMaxPoint = 4//组内点<=这个数的最后会被删除
+            let removedCount = 0
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            for(i=0;i<count;i++){
+                let pos = new THREE.Vector3(position[3*i], position[3*i+1], position[3*i+2] );
+                let nor = new THREE.Vector3(normal[3*i],normal[3*i+1],normal[3*i+2]);
+                pos.nor = nor
+                positions.push(pos)
+                normals.push(nor)
+                
+                if(removeChip){ 
+                    let groups = closeGroups.filter(group=>{
+                        var hasClosed = group.some(p=>{
+                            var dis = p.distanceToSquared(pos) 
+                            if(dis<minDisSquare){
+                                //return   dis / minDisSquare + (Math.abs(p.nor.x - nor.x) + Math.abs(p.nor.y - nor.y) + Math.abs(p.nor.z - nor.z)) < 1.7
+                                return   dis / minDisSquare - p.nor.dot(nor) < 0
+                            
+                            
+                            }      
+                        })
+                        return hasClosed
+                    })
+                    
+                    if(groups.length == 0){//创建一个新的
+                        var newGroup = []
+                        closeGroups.push(newGroup)
+                        groups = [newGroup]
+                    }
+                    
+                    if(groups.length == 1){//直接加入原有的 
+                        pos.belongTo = groups[0]; 
+                    }else if(groups.length>1){ // comebine多个组成一个  
+                        let newBigGroup = [];
+                        groups.forEach(e=>{
+                            newBigGroup.push(...e)
+                            let index = closeGroups.indexOf(e);
+                            closeGroups.splice(index, 1)
+                        })
+                        closeGroups.push(newBigGroup)
+                        pos.belongTo = newBigGroup
+                        newBigGroup.forEach(e=>{e.belongTo = newBigGroup})   
+                    } 
+
+                    pos.belongTo.push(pos)                   
+                }
+                
+                
+                
+            }    
+            
+            for(i=0;i<count;i++){
+                let pos = positions[i]
+                let nor = normals[i]
+                 
+                    
+                if(removeChip){  
+                    if(pos.belongTo.length <= groupTolerateMaxPoint){
+                        
+                        let sprite = new THREE.Mesh(planeGeo, getPlaneMat(pos.belongTo, true))
+                            sprite.lookAt(nor);
+                            sprite.position.copy(pos)
+                            sprite.scale.set(spriteWidth,spriteWidth,spriteWidth)
+                            sprite.name = geometryNode.name+'_index'+i
+                            splitSprites.add(sprite)
+                        removedCount ++;
+                        
+                        continue
+                    }else{ 
+                       /*  
+                        let sprite = new THREE.Mesh(planeGeo, getPlaneMat(pos.belongTo))
+                            sprite.lookAt(nor);
+                            sprite.position.copy(pos)
+                            sprite.scale.set(spriteWidth/3,spriteWidth/3,spriteWidth/3)
+                            sprite.name = geometryNode.name+'_index'+i
+                            splitSprites.add(sprite)
+                         */
+                        
+                    }
+                }       
+                         
+                
+                
+                 let matrix = (new THREE.Matrix4).lookAt( nor, zeroVec, up);
+                matrix.elements[12] = pos.x
+                matrix.elements[13] = pos.y
+                matrix.elements[14] = pos.z
+                
+                
+                cornerPoints.forEach(p=>{
+                    let point = p.clone();
+                    point.applyMatrix4(matrix)
+                    
+                    newPositions.push(...point.toArray())
+                    //newNormals
+                })
+                
+                indices.forEach(index=>{
+                    newIndices.push(index + i*4)
+                })  
+                
+                
+                
+            }
+            
+            /* closeGroups.forEach(e=>{
+                if(e.length <= groupTolerateMaxPoint )return
+                
+                
+                
+            }) */
+            
+            console.log('removed count: ', removedCount/* splitSprites.children.length */)
+            console.log(closeGroups) 
+            console.log('computeTime: ' + (Date.now() - startTime))
+            
+            
+            
+            spritesGeo.setAttribute('position', new THREE.Float32BufferAttribute(new Float32Array(newPositions), 3));
+            spritesGeo.setIndex( newIndices );
+            
+            
+            
+            let sprites = new THREE.Mesh(spritesGeo, getPlaneMat('use'))
+            sprites.name = geometryNode.name 
+            sprites.position.copy(sceneNode.position)
+            sprites.rotation.copy(sceneNode.rotation)
+             
+            sceneNode.sprites = sprites
+            sprites.pointsNode = sceneNode
+            
+            if(geometryNode.level == 0){
+                let root = new THREE.Object3D;
+                root.name = 'spriteNodeRoot'
+                 
+                
+                root.matrixAutoUpdate = false  //同pointcloud一样不自动更新,直接使用
+                root.matrix.copy(this.matrix)
+                root.matrixWorld.copy(this.matrixWorld)
+                viewer.scene.scene.add(root)  
+                this.spriteNodeRoot = root
+            } 
+            this.spriteNodeRoot.add(sprites) 
+            viewer.setObjectLayers(sprites,'sceneObjects')
+             
+             
+        } 
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        //------------------
+        /*        
+
+            viewer.scene.pointclouds[0].spriteNodeRoot.traverse(e=>e.material && (e.material = viewer.images360.cube.material))
+            viewer.scene.scene.children[12].visible = false
+                 
+         */
+
+
+    }    
+    
+    
+    
 
 	updateVisibleBounds () {
 		let leafNodes = [];
@@ -1172,6 +1791,7 @@ export class PointCloudOctree extends PointCloudTree {
     
     // 设置点大小
     changePointSize(num) {
+        
         if (num == void 0) {
             num = this.temp.pointSize
         } else {
@@ -1193,7 +1813,7 @@ export class PointCloudOctree extends PointCloudTree {
         }
         
         
-        console.log('changePointSize  '  + this.dataset_id + '  , num : ' + num + ' , size : ' + this.material.size, this.material.spacing)
+        //console.log('changePointSize  '  + this.dataset_id + '  , num : ' + num + ' , size : ' + this.material.size, this.material.spacing)
 
          
     }  
@@ -1215,16 +1835,17 @@ export class PointCloudOctree extends PointCloudTree {
             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越高效果越弱,以减免过度重叠后的亮度。
+                let ratio = Math.min(1 / base, 1 / minBase / 3) //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
                 this.material.opacity = THREE.Math.clamp(base * ratio * num, 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 / 9) //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
+                let ratio = Math.min(1 / base, 1 / minBase / 6) //ratio为一个能使opacity不大于1 的 乘量,minBase要除以一个数,该数调越大减弱效果越强。level越低opacity和面板越接,level越高效果越弱,以减免过度重叠后的亮度。
                 this.material.opacity = THREE.Math.clamp(base * ratio * num, 0, 0.999) //到1就不透明了(可能出现一段一样)
+                
             }
-        
+            //缺点:防止颜色过亮主要是相机离远时,当在漫游点处由于离点云太近,可能会导致高质量点云看起来很暗。
         }
         //console.log('changePointOpacity ' + this.dataset_id + ', num : ' + num + ' , opacity : ' + this.material.opacity) //检查是否做到了低质量时num==opacity,中质量opacity稍小于num,高质量更小
          
@@ -1285,6 +1906,32 @@ export class PointCloudOctree extends PointCloudTree {
 
 
 
+window.searchOutRing = function(points){
+    var points = [{x:0,y:0},{x:1,y:1},{x:0,y:1},{x:1,y:0},{x:2,y:1},{x:1,y:2},{x:1,y:3},{x:2,y:3},
+        {x:3,y:1},{x:3,y:2},{x:0,y:2},{x:0,y:3},{x:2,y:0},{x:-1,y:0},{x:-1,y:1},{x:-2,y:1},{x:3,y:3},
+        {x:3,y:0},{x:2,y:-1},{x:0,y:-1},{x:1,y:0.5},{x:2,y:0.5}, ].map((e,index)=>{
+            var a = new THREE.Vector2().copy(e) 
+            a.id = index;
+            return a
+        })
+    var lines = []
+    var minDis = 2*2 
+    points.forEach((p,j)=>{
+        for(let i=0;i<j;i++){
+            if(p.distanceToSquared(points[i])<minDis){
+                lines.push({p1:i,p2:j})
+            }
+        }  
+    })  
+         
+      
+    searchRings({
+        points,
+        lines, 
+        onlyGetOutRing:true
+    })
+}
+
 
 
 

+ 1 - 0
src/PointCloudTree.js

@@ -42,6 +42,7 @@ export class PointCloudTreeNode extends EventDispatcher{
 export class PointCloudTree extends THREE.Object3D {
 	constructor () {
 		super();
+        //this.spriteGroup = new THREE.Object3D  //add
 	}
 
 	initialized () {

+ 47 - 6
src/PotreeRenderer.js

@@ -156,7 +156,7 @@ let attributeLocations = {
 class Shader {
 
 	constructor(gl, name, vsSource, fsSource) {
-		this.gl = gl;
+		this.gl = gl; 
 		this.name = name;
 		this.vsSource = vsSource;
 		this.fsSource = fsSource;
@@ -225,11 +225,18 @@ class Shader {
 
 			this.vs = gl.createShader(gl.VERTEX_SHADER);
 			this.fs = gl.createShader(gl.FRAGMENT_SHADER);
+            
+            
+            
+            
 			this.program = gl.createProgram();
             
             if(  !gl.isProgram(this.program  )){//创建失败  开启多个页面可能会,原因是webglcontextlost
                 //console.error('创建program失败');
                 viewer.emit('webglError', 'potreeRenderer创建program失败')
+                console.log(this.vs)
+                console.log(this.fs)
+                
                 return;
             }
 
@@ -553,7 +560,7 @@ export class Renderer {
 	constructor(threeRenderer) {
 		this.threeRenderer = threeRenderer;
 		this.gl = this.threeRenderer.getContext();
-
+  
 		this.buffers = new Map();
 		this.shaders = new Map();
 		this.textures = new Map();
@@ -1035,8 +1042,11 @@ export class Renderer {
 			}
 
 			let numPoints = webglBuffer.numElements;
-			gl.drawArrays(gl.POINTS, 0, numPoints);
-
+			 
+            gl.drawArrays(gl.POINTS, 0, numPoints); 
+            //gl.drawArrays(gl.TRIANGLES, 0, numPoints);
+            
+            
 			i++;
 		}
 
@@ -1047,6 +1057,10 @@ export class Renderer {
 			performance.measure("render.renderNodes", "renderNodes-start", "renderNodes-end");
 		}
 	}
+    
+    
+    
+    
 
 	renderOctree(octree, nodes, camera, target, params = {}){
 
@@ -1316,7 +1330,7 @@ export class Renderer {
 			}
 
 
-			shader.setUniform1f("size", material.usePanoMap ? Potree.config.material.absolutePanoramaSize : material.size);//usePanoMap时控制在不大不小的范围内感觉较好,考虑到有的点云稀疏,用大一点的点
+			shader.setUniform1f("size", material.usePanoMap ? Potree.config.material.absolutePanoramaSize * window.devicePixelRatio : material.size);//usePanoMap时控制在不大不小的范围内感觉较好,考虑到有的点云稀疏,用大一点的点
 			shader.setUniform1f("maxSize", material.uniforms.maxSize.value);
 			shader.setUniform1f("minSize", material.uniforms.minSize.value);
 
@@ -1512,10 +1526,37 @@ export class Renderer {
 		gl.activeTexture(gl.TEXTURE2);
 		gl.bindTexture(gl.TEXTURE_2D, null);
 		gl.activeTexture(gl.TEXTURE0);
+        
+        
+        
+        
+        
+        
+        
+        
+        //add  恢复为不透明(否则renderToCubeMap时的贴图会被渲染成高亮的颜色)
+        gl.disable(gl.BLEND);
+        gl.depthMask(true);
+        gl.enable(gl.DEPTH_TEST);
+            //DEPTH_TEST等需要恢复吗
+         
+        
 	}
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
 
-	render(scene, camera, target = null, params = {}) {
 
+	render(scene, camera, target = null, params = {}) {
+ 
 		const gl = this.gl;
 
 		// PREPARE 

+ 1 - 0
src/Potree_update_visibility.js

@@ -324,6 +324,7 @@ export function updateVisibility(pointclouds, camera, areaSize){
 				node.sceneNode.updateMatrix();
 				node.sceneNode.matrixWorld.multiplyMatrices(pointcloud.matrixWorld, node.sceneNode.matrix);	
 				node._transformVersion = transformVersion.number;
+                               
 			}
 
 			if (pointcloud.showBoundingBox && !node.boundingBoxNode && node.getBoundingBox) {

+ 2 - 2
src/TextSprite.js

@@ -23,8 +23,8 @@ export class TextSprite extends THREE.Object3D{
             renderOrder:options.renderOrder,
             useDepth: options.useDepth,
             map,
-            root: this     
-          
+            root: this ,    
+            dontFixOrient: options.dontFixOrient
         })
         this.add(this.sprite)
         

+ 16 - 0
src/loader/BinaryLoader.js

@@ -4,6 +4,9 @@ import * as THREE from "../../libs/three.js/build/three.module.js";
 import {Version} from "../Version.js";
 import {XHRFactory} from "../XHRFactory.js";
 
+
+
+
 //加载 解析点云
 export class BinaryLoader{
 
@@ -133,7 +136,20 @@ export class BinaryLoader{
 			node.loading = false;
 			node.estimatedSpacing = data.estimatedSpacing;
 			Potree.numNodesLoading--;
+            
+            
+            
+             
+            
+            
+            
+            
+            
+            
+            
 		};
+ 
+
 
 		let message = {
 			buffer: buffer,

+ 20 - 17
src/materials/DepthBasicMaterial.js

@@ -1,7 +1,7 @@
 
 import * as THREE from "../../libs/three.js/build/three.module.js";
 import {Shaders} from "../../build/shaders/shaders.js";
-
+import {Features} from "../Features.js";
 
  
 export default class DepthBasicMaterial extends THREE.ShaderMaterial{
@@ -23,7 +23,7 @@ export default class DepthBasicMaterial extends THREE.ShaderMaterial{
         let defines = {};
         if(o.useDepth)defines.useDepth = ''
         if(o.map)defines.use_map = ''
-        
+         
         super({ 
             uniforms,
             vertexShader: Shaders['depthBasic.vs'],   
@@ -37,8 +37,7 @@ export default class DepthBasicMaterial extends THREE.ShaderMaterial{
         
         if(o.useDepth) this.useDepth_ = true
         
-         
-         
+        
         let setSize = (e)=>{//如果出现横条状的异常,往往是viewportOffset出错 
             let viewport = e.viewport
             let viewportOffset = viewport.offset || new THREE.Vector2() 
@@ -49,7 +48,7 @@ export default class DepthBasicMaterial extends THREE.ShaderMaterial{
         }
         
         let viewport = viewer.mainViewport;
-         
+             
         setSize( {viewport} )
         
         viewer.addEventListener('resize',(e)=>{
@@ -58,18 +57,22 @@ export default class DepthBasicMaterial extends THREE.ShaderMaterial{
                 //console.log(this.name +  viewportOffset.toArray())     
             } 
         })  
-        
-        
-        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})
-        }) */
+        if(Features.EXT_DEPTH.isSupported()){  
+            
+            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})
+            }) */
+            
+            this.updateDepthParams()
+        }
+        
         
-        this.updateDepthParams()
         //点云变化时要一直触发updateDepthParams??
         //viewer.once("render.pass.end",this.updateDepthParams.bind(this))
     }
@@ -80,9 +83,9 @@ export default class DepthBasicMaterial extends THREE.ShaderMaterial{
             this.uniforms.depthTexture.value = viewer.getPRenderer().rtEDL.depthTexture   //其实只赋值一次就行
             this.uniforms.nearPlane.value = camera.near;
             this.uniforms.farPlane.value = camera.far;
-             
+            
         }            
-    }
+    } 
     set map(map){
         this.uniforms.map.value = map; 
     }
@@ -91,7 +94,7 @@ export default class DepthBasicMaterial extends THREE.ShaderMaterial{
         return this.useDepth_
     }
     
-    set useDepth(value){
+    set useDepth(value){//如果不支持 EXT_DEPTH 的话会失效
         if(this.useDepth_ != value){
             if(value){
                 this.defines.useDepth = ''

+ 2 - 2
src/materials/PointCloudMaterial.js

@@ -5,7 +5,7 @@ import {Gradients} from "./Gradients.js";
 import {Shaders} from "../../build/shaders/shaders.js";
 import {ClassificationScheme} from "./ClassificationScheme.js";
 import {PointSizeType, PointShape, TreeType, ElevationGradientRepeat} from "../defines.js";
-
+import {Features} from "../Features.js";
 //
 // how to calculate the radius of a projected sphere in screen space
 // http://stackoverflow.com/questions/21648630/radius-of-projected-sphere-in-screen-space
@@ -281,7 +281,7 @@ export class PointCloudMaterial extends THREE.RawShaderMaterial {
 			defines.push('#define adaptive_point_size');
 		}
         
-        if(!viewer.supportExtFragDepth && this.shape === PointShape.PARABOLOID){
+        if(!Features.EXT_DEPTH.isSupported() && this.shape === PointShape.PARABOLOID){
             this.shape = PointShape.SQUARE ;//强行替换
         }
         

+ 36 - 19
src/modules/Images360/Images360.js

@@ -133,7 +133,7 @@ export class Images360 extends EventDispatcher{
 
         let click = (e) => {//不用"mouseup" 是因为 mouseup有drag object时也会触发
             if(Potree.settings.unableNavigate || this.flying  || !e.isTouch && e.button != THREE.MOUSE.LEFT || e.hoverViewport != viewer.mainViewport )return //
-            
+             
             /* if(currentlyHovered && currentlyHovered.pano){
 				this.focusPano(currentlyHovered.pano);
 			}else{//add */
@@ -570,7 +570,7 @@ export class Images360 extends EventDispatcher{
         var pano = toPano.pano 
         
         
-        var duration = toPano.duration == void 0 ? (300+Math.min(Potree.config.transitionsTime.flySpeed * this.position.distanceTo(pano.position),  Potree.config.transitionsTime.panoToPano )) : toPano.duration 
+        var duration = toPano.duration == void 0 ? (300+Math.min(Potree.config.transitionsTime.flyTime * this.position.distanceTo(pano.position),  Potree.config.transitionsTime.panoToPano )) : toPano.duration 
         
         //console.warn("flyto "+pano.id + ' duration: ' + duration )     
         
@@ -1017,7 +1017,14 @@ export class Images360 extends EventDispatcher{
         })
         //return vectorForwards[0].direction
         
-        return vectorForwards
+         
+        
+        return {
+            datasetsLocal: vectorForwards,
+            vectorForward
+        }
+        
+        
     }
     
     
@@ -1107,10 +1114,13 @@ export class Images360 extends EventDispatcher{
             
         
             
-            var fov = {//test for direction  预加载的边缘有一丢丢不准确,尤其在相机倾斜时(4dkk也是)。
+            /* var fov = {//test for direction  预加载的边缘有一丢丢不准确,尤其在相机倾斜时(4dkk也是)。
                 hFov: cameraLight.getHFOVForCamera(viewer.scene.getActiveCamera()  ),
 				vFov: viewer.scene.getActiveCamera().fov
-            }//原先是null,不要求方向
+            }//原先是null,不要求方向 */
+            var fov = null  //若不为null的话,因为可能可见范围的tile下载过了从而无法触发下载,然后得不到下载成功的消息,怎么办
+            
+            
             
             pano.loadTiledPano(/* 1024  */ basePanoSize  , vectorForward, fov, isclear, l, null).done(function(e, t) {
                     callback1 && callback1(e, t)
@@ -1386,10 +1396,13 @@ export class Images360 extends EventDispatcher{
                         
                         tile.material.opacity = 0.4;
                         tile.material.transparent = true 
-                        var colorHue = Math.random();
-                        tile.material.color = (new THREE.Color()).setHSL(colorHue, 0.5, 0.9)  
                         
                         
+                        if(Potree.settings.isTest){
+                            var colorHue = Math.random();
+                            tile.material.color = (new THREE.Color()).setHSL(colorHue, 0.5, 0.9)  
+                        }
+                        
                         tile.visible = false 
                         face.add(tile)
                     }
@@ -1464,7 +1477,7 @@ export class Images360 extends EventDispatcher{
     resetHighMap(){ 
     
         if(!this.highMapCube)   return 
-        console.warn('resetHighMap')
+        //console.warn('resetHighMap')
         this.highMapCube.children.forEach(e=>e.children.forEach(tile=>{
             if(tile.material.map){
                 tile.material.map.dispose() 
@@ -1492,16 +1505,23 @@ export class Images360 extends EventDispatcher{
         //可以利用第0个pano查看,其 rotation4dkk是(_x: 0, _y: -1.5707963267948966, _z: 0 )而手动旋转至(_x:1.5707963, _y: -1.57079, _z: 0)时才正确,说明要在4dkk的旋转基础上,绕x轴转90度,(也就是转成navvis坐标系), 然后得到YupToZup的函数写法的
          
         this.highMapCube.quaternion.copy( math.convertQuaternion.YupToZup( pano.quaternion4dkk ) )
+        
+        
+        //乘上数据集整体的旋转:
+        let modelRotQua = new THREE.Quaternion().setFromRotationMatrix(pano.pointcloud.rotateMatrix)
+        this.highMapCube.quaternion.premultiply(modelRotQua)
+        
+        
     }
     
     showHighMap(){ 
         if(!this.highMapCube)   return 
-        console.warn('showHighMap')
+        //console.warn('showHighMap')
         this.highMapCube.visible = true; 
     } 
     hideHighMap(){ 
         if(!this.highMapCube)   return
-        console.warn('hideHighMap')        
+        //console.warn('hideHighMap')        
         this.highMapCube.visible = false;
     }
     //缩小后继续显示cube呢还是不显示?  不显示的话,就要把cube上的复制到renderTarget上……会不会又崩溃,or没加载的显示???
@@ -1572,10 +1592,7 @@ Images360.prototype.checkAndWaitForPanoLoad = function() {
 
 Images360.filters = { 
     inPanoDirection : function(pos, dir, i) { 
-        return function(pano) {
-            if(dir instanceof Array){  
-                dir = dir.find(e=>e.datasetId == pano.pointcloud.dataset_id).direction; 
-            } 
+        return function(pano) { 
             var r = pano.floorPosition.clone().sub(pos).setZ(0).normalize()    //忽略上下角度,这样即使看得很低也能走
 			  , o = pano.position.clone().sub(pos).normalize(); 
 			return r.dot(dir.clone().setZ(0).normalize()) > i || o.dot(dir) > i
@@ -1611,10 +1628,7 @@ Images360.filters = {
 
 Images360.scoreFunctions = {
    direction: function(pos, dir) {
-        return function(pano) {
-            if(dir instanceof Array){
-                dir = dir.find(e=>e.datasetId == pano.pointcloud.dataset_id).direction; 
-            }  
+        return function(pano) { 
             var pos = pano.position.clone()
             var n = pos.clone().sub(pos).normalize();
             return n.dot(dir) * 10 
@@ -1654,12 +1668,15 @@ export class Images360Loader{
         center = {lat:center.y, lon:center.x} //中心点 
         
         Potree.loadPanos(center,(data)=>{
+            //data[0].file_id = '00019'
+             
+            
             if(data.length == 0)console.error('没有漫游点')
             
             let images360 = new Images360(viewer, params);
             
             data = data.sort(function(a,b){return a.id-b.id})
-           
+            
             data.forEach((info,i)=>{  
                 if(Potree.fileServer){
                     info.id = i //info的id是一长串数字,改简单点

+ 25 - 10
src/modules/Images360/Panorama.js

@@ -12,6 +12,7 @@ const labelProp = {
     sizeInfo: {minSize : 120 ,  maxSize : 200,   nearBound : 0.8, farBound : 10},
     backgroundColor:{r: 255, g: 255, b: 255, a: 0.2 },
     borderRadius: 15,
+    renderOrder:10
 }
 
 let standardMarkerMat 
@@ -393,7 +394,7 @@ class Panorama extends EventDispatcher{
     onUploadAttemptedForAllTiles(e, t, i) {
         if (e === this.id) {
             var n = this.images360.qualityManager.getPanoSize(PanoSizeClass.BASE);
-            if(t === n && this.shouldRedrawOnBaseLoaded)
+            if(t === n && this.shouldRedrawOnBaseLoaded) //shouldRedrawOnBaseLoaded一直是false。在4dkk里只有初始点在quickstart后变为true。
             {
                 this.shouldRedrawOnBaseLoaded = !1;
                 this.panoRenderer.resetRenderStatus(this.id, !0, !1);
@@ -407,9 +408,9 @@ class Panorama extends EventDispatcher{
     createTextLabel(){
         this.removeTextLabel()
         this.label = new TextSprite($.extend(
-           labelProp, {text: this.id}) //{text: `id:${this.id}, dataset:${this.pointcloud.name}, 4dkkId:${this.originID}`}
+           labelProp, {text: this.id }) //{text: `id:${this.id}, dataset:${this.pointcloud.name}, 4dkkId:${this.originID}`}
         );
-
+    
         this.images360.node.add(this.label);
         this.floorPosition && this.label.position.copy(this.floorPosition)
     }
@@ -426,22 +427,22 @@ class Panorama extends EventDispatcher{
 };
 
 
-
+ 
 
 Panorama.prototype.loadTiledPano = function() {
     var downloads = []  , t = [];
-    
+     
     return function(size, dirs, fov, o, a, download) {
-        var dir = dirs.find(e=>e.datasetId == this.pointcloud.dataset_id).direction;
+        var dir = dirs.datasetsLocal.find(e=>e.datasetId == this.pointcloud.dataset_id).direction;
         //var dir = dirs
-        
+         
         
         null !== o && void 0 !== o || (o = !0),
         null !== a && void 0 !== a || (a = !0);
         var l = this.getWaitDeferred(size)
           , c = l.deferred
           , h = null
-          , u = null;
+          , u = null; 
         fov && ("number" == typeof fov ? h = fov : (h = fov.hFov, u = fov.vFov))  
         if (!this.isLoaded(size)) {
             if (!l.active) {
@@ -453,11 +454,19 @@ Panorama.prototype.loadTiledPano = function() {
                         targetTileCount: d
                     } 
                     //console.log("Loading partial pano: " + this.id + " with " + d + " tiles")
+                }else{
+                    this.downloads =  this.downloads || {}
+                       
+                    
                 }
                 if(!t[this.id]) {
                     t[this.id] = !0 
                     
                     this.addEventListener(PanoramaEvents.LoadComplete, function(ev/* e, t */) {//本次任务全部加载完毕 
+                        
+                        //console.warn('点位下载完成 ', 'id:'+this.id,  'size:'+ev.size )
+                        
+                        
                         var i = this.getWaitDeferred(ev.size).deferred;//"pending"为还未完成
                         i && "pending" === i.state() && this.highestPartialTileRenderOpCompleted >= ev.size && (i.resolve(ev.size, ev.count),
                         this.resetWaitDeferred(ev.size))//恢复active为false
@@ -470,12 +479,18 @@ Panorama.prototype.loadTiledPano = function() {
                     }.bind(this)) 
                     
                     this.addEventListener(PanoramaEvents.TileLoaded, function(ev/* t, i, n */) {//每张加载完时
+                       
+                        //console.log('tileLoaded', 'id:'+this.id,  'size:'+ev.size, 'index:'+ev.index )
+                        
+                        
                         var r = this.getWaitDeferred(ev.size).deferred;
                         if (r && "pending" === r.state()) {
                             r.notify(ev.size, ev.index, ev.count);
+                             
                             var o = downloads[this.id + ":" + ev.size];
                             if(o){//如果有规定下载哪些tile,只需要下载这些tile则LoadComplete
                                 o.tileCount++ 
+                                
                                 if(o.tileCount === o.targetTileCount){//达到下载目标数
                                     this.onPanoRendered(this.id, ev.size, ev.count, !0);
                                     r.resolve(ev.size, ev.count);
@@ -487,8 +502,8 @@ Panorama.prototype.loadTiledPano = function() {
                 }
             }
             this.images360.tileDownloader.clearForceQueue(),
-            this.images360.tileDownloader.forceQueueTilesForPano(this, size, dir, h, u, download),
-            this.tiledPanoRenderTarget = this.images360.panoRenderer.activateTiledPano(this, this.images360.qualityManager.getMaxNavPanoSize(), o),
+            this.images360.tileDownloader.forceQueueTilesForPano(this, size, dir, h, u, download) 
+            this.tiledPanoRenderTarget = this.images360.panoRenderer.activateTiledPano(this, this.images360.qualityManager.getMaxNavPanoSize(), o) 
             this.images360.panoRenderer.renderPanoTiles(this.id, dirs, a)
         }
         return c.promise()

+ 29 - 6
src/modules/Images360/tile/PanoRenderer.js

@@ -853,7 +853,7 @@ PanoRenderer.prototype.uploadTile = function () {//重写
     var collection = {},
         overlayStyle = config.tiling.overlayStyle;
         
-        
+    var failHistory = {};    
         
     return function (info, n) {
         
@@ -878,15 +878,27 @@ PanoRenderer.prototype.uploadTile = function () {//重写
             size =  this.zoomRenderTarget.width   //this.qualityManager.getMaxZoomPanoSize(); //放大后可能2048或4096
         } 
         
+      
+        
         
         
+        {//已经uploadTile过了不再uploadTile
+            if(!this.isRenderTargetDescriptorValid(activeDescripor)){
+                p = !1; g = !1
+            } 
+            if(!n){
+                this.anyUploaded(info.node) && (p = !1, g = !0) //包括子集也uploadTile了
+                this.isTileUploaded(info) && (p = !1, g = !1) //当前tile uploadTile了
+            }
+        }
         
         
-        this.isRenderTargetDescriptorValid(activeDescripor) || (p = !1, g = !1),
-            n || (this.anyUploaded(info.node) && (p = !1, g = !0),
-                this.isTileUploaded(info) && (p = !1, g = !1));
         if (p) {
-              
+             
+            /* if(failHistory[''+id+ panoSize+ tileIndex]){
+                console.log('uploadTile retry',id, panoSize, tileIndex)
+            } 
+            console.log('uploadTile 成功', id, panoSize, tileIndex) */
 
             var C = tileX * tileSize,
                 I = tileY * tileSize,
@@ -923,7 +935,13 @@ PanoRenderer.prototype.uploadTile = function () {//重写
             this.setUploaded(info, !0);
             this.addCoverageForNode(info.node);
         } else {
+            /* console.log('uploadTile  失败', id, panoSize, tileIndex)
+            failHistory[''+id+ panoSize+ tileIndex] = true; */
             this.setUploaded(info, !1);
+            
+            //发现如果不预加载512,512很可能在1024加载了之后才加载,然后g = true,就不会发送TileRenderSuccess,导致该pano一直loading。但现在应该很难出现这种情况
+            
+            
         }
         info.uploadAttempted || (LodDescripor.uploadAttempts++, this.emit(PanoRendererEvents.TileUploadAttempted, id, panoSize, tileIndex, totalTiles)),
             info.uploadAttempted = !0;
@@ -1030,7 +1048,8 @@ PanoRenderer.prototype.renderToCubeMap = function() {
         renderer.properties.get(scene); 
         material.uniforms.tDiffuse.value = texture;
         material.blending = E || THREE.NoBlending,
-        material.transparent = !!b,
+        material.transparent = !!b 
+        
         void 0 !== w && null !== w || (w = 1),
         material.uniforms.alpha.value = w,
         material.needUpdate = !0  
@@ -1047,6 +1066,10 @@ PanoRenderer.prototype.renderToCubeMap = function() {
         var oldTarget = renderer.getRenderTarget();
         renderer.autoClear = !1
         
+        
+        
+         
+        
         renderer.setRenderTarget(renderTarget, cubeFace);
         renderer.render(scene, camera/* , renderTarget, !1 */);  
         renderer.setRenderTarget(oldTarget)

+ 1 - 1
src/modules/Images360/tile/QualityManager.js

@@ -116,7 +116,7 @@ export default class QualityManager {
             return PanoSizeClass.STANDARD
         }
         return PanoSizeClass.HIGH  */
-        switch(config.navTileClass){  
+        switch(Potree.settings.navTileClass){  
             case '1k':
                 return PanoSizeClass.STANDARD;
                 break;

+ 11 - 3
src/modules/Images360/tile/TileDownloader.js

@@ -326,16 +326,24 @@ TileDownloader.prototype.forceQueueTilesForPano = function() {//根据条件开
             TilePrioritizer.sortPanoTiles(e, pano, dir) //按最佳方向排序e
             t.length = 0 
             TileUtils.matchingTilesInDirection(pano, size, dir, hFov, vFov, t);//得到在符合视野标准的集合t
+            
+            
+            
             for (var f = 0, g = function(e) {
-                    return e.face === m.face && e.faceTileIndex === m.faceTileIndex
-                }; f < e.length;) {
+                return e.face === m.face && e.faceTileIndex === m.faceTileIndex
+            }; f < e.length;) {  //过滤掉不符合角度要求的
                 var m = e[f],
                     v = t.findIndex(g);
                 v < 0 ? e.splice(f, 1) : f++
             }
         }
-        for (var A = 0; A < e.length; A++)
+        for (var A = 0; A < e.length; A++){
             this.forceQueue.push(e[A]);         //装载
+        }
+        if(e.length){
+            console.log(e)
+        }
+        
         this.setStatusForAllDescriptors(this.forceQueue, DownloadStatus.ForceQueued);
         this.clearFromQueue(this.priorityQueue, DownloadStatus.ForceQueued, !1);
         download && this.processQueueForDownloading(this.forceQueue, !0);

+ 17 - 9
src/modules/Images360/tile/TilePrioritizer.js

@@ -171,7 +171,7 @@ TilePrioritizer.appendQueue = function (e, t) {
 };
 
 TilePrioritizer.sortPanoTiles = function (descriptors, pano, dir) {
-    if(dir instanceof Array)  dir = dir.find(e=>e.datasetId == pano.pointcloud.dataset_id).direction;//add
+    if(dir.datasetsLocal)  dir = dir.datasetsLocal.find(e=>e.datasetId == pano.pointcloud.dataset_id).direction;//add
     u._panoSpaceDir.copy(dir) 
     TileUtils.getRelativeDirection(pano.quaternion4dkk, u._panoSpaceDir) //应该是将dir根据quaternion转化下
     u._fovThresholdNarrow = math.getFOVDotThreshold(TilePrioritizer.DIRECTIONAL_FOV_NARROW)
@@ -180,7 +180,7 @@ TilePrioritizer.sortPanoTiles = function (descriptors, pano, dir) {
 };
 
 TilePrioritizer.insertSortedPanoTile = function (e, t, pano, dir) {
-    if(dir instanceof Array)  dir = dir.find(e=>e.datasetId == pano.pointcloud.dataset_id).direction;//add
+    if(dir.datasetsLocal)  dir = dir.datasetsLocal.find(e=>e.datasetId == pano.pointcloud.dataset_id).direction;//add
     u._panoSpaceDir.copy(dir),
         TileUtils.getRelativeDirection(pano.quaternion4dkk, u._panoSpaceDir),
         u._fovThresholdNarrow = math.getFOVDotThreshold(TilePrioritizer.DIRECTIONAL_FOV_NARROW),
@@ -208,17 +208,25 @@ TilePrioritizer.prototype.filterAndPrioritize = function () {//挑选出优先
         i = [];
     return function (queue, panos, tileDownloader) {
         //this.populateNeighborPanos(this.priorityCriteria.pano, panos, e);
-        
          
-        let cameraDirLocals = this.priorityCriteria.cameraDirs.map(e=>{ //add
+        /* let cameraDirLocals = this.priorityCriteria.cameraDirs.map(e=>{ //add
+            var dataset = viewer.scene.pointclouds.find(u=>u.dataset_id == e.datasetId)
+            var matrix = new THREE.Matrix4().copy(dataset.rotateMatrix)
+            var direction = math.convertVector.YupToZup(e.direction)  
+        
+        
             return {
                 datasetId:e.datasetId,
-                direction: math.convertVector.YupToZup(e.direction)
+                direction: direction.clone().applyMatrix4(matrix)
             }
-        }) 
-        //let cameraDirLocals = math.convertVector.YupToZup(this.priorityCriteria.cameraDirs)
-        
+        }) */
+        let cameraDirLocals = this.priorityCriteria.cameraDirs.vectorForward
+         
+        //获得视野范围内的邻近点位序列t
         this.populateScoredPanos(this.priorityCriteria.pano, panos, t, cameraDirLocals , TilePrioritizer.MAX_SCORED_PANOS_TOCONSIDER);
+        
+        
+        
         var s = this.baseSize //512
             ,
             l = this.standardSize //1024
@@ -280,7 +288,7 @@ TilePrioritizer.prototype.queueTilesInDirectionForPano = function () {
         t = new THREE.Vector3;
     return function (i, n, pano, o, a, dirs, c) {
         
-        var dir = dirs.find(e=>e.datasetId == pano.pointcloud.dataset_id).direction;//add
+        var dir = dirs.datasetsLocal.find(e=>e.datasetId == pano.pointcloud.dataset_id).direction;//add
         //var dir = dirs
         
         t.copy(dir);

+ 3 - 0
src/modules/datasetAlignment/Alignment.js

@@ -67,6 +67,9 @@ var Alignment = {
             Alignment.changeCallBack && Alignment.changeCallBack();
         } 
         
+        if(pointcloud.spriteNodeRoot){
+            pointcloud.spriteNodeRoot.matrixWorld.copy(pointcloud.matrixWorld)//.multiplyMatrices(pointcloud.matrixWorld, pointcloud.matrixWorld);	
+        }
     },
     rotate:function(pointcloud, deg, angle){//假设点云位移position后0,0,0就是它的中心了(根据navvis观察这样做是绕同一个点旋转的)
         var angle = angle != void 0 ? angle : THREE.Math.degToRad(deg)   //正逆负顺

+ 2 - 2
src/modules/siteModel/SiteModel.js

@@ -189,7 +189,7 @@ var SiteModel = {
                 
                  
             } 
-             
+              
             if (!e.complete && entity.markers.length > 3) {
 				entity.removeMarker(entity.points.length - 1); 
 			}
@@ -201,7 +201,7 @@ var SiteModel = {
             clearTimeout(timer) 
 			viewer.removeEventListener('cancel_insertions', Exit);
             pressExit && viewer.inputHandler.removeEventListener('keydown', pressExit);
-            callback && callback() 
+            callback && callback(entity) 
             
             /* this.viewer.dispatchEvent({
                 type: 'finish_inserting_polygonment',

+ 12 - 18
src/navigation/FirstPersonControls.js

@@ -77,20 +77,20 @@ export class FirstPersonControls extends EventDispatcher {
 
 		let drag = (e) => {
             if(!this.enabled)return 
-            let viewport = e.drag.dragViewport;
+            let viewport = e.dragViewport;
             if(!viewport)return
             let camera = viewport.camera 
             let mode 
             if(e.isTouch){
                 if(e.touches.length == 1){
-                    mode = (!e.drag.dragViewport || e.drag.dragViewport.name == 'MainView') ? 'rotate' : 'pan' 
+                    mode = (!e.dragViewport || e.dragViewport.name == 'MainView') ? 'rotate' : 'pan' 
                 }else if(e.touches.length == 2){
                     mode = 'scale'
                 }else{
-                    mode = (!e.drag.dragViewport || e.drag.dragViewport.name == 'MainView') ? 'pan' : 'scale' 
+                    mode = (!e.dragViewport || e.dragViewport.name == 'MainView') ? 'pan' : 'scale' 
                 } 
             }else{
-                mode = e.buttons === Buttons.LEFT && (!e.drag.dragViewport || e.drag.dragViewport.name == 'MainView') ? 'rotate' : 'pan'
+                mode = e.buttons === Buttons.LEFT && (!e.dragViewport || e.dragViewport.name == 'MainView') ? 'rotate' : 'pan'
             }
             //console.log('mode  ', mode )
             let moveSpeed = this.currentViewport.getMoveSpeed();
@@ -147,15 +147,7 @@ export class FirstPersonControls extends EventDispatcher {
                 if(viewport.unableChangePos)return
                 if(camera.type == "OrthographicCamera"){
                    
-                    
-                    /* let ViewWidthPX = viewport.width * viewer.renderer.domElement.clientWidth
-                    let ViewHeightPX = viewport.height * viewer.renderer.domElement.clientHeight
-                    let cameraViewWidth = camera.right * 2
-                    let cameraViewHeight = camera.top * 2; 
-                     
-                    moveVec.set(-1 * e.drag.mouseDelta.x * cameraViewWidth / ViewWidthPX, e.drag.mouseDelta.y * cameraViewHeight / ViewHeightPX , 0).applyQuaternion(camera.quaternion)  
-                     */
-                    
+                    //console.log(e.drag.pointerDelta, e.pointer, e.drag.end)
                     let moveVec = Utils.getOrthoCameraMoveVec(e.drag.pointerDelta, camera )//最近一次移动向量
                     
                     let handleState = window.viewer.modules.Alignment.handleState
@@ -305,7 +297,7 @@ export class FirstPersonControls extends EventDispatcher {
                  
                 
                 if(e.delta != void 0){//滚轮缩放 
-                    speed = (this.currentViewport.getMoveSpeed() || 1) * 7
+                    speed =  this.currentViewport.getMoveSpeed() * 15
                     
                     //var direction = this.currentViewport.view.direction.clone();
                     direction = this.viewer.inputHandler.getMouseDirection().direction  //定点缩放
@@ -317,7 +309,7 @@ export class FirstPersonControls extends EventDispatcher {
                         speed *= -1
                     } 
                 }else{
-                    const constantDis =  this.currentViewport.getMoveSpeed() * 500 //constantDis = 10;//常量系数,当放大一倍时前进的距离。可以调整
+                    const constantDis =  this.currentViewport.getMoveSpeed() * 200 //constantDis = 10;//常量系数,当放大一倍时前进的距离。可以调整
                     speed = (e.scale-1)*constantDis //触屏缩放
                     //pointer = new THREE.Vector2().addVectors().multiplyScalar(0.5);//两个指头的中心点
                     direction = this.viewer.inputHandler.getMouseDirection(e.pointer).direction  //定点缩放
@@ -349,6 +341,7 @@ export class FirstPersonControls extends EventDispatcher {
 
 		this.viewer.addEventListener('global_drag', drag);
         this.viewer.addEventListener('global_touchmove', (e)=>{ 
+            if(!this.enabled)return
             if(e.touches.length>1){//单指的就触发上一句 
                 //console.log('global_touchmove' )
                 drag(e)
@@ -365,7 +358,7 @@ export class FirstPersonControls extends EventDispatcher {
         }
         let prepareRotate = (e)=>{ 
             this.pointerDragStart = e.pointer.clone() 
-            console.log('prepareRotate')
+            //console.log('prepareRotate')
         }
         let preparePan = (e)=>{//触屏的pan点云    还是会偏移
             
@@ -383,16 +376,17 @@ export class FirstPersonControls extends EventDispatcher {
         }
         
         this.viewer.addEventListener('global_mousedown'/* 'startDragging' */, (e)=>{
+            if(!this.enabled)return
             this.setCurrentViewport(e)
             prepareRotate(e)
         })
         this.viewer.addEventListener('global_touchstart', (e)=>{
-            if(e.touches.length==2){//只监听开头两个指头
+            if(this.enabled && e.touches.length==2){//只监听开头两个指头
                 prepareScale(e)
             }
         })
         this.viewer.addEventListener('global_touchend', (e)=>{
-            
+            if(!this.enabled)return
             if(e.touches.length==2){//停止平移,开始scale
                 prepareScale(e)
             }else if(e.touches.length==1){//停止scale,开始rotate

+ 16 - 7
src/navigation/InputHandler.js

@@ -319,6 +319,11 @@ export class InputHandler extends EventDispatcher {
         
         if(isTouch){
             var  {  camera, viewport  } = this.updateTouchesInfo(e) 
+            if(this.drag){
+                //因为触屏在按下前缺少pointermove所以要更新下
+                this.drag.end = this.pointer.clone()
+            }
+             
              
         }else{
             var  {  camera, viewport  } = this.getPointerInViewport(x, y ) 
@@ -390,6 +395,7 @@ export class InputHandler extends EventDispatcher {
         this.drag.intersectStart = this.intersectPoint;
         this.mouseDownMouse = this.mouse.clone()
         this.dragViewport = this.hoverViewport;
+        this.pointerDownTime = Date.now()
     }
 
 
@@ -440,6 +446,8 @@ export class InputHandler extends EventDispatcher {
 		e.preventDefault();
         
         let pressDistance = this.mouseDownMouse.distanceTo(this.mouse);
+        let pressTime = Date.now() - this.pointerDownTime;
+        
 		let noMovement = this.drag.pointerDelta.length() == 0//this.getNormalizedDrag().length() === 0;
         
 		let consumed = false;
@@ -501,7 +509,7 @@ export class InputHandler extends EventDispatcher {
                  
                 
                 // check for a click 
-                if(pressDistance < Potree.config.clickMaxDragDis){
+                if(pressDistance < Potree.config.clickMaxDragDis && pressTime<Potree.config.clickMaxPressTime){
                     if(this.hoveredElements && this.hoveredElements[0]){
                         if (this.logMessages) console.log(`${this.constructor.name}: click ${clicked.name}`);
                         this.hoveredElements[0].object.dispatchEvent($.extend(  
@@ -719,7 +727,9 @@ export class InputHandler extends EventDispatcher {
  
 		if (this.drag) {//有拖拽(不一定拖拽了物体, 也不一定按下了鼠标)
 			this.drag.mouse = isTouch ? 1 : e.buttons; 
-            this.drag.hoverViewport = this.hoverViewport 
+            //add:
+            //this.drag.pointer = this.pointer.clone();
+            //this.drag.hoverViewport = this.hoverViewport
             this.drag.pointerDelta.subVectors(this.pointer,  this.drag.end)
 			this.drag.end.copy(this.pointer)
             
@@ -737,8 +747,7 @@ export class InputHandler extends EventDispatcher {
                 
 			} else {
                 
-                //add:
-                this.drag.pointer = this.pointer.clone();
+                
                 
 				if (this.logMessages) console.log(this.constructor.name + ': drag: ');
 
@@ -898,8 +907,8 @@ export class InputHandler extends EventDispatcher {
 			end: this.pointer.clone(),
 			pointerDelta: new THREE.Vector2(0, 0), 
 			object: object, 
-            dragViewport :  this.hoverViewport, //开始之后就不会变了
-            hoverViewport: this.hoverViewport   //会变化
+            hoverViewport: this.hoverViewport,   //会变化
+            dragViewport: this.hoverViewport, //不变
 		};
         if (args) {
 			for (let key of Object.keys(args)) {
@@ -1026,7 +1035,7 @@ export class InputHandler extends EventDispatcher {
 			return null;
 		}
 	}
-
+ 
 	getHoveredElements () {
 		let scenes = this.hoverViewport.interactiveScenes || this.interactiveScenes.concat(this.scene);
 

+ 87 - 14
src/navigation/OrbitControls.js

@@ -43,40 +43,84 @@ export class OrbitControls extends EventDispatcher{
 		this.doubleClockZoomEnabled = true;
 
 		this.tweens = [];
-
+        this.dollyStart = new THREE.Vector2
+        this.dollyEnd = new THREE.Vector2
+        
 		let drag = (e) => {
             if(!this.enabled)return
 			if (e.drag.object !== null) {
 				return;
 			}
+            let mode
+            
+            if(e.isTouch){
+               
+                if(e.touches.length == 1){
+                    mode = 'rotate'  
+                }else{  
+                    mode = 'scale-pan'
+                }  
+            }else{
+                mode = e.buttons === Buttons.LEFT ? 'rotate' : 'pan'
+            }
+
+
 
-			if (e.drag.startHandled === undefined) {
-				e.drag.startHandled = true;
 
+            
+			if (e.drag.startHandled === undefined) {
+				e.drag.startHandled = true; 
 				this.dispatchEvent({type: 'start'});
 			}
 
-			/* let ndrag = {
-				x: e.drag.mouseDelta.x / this.renderer.domElement.clientWidth,
-				y: e.drag.mouseDelta.y / this.renderer.domElement.clientHeight
-			}; */
+			 
             let ndrag = e.drag.pointerDelta.clone()//.add(new THREE.Vector2(1,1)).multiplyScalar(0.5)
             ndrag.y *= -1
 
-			if (e.buttons === Buttons.LEFT) {
+			if (mode == 'rotate') {
 				this.yawDelta += ndrag.x * this.rotationSpeed;
 				this.pitchDelta += ndrag.y * this.rotationSpeed;
 
-				this.stopTweens();
-			} else {
+				
+			} else if(mode == 'pan'){
                
 				this.panDelta.x += ndrag.x;
 				this.panDelta.y += ndrag.y;
 
-				this.stopTweens();
-			}
+				 
+			}else if(mode == 'scale-pan'){ //add
+                this.dollyEnd.subVectors(e.touches[0].pointer, e.touches[1].pointer); 
+                var scale = this.dollyEnd.length() / this.dollyStart.length() 
+                  
+                this.dollyStart.copy(this.dollyEnd); 
+                this.radiusDelta = (1-scale) * this.scene.view.radius 
+			  
+                //------------------------
+                //平移
+                let pointer = new THREE.Vector2().addVectors(e.touches[0].pointer, e.touches[1].pointer).multiplyScalar(0.5);//两个指头的中心点
+                 
+                let delta = new THREE.Vector2().subVectors(pointer, this.lastScalePointer)
+                delta.y *= -1
+                this.panDelta.add(delta)
+                
+                this.lastScalePointer = pointer.clone()
+                
+                
+                
+                //console.log('scale ',scale, this.radiusDelta)
+                
+            }
+            
+            this.stopTweens();
+            
+            
 		};
-
+        
+        
+        
+         
+        
+        
 		let drop = e => {
             if(!this.enabled)return
 			this.dispatchEvent({type: 'end'});
@@ -158,6 +202,35 @@ export class OrbitControls extends EventDispatcher{
 		this.viewer.addEventListener('global_drop', drop);
 		this.viewer.addEventListener('global_mousewheel', scroll);
 		this.viewer.addEventListener('global_dblclick', dblclick);
+        this.viewer.addEventListener('global_touchmove', (e)=>{ 
+            if(e.touches.length>1){//单指的就触发上一句 
+                //console.log('global_touchmove' )
+                drag(e)
+            }
+        });
+        let prepareScale = (e)=>{//触屏的scale
+            this.dollyStart.subVectors(e.touches[0].pointer, e.touches[1].pointer);
+            this.lastScalePointer = new THREE.Vector2().addVectors(e.touches[0].pointer, e.touches[1].pointer).multiplyScalar(0.5);//两个指头的中心点
+              
+        }
+         
+        this.viewer.addEventListener('global_touchstart', (e)=>{
+            if(this.enabled && e.touches.length==2){//只监听开头两个指头
+                prepareScale(e)
+            }
+        })
+        /* this.viewer.addEventListener('global_touchend', (e)=>{
+            if(!this.enabled)return
+            if(e.touches.length==1){//停止scale,开始rotate
+                prepareRotate(e)
+                //this.pointerDragStart = null
+                //console.log('只剩一个', e.pointer.toArray())
+            }
+        }) */
+        
+        
+        
+        
 	}
 
 	setScene (scene) {
@@ -280,7 +353,7 @@ export class OrbitControls extends EventDispatcher{
 		}
 
 		{ // apply zoom
-			let progression = Math.min(1, this.fadeFactor * delta);
+			let progression = 1//Math.min(1, this.fadeFactor * delta);
 
 			// let radius = view.radius + progression * this.radiusDelta * view.radius * 0.1;
 			let radius = view.radius + progression * this.radiusDelta;

+ 45 - 10
src/navigation/Reticule.js

@@ -10,8 +10,6 @@ let defaultOpacity =  0.7
 export default class Reticule extends THREE.Mesh{
     constructor(viewer){
         var defaultTex = texLoader.load(Potree.resourcePath+'/textures/whiteCircle.png'/* reticule-256x256.png'  */)  
-        var crosshairTex = texLoader.load(Potree.resourcePath+'/textures/reticule_cross_hair.png') 
-        
         super(new THREE.PlaneBufferGeometry(0.15,0.15,1,1),new THREE.MeshBasicMaterial({
             side: THREE.DoubleSide , 
             map: defaultTex,
@@ -21,6 +19,10 @@ export default class Reticule extends THREE.Mesh{
             //depthWrite: !1,
         })) 
         
+        this.defaultTex = defaultTex
+        this.crosshairTex = texLoader.load(Potree.resourcePath+'/textures/reticule_cross_hair.png') 
+        this.forbitTex = texLoader.load(Potree.resourcePath+'/textures/pic-forbid.png') 
+        
         //this.layers.set(0/* RenderLayers.RETICULE */);
         this.renderOrder = 0
         this.layers.set(Potree.config.renderLayers.marker);
@@ -36,21 +38,49 @@ export default class Reticule extends THREE.Mesh{
         //viewer.addEventListener('global_click',this.move.bind(this))
         viewer.addEventListener('global_mousedown',this.move.bind(this))//主要针对触屏
         
-        
+        this.state = {}
         
         viewer.addEventListener('measureMovePoint',()=>{
-            this.material.map = crosshairTex
-            this.state = 'crosshair' 
+            this.state.cross = true
+            this.judgeTex()
         }) 
         viewer.addEventListener('endMeasureMove',()=>{
-            this.material.map = defaultTex 
-            this.state = 'default' 
+            this.state.cross = false
+            this.judgeTex()
         }) 
-        this.state = 'default'
+        
+        viewer.on('reticule_forbit',(e)=>{
+            if(this.state.forbit != e){
+                console.log('change forbit ',e)
+            }
+            this.state.forbit = e
+            this.judgeTex() 
+        })
+        
+        
+        
+        
+       
         
         viewer.setObjectLayers(this, 'reticule' )
     }
 
+    judgeTex(){ 
+        if(this.state.forbit){
+            this.material.map = this.forbitTex 
+        }else if(this.state.cross){
+            this.material.map = this.crosshairTex 
+        }else{
+            this.material.map = this.defaultTex 
+        }
+        
+         
+        viewer.mapViewer.dispatchEvent({type:'content_changed'})
+    }
+
+
+
+
     move(e){ 
     
         if(e.type == "global_mousemove" && (e.isTouch || e.buttons != Buttons.NONE) && this.state != 'crosshair')
@@ -68,6 +98,7 @@ export default class Reticule extends THREE.Mesh{
         //console.log("hide Reticule")
         this.hidden || (this.hidden = !0,
         transitions.start(lerp.property(this.material , "opacity", 0), 500))
+        this.dispatchEvent({type:'update', visible:false})
     }
 
     show(){
@@ -75,6 +106,9 @@ export default class Reticule extends THREE.Mesh{
         //console.log("show Reticule")
         this.hidden = !1,
         this.material.opacity <= 0 && transitions.start(lerp.property(this.material, "opacity", defaultOpacity), 300)
+        
+        this.dispatchEvent({type:'update', visible:true})
+        
     }
 
     //鼠标静止一段时间它就会消失
@@ -88,7 +122,7 @@ export default class Reticule extends THREE.Mesh{
                 return //this.hide();
             var atMap = !intersectPoint.location
             let normal
-            if(atMap){
+            if(atMap){ 
                 normal =  new THREE.Vector3(0,0,1)//地图无normal
             }else{
                 normal = new THREE.Vector3().fromArray(intersectPoint.point.normal ).applyMatrix4(intersectPoint.pointcloud.transformMatrix);
@@ -104,7 +138,7 @@ export default class Reticule extends THREE.Mesh{
                 n < 1 && (s -= 1 - n)
             }else{
                 camera = viewer.mapViewer.camera
-                s = math.getScaleForConstantSize({width2d:300, position:location, camera, resolution:viewport.resolution2} )
+                s = math.getScaleForConstantSize({width2d:400, position:location, camera, resolution:viewport.resolution/* 2 */} )
                 location.setZ(0);//低于相机高度即可
             }
             
@@ -116,6 +150,7 @@ export default class Reticule extends THREE.Mesh{
             this.direction.add(normal.clone().multiplyScalar(.2));
             this.position.copy(location).add(normal.clone().multiplyScalar(.01));
             this.lookAt(this.position.clone().add(this.direction));
+            this.dispatchEvent({type:'update'})
         }
     }
 }

+ 16 - 9
src/navigation/RouteGuider.js

@@ -103,7 +103,7 @@ export class RouteGuider extends EventDispatcher{
             map
         }))
         this.arrow.scale.set(arrowSize,arrowSize,arrowSize)
-        viewer.setObjectLayers(this.arrow, 'route' )
+        viewer.setObjectLayers(this.arrow, 'sceneObjects' )
          
         
         this.testArrow = this.arrow.clone();
@@ -113,7 +113,7 @@ export class RouteGuider extends EventDispatcher{
         this.arrows = new THREE.Object3D;
         this.sceneMeshGroup.add(this.arrows)
         
-        viewer.setObjectLayers(this.sceneMeshGroup, 'route' )
+        viewer.setObjectLayers(this.sceneMeshGroup, 'sceneObjects' )
         //this.sceneMeshGroup.traverse(e=>e.renderOrder = 90)
         
         
@@ -139,12 +139,9 @@ export class RouteGuider extends EventDispatcher{
         this.mapArrow.scale.set(arrowSize,arrowSize,arrowSize)
         this.mapArrows = new THREE.Object3D;
         this.mapArrows.name = 'mapArrows'
-        //viewer.setObjectLayers(this.mapArrow, 'route' )
-        
+         
         
         
-        /* this.mapMeshGroup.add(this.mapMarkStart)
-        this.mapMeshGroup.add(this.mapMarkEnd) */
         this.mapMeshGroup.add(this.mapArrows)
         this.mapMeshGroup.name = 'mapRouteLayer'
         this.mapMeshGroup.visible = false
@@ -327,10 +324,18 @@ export class RouteGuider extends EventDispatcher{
                     let result
                     if(data && data.code == 4002){
                         result = data;//正被修改数据集
+                    }else if(this.routeStart.distanceTo(this.routeEnd) < 1){
+                        result = { code: 500, msg: '距离太短,无法规划路线' }
                     }else{
                         result = { code: 500, msg: '超出数据集范围,无法规划路线' }
                     }
-                    this.clearRoute()  
+                    this.clearRoute() 
+
+
+                    this.setStartPole(this.routeStart) 
+                    this.setEndPole(this.routeEnd) 
+                    
+                    this.displayRoute() //还是要显示一下起始
                     this.bus && this.bus.emit('gotResult', result )
                     
                     return //this.generateDeferred && this.generateDeferred.resolve()
@@ -359,9 +364,11 @@ export class RouteGuider extends EventDispatcher{
                     
                     console.log(this.route)
                     
-                    this.setStartPole(this.route[0]) 
-                    this.setEndPole(this.route[this.route.length-1]) 
+                    
                 }
+                this.setStartPole(this.route[0]) 
+                this.setEndPole(this.route[this.route.length-1]) 
+                
                 create()
                 /*
                     distance: 0.17581000000000116

+ 67 - 31
src/settings.js

@@ -70,18 +70,26 @@ const config = {//配置参数   不可修改
         prefix2: 'testlaser.4dkankan.com'
     },
      
+    /* transitionsTime:{
+        flyTime : 1000  // 毫秒/米
+        panoToPano: 1000, 
+        flyIn:1000,
+        flyOut:1000,
+    } */
     transitionsTime:{
-        flySpeed : 1000 /* 200 */,//400, // 毫秒/米
-        panoToPano: 1000,//2000,
+        flyTime : 2000,  // 毫秒/米
+        panoToPano: 1000, 
         flyIn:1000,
         flyOut:1000,
     }
+    
     ,
-    moveSpeedAdujust : 0.3  //越小越慢
+    moveSpeedAdujust : 0.5  //越小越慢
     ,
     view:{
         fov:50,  //navvis:50 
-        
+        near:0.1,
+        far: 10000,
     },
     
      
@@ -90,7 +98,7 @@ const config = {//配置参数   不可修改
     pointDensity:{
         panorama:{//显示全景时的漫游。因为点只能显示1个像素的大小,所以必须很密集,但又要限制点的数量
             maxLevelPercent: 1,
-            pointBudget :0.25*1000*1000,  //点云总最大数
+            pointBudget :   0.25*1000*1000,  //点云总最大数
         },
         fourViewports:{//分四屏时防止卡顿
             maxLevelPercent: 0.5,  
@@ -108,14 +116,39 @@ const config = {//配置参数   不可修改
             maxLevelPercent: 1, 
             pointBudget:8*1000*1000,
         }
+        //browser.isMobile() 时要不要限制下pointBudget,还是让用户自己调低质量?
         //minNodeSize?
         //数值由testLevelSteps得来,其中nodeMaxLevel为2时,low和middle的都是1,如果真有这么低的点云就单独处理下。
-    },
-    
-    
+    },  
     
     
     
+    /* pointDensity:{
+        panorama:{//显示全景时的漫游。因为点只能显示1个像素的大小,所以必须很密集,但又要限制点的数量
+            maxLevelPercent: 1,
+            pointBudget :   0.1*1000*1000,  //点云总最大数
+        },
+        fourViewports:{//分四屏时防止卡顿
+            maxLevelPercent: 0.1,  
+            pointBudget :0.01*1000*1000, // 只要限制这个就足够 (为什么分屏focus区域不同会闪烁,navvis不会)(navvis:maxLevel:5,pointBudget:1*1000*1000)
+        },
+        low:{//highPerformance
+            maxLevelPercent: 0.2, //最小为0
+            pointBudget :0.01*1000*1000,
+        }, 
+        middle:{//balanced  //不同场景相同级别所产生的numVisibleNodes和numVisiblePoints不同,如果分层比较细,可能要到level8才能看清,那么level5看到的点就很大且很少,如隧道t-e2Kb2iU
+            maxLevelPercent: 0.3,
+            pointBudget:0.01*1000*1000,
+        },
+        high:{//highQuality
+            maxLevelPercent: 0.5, 
+            pointBudget:0.01*1000*1000,
+        }
+        //browser.isMobile() 时要不要限制下pointBudget,还是让用户自己调低质量?
+        //minNodeSize?
+        //数值由testLevelSteps得来,其中nodeMaxLevel为2时,low和middle的都是1,如果真有这么低的点云就单独处理下。
+    },
+     */
     
     
     clip:{
@@ -147,21 +180,21 @@ const config = {//配置参数   不可修改
     ,
      
     
-    renderLayers:{//渲染层,方便分批渲染管理,替代scene的创建。数字不代表顺序。
-        bg: 0, 
-        bg2: 100,
+    renderLayers:{//渲染层,方便分批渲染管理,替代scene的创建。数字不代表顺序。(数字不能太大)
+        bg: 20, 
+        bg2: 21,
         
         skybox: 1,
         pointcloud: 11,
-        sceneObjects:2,//default
-        marker: 2,
+        sceneObjects:0,//default
+        marker: 0,
         reticule: 3,
         measure:4,  
         magnifier:5, 
         magnifierContent:16,
         volume:6,
         transformationTool:7,
-        route:10,
+       
         map:8,
         mapObjects:9,//default
         
@@ -226,6 +259,9 @@ const config = {//配置参数   不可修改
     ultraHighQualityMaxZoom: 3,
     
     clickMaxDragDis:5,
+    clickMaxPressTime:500, //ms
+     
+     
      
     background: '#232323',
     mapBG:'#F5F5F5', //地图的clearColor
@@ -259,7 +295,20 @@ const config = {//配置参数   不可修改
 2只显示全景: 不能任意行走。 过渡时显示贴图材质非edl的点云(否则有折痕不贴合)。
 3混合:都显示。 不能任意行走。过渡时显示贴图材质非edl的点云(因为只显示点云的话不太美,点云很碎,不细腻)
  */
- 
+window.testLevelSteps = function(steps){//[0.4,0.7,1]
+    if(!steps){
+        let s = Potree.config.pointDensity;
+        steps = [s.low.maxLevelPercent, s.middle.maxLevelPercent, s.high.maxLevelPercent, ]
+    }
+    let max = 1
+    while(++max<=12){ 
+        let r1 = steps.map(e=>e * max);
+        let r2 = steps.map(e=>Math.round(e * max));
+        console.log(`当nodeMaxLevel为${max}时,每一级的level分别为${r2}, (小数:${r1})`) 
+    }
+    console.log('请检查每一层的三个level是否有重复')
+     
+} 
 function getPrefix(){  
     let u = window.location.href.split('//')
     let v = u[1].split('/');
@@ -270,16 +319,17 @@ function getPrefix(){
 let settings = {//设置   可修改
     number: '', //场景序号
     isOfficial:false,
+    webSite:'data', //不同环境对应的静态文件的地址不同
     displayMode:'',
     isTest :browser.urlHasValue('test'),
-    prefix:getPrefix(),
+    prefix: getPrefix(),
     pointDensity: '',    UserPointDensity:'',//pointDensity会随着进入不同的模块而自动改变,UserPointDensity记录了用户的设置
     UserDensityPercent:null,//点云密度百分比 
     ifShowMarker:true,//显示漫游点
     floorplanType:null,//平面图类型 'default' | 'diy'
     floorplanEnable:false,
     mapEnable:true,//地图区域是否加载地图
-    cameraFar : 10000, //相机最远范围 1-300
+    cameraFar : config.view.far, //相机最远范围 1-300
     //limitFar: true, //是否使用setting的cameraFar来限制(如在点云裁剪时为false)
     showPanoMesh:false, //显示小球,
     dblToFocusPoint:false,//调试时如果需要双击飞向某个点云的点,就打开。此时不在漫游点的话单击将无法漫游。//因和单击漫游冲突 
@@ -321,18 +371,4 @@ settings.isLocalhost = settings.prefix.includes('localhost')
  */
  
  
-window.testLevelSteps = function(steps){//[0.4,0.7,1]
-    if(!steps){
-        let s = Potree.config.pointDensity;
-        steps = [s.low.maxLevelPercent, s.middle.maxLevelPercent, s.high.maxLevelPercent, ]
-    }
-    let max = 1
-    while(++max<=12){ 
-        let r1 = steps.map(e=>e * max);
-        let r2 = steps.map(e=>Math.round(e * max));
-        console.log(`当nodeMaxLevel为${max}时,每一级的level分别为${r2}, (小数:${r1})`) 
-    }
-    console.log('请检查每一层的三个level是否有重复')
-     
-} 
 export {config, settings}

+ 75 - 9
src/start.js

@@ -8,11 +8,18 @@ import './extensions/three.shim.js'
 import {Utils} from "../src/utils.js"
  
 
-var start = function(dom, mapDom, number, fileServer){ //t-Zvd3w0m
-
-    
+var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
+    /* {
+        let obj = JSON.parse(localStorage.getItem('setting'))
+        for(let i in obj){
+            console.log(i + ': ' +  obj[i])
+        }
+    }
+     */
     Potree.settings.number = number || 't-o5YMR13'// 't-iksBApb'// 写在viewer前
     Potree.fileServer = fileServer
+    webSite && (Potree.settings.webSite = webSite)
+    
     
     let viewer = new Potree.Viewer(dom , mapDom);
     
@@ -78,6 +85,11 @@ var start = function(dom, mapDom, number, fileServer){ //t-Zvd3w0m
                         }
                         
                     }
+                    
+                    
+                    
+                    viewer.addObjectTest()
+                    
                     viewer.emit('allLoaded')
                 });
                 
@@ -125,6 +137,9 @@ var start = function(dom, mapDom, number, fileServer){ //t-Zvd3w0m
             pointcloud.translateUser = new THREE.Vector3;
             
             viewer.sidebar && viewer.sidebar.addAlignmentButton(pointcloud) 
+            
+            //dataset.orientation = 0
+            
             Alignment.rotate(pointcloud, null, dataset.orientation)   
             Alignment.translate(pointcloud, new THREE.Vector3(location[0], location[1], dataset.location[2])) 
             
@@ -165,8 +180,8 @@ var start = function(dom, mapDom, number, fileServer){ //t-Zvd3w0m
             } 
             
             if(!ifReload){
-                var cloudPath = `https://${Potree.config.urls.prefix}/data/${number}/data/${dataset.name}/webcloud/cloud.js` 
-                Potree.loadPointCloud(cloudPath, dataset.name , e => {
+                var cloudPath = `https://${Potree.config.urls.prefix}/${Potree.settings.webSite}/${number}/data/${dataset.name}/webcloud/cloud.js` 
+                 Potree.loadPointCloud(cloudPath, dataset.name , e => {
                     let scene = viewer.scene;
                     let pointcloud = e.pointcloud; 
                     let config = Potree.config.material
@@ -178,7 +193,7 @@ var start = function(dom, mapDom, number, fileServer){ //t-Zvd3w0m
                     pointcloud.changePointSize(config.pointSize)  //material.size =  config.pointSize;
                     pointcloud.changePointOpacity(1)
                     material.shape = Potree.PointShape.SQUARE; 
-                    pointcloud.color = dataset.color  
+                    pointcloud.color = pointcloud.material.color = dataset.color  
                     pointcloud.dataset_id = dataset.id;//供漫游点找到属于的dataset点云
                     pointcloud.panos = [] 
                     transformPointcloud(pointcloud,dataset)
@@ -241,9 +256,60 @@ var start = function(dom, mapDom, number, fileServer){ //t-Zvd3w0m
         
     }
 }
-  //https://testlaser.4dkankan.com/indoor/t-ia44BhY/api/site_model
-  
-  //https://testlaser.4dkankan.com/indoor/t-ia44BhY/api/tiled_maps
+ 
+ 
+ 
+ 
+/* var changeLog = ()=>{ //如果移动端加了test反而出不来bug的话,用这个
+        
+    
+        var textarea = document.createElement('textarea');
+          textarea.id = "consoleLog";
+          
+          textarea.style.width = '160px';
+          textarea.style.height =  '200px'
+          textarea.style.position = 'fixed'
+          textarea.style.right = 0
+          textarea.style.bottom = '0'
+          textarea.style['z-index'] = 9999;
+          textarea.style.color = 'black';
+          textarea.style.opacity = 0.9;
+          textarea.style['font-size'] = '12px';
+          textarea.style['backgroundColor'] = '#ffffff'
+         
+          
+
+          document.getElementsByTagName("body")[0].appendChild(textarea);
+          var list = ["log", "error", "warn", "debug", "info", "time", "timeEnd"]
+          var exchange = function (o) {
+            console["old" + o] = console[o];
+            console[o] = function () {
+              var args =   Array.from(arguments)
+              console["old" + o].apply(this, arguments)
+              var t = document.getElementById("consoleLog").innerHTML;
+              
+              var str = ''
+              args.forEach(a=>{
+                  str += a + ' '
+              })
+              document.getElementById("consoleLog").innerHTML = str + "\n\n" + t;
+            }
+          }
+
+          for (var i = 0; i < list.length; i++) {
+            exchange(list[i])
+          } 
+   
+    
+    
+}
+ 
+changeLog() */
+ 
+ 
+ 
+ 
+ 
 export {start}
 
 

+ 35 - 6
src/utils/DrawUtil.js

@@ -6,7 +6,7 @@ import {Line2} from "../../libs/three.js/lines/Line2.js";
 import {LineGeometry} from "../../libs/three.js/lines/LineGeometry.js";
 import {LineMaterial} from "../../libs/three.js/lines/LineMaterial.js";
 //画线等函数--by 许钟文
-
+import {Features} from "../Features.js";
 
 
 var defaultColor = new THREE.Color(1,1,1);//config.applicationName == "zhiHouse" ? Colors.zhiBlue : Colors.lightGreen;
@@ -110,6 +110,12 @@ var LineDraw = {
 	},	 
 	 
 	createFatLineMat : function(o){ 
+    
+        var supportExtDepth = !!Features.EXT_DEPTH.isSupported()  
+    
+        
+    
+    
 		var mat = new LineMaterial( { 
 			color: o.color || 0xffffff,
 			lineWidth: o.lineWidth || 5, // in pixels
@@ -123,8 +129,13 @@ var LineDraw = {
             gapSize: o.gapSize || 0.1,
                
             useDepth: !!o.useDepth,  
-            dashed: !!o.dashed,
+            dashed: o.dashWithDepth ? supportExtDepth && !!o.dashed : !!o.dashed,
             dashWithDepth:!!o.dashWithDepth,//只在被遮住的部分显示虚线
+            
+            supportExtDepth,
+            
+            
+            
            /*  transparent:o.dontAlwaysSeen ? false : true,
 			depthTest:o.dontAlwaysSeen ? true : false
              */
@@ -245,12 +256,30 @@ var MeshDraw = {
 	},
     
     
-    getExtrudeGeo:  function(points, height){//获得挤出棱柱
-        var shape = this.getShape(points)
+    getExtrudeGeo:  function(points, height, extrudePath, tension, closed){//获得挤出棱柱,可以选择传递height,或者extrudePath
+        var shape = this.getShape(points) //points是横截面 [vector2,...]
+        
+        if(extrudePath){// 路径 :[vector3,...]
+            
+            
+            var length = extrudePath.reduce((total, currentValue, currentIndex, arr)=>{
+                if(currentIndex == 0)return 0
+                return total + currentValue.distanceTo(arr[currentIndex-1]);
+            },0)
+            extrudePath = new THREE.CatmullRomCurve3(extrudePath, closed ,  'catmullrom'  /* 'centripetal' */  , tension)
+            
+           
+        }
+        
+        
+        
+        
+        
         var extrudeSettings = {
-            steps: 1,
-            bevelEnabled: false,
+            steps: height != void 0 ? 1 : Math.round(length/0.3), 
             depth: height,
+            extrudePath,
+            
         };
         var geometry = new THREE.ExtrudeBufferGeometry( shape, extrudeSettings );
         return geometry;

+ 21 - 8
src/utils/Magnifier.js

@@ -1,18 +1,23 @@
 
 import * as THREE from "../../libs/three.js/build/three.module.js";
 import math from './math'
+import browser from './browser'
 import Viewport from '../viewer/Viewport'
  
-let texLoader = new THREE.TextureLoader() 
-let circleGeo = new THREE.CircleGeometry(1.45,100);
- 
+const texLoader = new THREE.TextureLoader() 
+const circleGeo = new THREE.CircleGeometry(1.45,100);
+const sphereGeo = new THREE.SphereBufferGeometry(0.018,10,10);
  
  
 const magDistance_ = 2;//相机离目标位置的距离的分界线,当离得远时要缩小fov以使看到的视野固定(望远镜效果)
 const radius_ = 0.2; //当相机离目标位置的距离>magDistance_时,希望看到的视野的半径
 const maxFov = THREE.Math.radToDeg(Math.atan(radius_ / magDistance_ )) * 2//提前计算出当相机离目标位置的距离<magDistance_时的fov,均使用=magDistance_时的fov。只要保证该fov大于主相机的fov就会有放大效果 
-const width2dPX = 200/1.4;//px
-const sphereGeo = new THREE.SphereBufferGeometry(0.02,10,10);
+
+let w = 200/1.4;
+let maxPX = 1366*1024 //ipad pro.  大于这个分辨率的就直接用devicePixelRatio, 如macbook也是
+const width2dPX = window.devicePixelRatio >= 2 ? ( window.screen.width * window.screen.height >= maxPX ? window.devicePixelRatio : window.devicePixelRatio/1.5)*w : w  //触屏或高分辨率的可能要放大些。但在手机上不能太大
+
+
 
 
 export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
@@ -189,11 +194,19 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
         this.quaternion.copy(playerCamera.quaternion);
 
         //mesh位置
-        let screenPos = viewer.inputHandler.mouse.clone();
+        /* let screenPos = viewer.inputHandler.mouse.clone();
         let clientWidth = viewer.inputHandler.domElement.clientWidth * viewer.mainViewport.width;
         let clientHeight = viewer.inputHandler.domElement.clientHeight * viewer.mainViewport.height;
         screenPos.x = screenPos.x / clientWidth * 2 - 1;
-        screenPos.y = -((screenPos.y  < 300 ? 200 : -200) + screenPos.y) / clientHeight * 2 + 1;
+        screenPos.y = -((screenPos.y  < 300 ? 200 : -200) + screenPos.y) / clientHeight * 2 + 1; */
+    
+    
+        let pointer = viewer.inputHandler.pointer.clone();
+        let margin = 0.4, maxY = 0.4
+        let screenPos = pointer.clone().setY(pointer.y + (pointer.y>maxY ? -margin : margin ))
+     
+    
+    
     
                 
         let newPos = new THREE.Vector3(screenPos.x,screenPos.y,0.8).unproject(playerCamera); //z:-1朝外       
@@ -208,7 +221,7 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
         var scale = math.getScaleForConstantSize({// 
             width2d : width2dPX,
             camera:viewer.scene.getActiveCamera(),  position: this.getWorldPosition(new THREE.Vector3()),
-            resolution: viewer.mainViewport.resolution/* 2 */
+            resolution: viewer.mainViewport.resolution2 
         })
         this.scale.set(scale, scale, scale); 
  

+ 5 - 5
src/utils/Measure.js

@@ -11,7 +11,7 @@ import {config} from '../settings'
 
 import {ctrlPolygon} from './ctrlPolygon'
 
-
+ 
 let texLoader = new THREE.TextureLoader()  
 let color = new THREE.Color(config.measure.lineColor)
 let textColor = new THREE.Color(config.measure.textColor)
@@ -397,10 +397,10 @@ export class Measure extends ctrlPolygon{
     
     
     
-    setEdgesDisplay(state){
+    setEdgesDisplay(state, ignoreGuideLine){
         this.closed && this.edgeLabels.forEach(e=>e.setVisible(!!(state && e.shouldVisi))  )
         
-        if(this.measureType == 'Distance'){
+        if(!ignoreGuideLine && this.measureType == 'Distance'){
             this.horEdgeLabel.visible = this.verEdgeLabel.visible = this.horGuideEdge.visible = this.verGuideEdge.visible = !!(state && this.shouldShowHorVerGuide)
         }
     }
@@ -427,7 +427,7 @@ export class Measure extends ctrlPolygon{
             
             //this.areaLabel && this.areaLabel.elem.addClass('highLight')
             //this.closed || this.edgeLabels.forEach(e=>e.elem.addClass('highLight')  )
-            this.setEdgesDisplay(true)
+            this.setEdgesDisplay(true, hoverObject=="screenshot")
             
             this.areaLabel && setLabelHightState(this.areaLabel, true) 
             this.closed || this.edgeLabels.forEach(e=>setLabelHightState(e, true)  )
@@ -436,7 +436,7 @@ export class Measure extends ctrlPolygon{
             this.markers.forEach(e=>this.setMarkerSelected(e,false,'selectAll' ))
             this.edges.forEach(e=>e.material = this.getLineMat('edgeDefault')  )
             this.areaPlane && (this.areaPlane.material = planeMats.default)
-            this.setEdgesDisplay(false)
+            this.setEdgesDisplay(false, hoverObject=="screenshot")
             //this.areaLabel && this.areaLabel.elem.removeClass('highLight')
             //this.closed || this.edgeLabels.forEach(e=>e.elem.removeClass('highLight')  )
             this.areaLabel && setLabelHightState(this.areaLabel, false) 

+ 36 - 12
src/utils/MeasuringTool.js

@@ -516,18 +516,25 @@ export class MeasuringTool extends EventDispatcher{
         }  
           
                  
-        let click = (e)=>{//一旦点击就立刻增加两marker
-            if(measure.unableDragAtMap && e.hoverViewport.name == 'mapViewport' )return 
+        let click = (e)=>{//一旦点击就立刻增加两marker 
+            if(ifAtWrongPlace(e))return  
+            if(e.button === THREE.MOUSE.RIGHT)return 
+             
+            var I = e.intersectPoint && (e.intersectPoint.orthoIntersect || e.intersectPoint.location)
+            if(!I)return
+            
+             
             var marker = measure.addMarker({point:new THREE.Vector3(0, 0, 0)})
             this.viewer.inputHandler.startDragging(marker , {endDragFun, notPressMouse:true} ); //notPressMouse代表不是通过按下鼠标来拖拽
             e.drag = this.viewer.inputHandler.drag
             e.drag.endDragFun = endDragFun
             e.drag.notPressMouse = true
-            e.intersectPoint = this.viewer.inputHandler.intersectPoint
+            
+            //if(!measure.dragMarker(e) || !measure.dropMarker(e))return
+             
             measure.dragMarker(e) 
             measure.dropMarker(e)
             
-            
             measure.markers[1].visible = false
             measure.edges[1].visible = false
             
@@ -540,6 +547,11 @@ export class MeasuringTool extends EventDispatcher{
             
             this.viewer.removeEventListener('global_click', click)///* global_drop */
             
+            
+            
+            console.log('measure clicked')
+            
+            
             return {stopContinue:true}//防止继续执行别的侦听,如flytopano
         }
         
@@ -549,16 +561,28 @@ export class MeasuringTool extends EventDispatcher{
         this.viewer.addEventListener('global_click', click, 10)//add importance:10
             
         let ifAtWrongPlace = (e)=>{
-            if(measure.unableDragAtMap && e.hoverViewport.name == 'mapViewport' ){
-                viewer.dispatchEvent({
-                    type : "CursorChange", action : "add",  name:"polygon_AtWrongPlace"
-                });
-            }else{
-                viewer.dispatchEvent({
-                    type : "CursorChange", action : "remove",  name:"polygon_AtWrongPlace"
-                });
+            if(measure.unableDragAtMap && e.hoverViewport.name == 'mapViewport' ){ 
+                if(e.isTouch){
+                    viewer.emit('reticule_forbit', true)
+                }else{
+                    viewer.dispatchEvent({
+                        type : "CursorChange", action : "add",  name:"polygon_AtWrongPlace"
+                    });
+                } 
+                return true
+            }else{ 
+                if(e.isTouch){
+                    viewer.emit('reticule_forbit', false)
+                }else{
+                    viewer.dispatchEvent({
+                        type : "CursorChange", action : "remove",  name:"polygon_AtWrongPlace"
+                    });
+                }
             }
         }
+        
+        
+        
         if(measure.unableDragAtMap){ 
             this.viewer.addEventListener('global_mousemove', ifAtWrongPlace) 
         }

+ 5 - 7
src/utils/PointCloudSM.js

@@ -1,7 +1,7 @@
 
 import * as THREE from "../../libs/three.js/build/three.module.js";
 
-export class PointCloudSM{
+export class PointCloudSM{//shadow material ?
 
 	constructor(potreeRenderer){
 
@@ -12,10 +12,10 @@ export class PointCloudSM{
 			minFilter: THREE.LinearFilter,
 			magFilter: THREE.LinearFilter,
 			format: THREE.RGBAFormat,
-			type: THREE.FloatType
+			type: THREE.FloatType, 
 		});
 		this.target.depthTexture = new THREE.DepthTexture();
-		this.target.depthTexture.type = THREE.UnsignedIntType;
+		this.target.depthTexture.type = THREE.UnsignedIntType; 
 
 		//this.threeRenderer.setClearColor(0x000000, 1);
 		this.threeRenderer.setClearColor(0xff0000, 1);
@@ -24,10 +24,8 @@ export class PointCloudSM{
 		//this.threeRenderer.clearTarget(this.target, true, true, true); 
 		{
 			const oldTarget = this.threeRenderer.getRenderTarget();
-
-			this.threeRenderer.setRenderTarget(this.target);
-			this.threeRenderer.clear(true, true, true);
-
+			this.threeRenderer.setRenderTarget(this.target); 
+			//this.threeRenderer.clear(true, true, true); //救命,为什么iphoneX ios13.6执行这一句clear会崩溃?即使把target的大小改为1*1.
 			this.threeRenderer.setRenderTarget(oldTarget);
 		}
 	}

+ 2 - 2
src/utils/SplitScreen.js

@@ -92,13 +92,13 @@ var SplitScreen = {
             viewer.scene.pointclouds.forEach(e=>{ 
                 if(viewport.name == "MainView"){ 
                     e.material.activeAttributeName = SplitScreen.statesBefore.mat.colorType 
-                    e.material.color.copy(SplitScreen.statesBefore.mat.color)
+                    //e.material.color = SplitScreen.statesBefore.mat.color
                     e.material.useFilterByNormal = false
                     e.material.opacity = SplitScreen.statesBefore.mat.opacity 
                     Potree.settings.pointDensity = 'fourViewports' //本来想比另外三屏高一点质量,结果发现会闪烁,因为点云加载需要时间 (navvis仿版也是一样,以后看看能否优化)
                 }else{ 
                     e.material.activeAttributeName = "color"
-                    e.material.color.set(e.color)
+                    //e.material.color = e.color
                     e.material.useFilterByNormal = true
                     e.material.opacity =  /* THREE.Math.clamp( */e.material.spacing /* , 0.01,100); */   //0.09 //越稀疏给的opacity应该越高,支持超过1(隧道场景  spacing达9之多) 
                     Potree.settings.pointDensity = 'fourViewports' //强制降低点云质量

+ 7 - 0
src/utils/TransformationTool.js

@@ -37,6 +37,13 @@ export class TransformationTool {
 
 		});
 
+
+        this.viewer.addEventListener('global_touchstart',(e)=>{ //add
+            this.update()
+        })
+
+
+
 		let red = Potree.config.axis.x.color
 		let green = Potree.config.axis.y.color
 		let blue = Potree.config.axis.z.color

+ 24 - 18
src/utils/ctrlPolygon.js

@@ -134,15 +134,12 @@ export class ctrlPolygon extends THREE.Object3D {
         
         var I, atMap 
         
-        if(e.drag.hoverViewport != e.drag.dragViewport)return 
+        if(e.hoverViewport != e.drag.dragViewport)return //不能使用e.dragViewport,要使用drag中的,因为drag中存储的要一直继承下来,不因mouseup了而改变。
         atMap = e.drag.dragViewport.name == 'mapViewport' 
         
-        if(atMap && this.unableDragAtMap){
-            viewer.dispatchEvent({
-                type : "CursorChange", action : "add",  name:"polygon_AtWrongPlace"
-            });
+        if(atMap && this.unableDragAtMap){ 
             e.drag.object = null //取消拖拽
-            return
+            return 
         }
         
         I = e.intersectPoint && (e.intersectPoint.orthoIntersect || e.intersectPoint.location)
@@ -162,12 +159,12 @@ export class ctrlPolygon extends THREE.Object3D {
                     else this.points_datasets[i] = null
                 } 
             }
-            
-            
+            this.editStateChange(true)
+            return true
         }
         
         
-        this.editStateChange(true)
+        
         
     };
     
@@ -340,6 +337,7 @@ export class ctrlPolygon extends THREE.Object3D {
 
         } 
         if(this.retrictArea && !math.isPointInArea(this.retrictArea.points, location)){
+            
             viewer.dispatchEvent({
                 type : "CursorChange", action : "add",  name:"polygon_AtWrongPlace"
             })
@@ -364,8 +362,17 @@ export class ctrlPolygon extends THREE.Object3D {
             return continueDrag(e, this)   
         } 
         
-        if(e.isTouch){
-            this.dragMarker(e) //触屏时必须先更新下点
+        if(e.isTouch){ 
+            if(e.hoverViewport != viewer.mainViewport && this.unableDragAtMap){
+                viewer.emit('reticule_forbit', true)
+                console.log('reticule_forbit',true)
+                return continueDrag(e, this) 
+            }else{
+                viewer.emit('reticule_forbit', false)
+                console.log('reticule_forbit',false)
+            }
+            this.dragMarker(e) //触屏时必须先更新下点 
+            
         }
         
         
@@ -380,7 +387,7 @@ export class ctrlPolygon extends THREE.Object3D {
             return continueDrag(e, this)   
         } 
          
-        
+        //console.log('drop marker' )
          
         let i = this.markers.indexOf(e.drag.object); 
         if (i !== -1) {
@@ -402,7 +409,10 @@ export class ctrlPolygon extends THREE.Object3D {
         
         
         e.drag.endDragFun && e.drag.endDragFun(e)//  addmarker
+         
         if(this.changeCallBack)this.changeCallBack()
+            
+        return true
     };
     
     getFacePlane(){//最普通一种get方法,根据顶点。且假设所有点已经共面,且不重合
@@ -577,12 +587,7 @@ export class ctrlPolygon extends THREE.Object3D {
     
     dispose(){//add 
         this.parent.remove(this)
-        /* viewer.dispatchEvent({
-            type : "CursorChange", action : "remove",  name:"polygon_isIntersectSelf"
-        })
-        viewer.dispatchEvent({
-            type : "CursorChange", action : "remove",  name:"polygon_AtWrongPlace"
-        }) */
+         
     }
     
     
@@ -608,6 +613,7 @@ export class ctrlPolygon extends THREE.Object3D {
             viewer.dispatchEvent({
                 type : "CursorChange", action : "remove",  name:"polygon_AtWrongPlace"
             })
+            viewer.emit('reticule_forbit', false)
         }
     }
     

+ 1 - 1
src/utils/mapClipBox.js

@@ -121,7 +121,7 @@ export class mapClipBox extends ctrlPolygon {
     dragEdge(dragInfo, e){//拖拽一个边(或一个边类型的marker),带动它的两个端点。 可以转化为拖拽marker往法线方向
         var I, atMap 
          
-        atMap = e.drag.dragViewport.name == 'mapViewport'
+        atMap = e.dragViewport.name == 'mapViewport'
         I = e.intersectPoint.orthoIntersect 
         
         if (I && dragInfo.lastPos) {

+ 59 - 43
src/viewer/EDLRenderer.js

@@ -5,7 +5,7 @@ import {EyeDomeLightingMaterial} from "../materials/EyeDomeLightingMaterial.js";
 import {SphereVolume} from "../utils/Volume.js";
 import {Utils} from "../utils.js";
 import {copyShader} from '../materials/shaders/otherShaders'
-
+import {Features} from "../Features.js";
 
 export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 	constructor(viewer){
@@ -17,11 +17,11 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 		this.rtEDL;
 
 		this.gl = viewer.renderer.getContext();
-
-		this.shadowMap = new PointCloudSM(this.viewer.pRenderer);
+        //反正也没用到,注释了:
+		//this.shadowMap = new PointCloudSM(this.viewer.pRenderer);
         
         viewer.addEventListener('resize',this.resize.bind(this))
-        this.initEDL(viewer)
+        this.initEDL(viewer) 
 	}
 
 	initEDL(viewer){
@@ -34,13 +34,20 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 		this.edlMaterial.depthWrite = true;
 		this.edlMaterial.transparent = true;
         
-		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)
-		});
+        
+        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,
@@ -53,7 +60,7 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
         
         
         
-        let copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
+       /*  let copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms );
           
         this.copyMaterial = new THREE.ShaderMaterial(	{
             uniforms: copyUniforms,
@@ -64,15 +71,15 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
             //blending: THREE.AdditiveBlending,
             depthTest: false,
             depthWrite: false
-        });
+        }); */
         
 	};
 
-	resize(e){
-        let viewport = e.viewport
-		this.rtEDL.setSize(viewport.resolution2.x, viewport.resolution2.y);
-		//this.rtRegular.setSize(e.resolution.x, e.resolution.y);
-        
+	resize(e,  aaa){
+        if(Features.EXT_DEPTH.isSupported()){  
+            let viewport = e.viewport
+            this.rtEDL.setSize(viewport.resolution2.x, viewport.resolution2.y);
+        }
 	}
 
 	
@@ -87,14 +94,21 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
             renderer.setRenderTarget( params.target);
             renderer.clear() 
         }
-        if(params.rtEDL){
-            renderer.setRenderTarget( params.rtEDL);
-            renderer.clear() 
-        }else{
-            renderer.setRenderTarget( this.rtEDL );
-            renderer.clear( true, true, true );
+        
+        
+        
+        if(Features.EXT_DEPTH.isSupported()){ 
+            if(params.rtEDL){
+                renderer.setRenderTarget( params.rtEDL);
+                renderer.clear() 
+            }else{
+                renderer.setRenderTarget( this.rtEDL );
+                renderer.clear( true, true, true );
+            }
         }
-
+        
+        
+        
 		//renderer.setRenderTarget( this.rtRegular );
 		//renderer.clear( true, true, false );
 
@@ -138,7 +152,8 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 	}
 
 	render(params={}){
-        
+
+         
         /* 
             渲染顺序:
                 底层:背景 -> skybox(也可中间)
@@ -169,11 +184,11 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
         
  
 		let lights = [];
-		viewer.scene.scene.traverse(node => {
+		/* viewer.scene.scene.traverse(node => {
 			if(node.type === "SpotLight"){
 				lights.push(node);
 			}
-		});
+		}); */
 
 
         viewer.renderer.setRenderTarget(params.target || null);
@@ -215,7 +230,7 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
         camera.layers.set(Potree.config.renderLayers.pointcloud);
 		
         //TODO adapt to multiple lights
-		this.renderShadowMap(visiblePointClouds2, camera, lights);  //???????
+		//this.renderShadowMap(visiblePointClouds2, camera, lights);  //???????
 
 		{ //scenePointCloud   COLOR & DEPTH PASS
 			for (let pointcloud of visiblePointClouds2) {
@@ -241,19 +256,20 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
                 }  
                 
 			}
-			
             
-            //借用rtEDL存储深度信息 
-            viewer.renderer.setRenderTarget(params.rtEDL || this.rtEDL);
-         
             
-            //渲染scenePointCloud到rtEDL
-            viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, params.rtEDL || this.rtEDL, {
-                shadowMaps:  lights.length > 0 ? [this.shadowMap] : null,
-                clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
-                transparent: false,
-            });
-             
+            if(Features.EXT_DEPTH.isSupported()){   
+                //借用rtEDL存储深度信息 
+                viewer.renderer.setRenderTarget(params.rtEDL || this.rtEDL);
+                
+                
+                //渲染scenePointCloud到rtEDL
+                viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, params.rtEDL || this.rtEDL, {
+                    shadowMaps:  lights.length > 0 ? [this.shadowMap] : null,
+                    clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
+                    transparent: false,
+                });
+            } 
 		}
         
         
@@ -271,9 +287,9 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
          
         
        //设置edlMaterial
-        if(viewer.useEDL && showPointClouds  /* || params.magnifier */) {
-            // EDL PASS
-
+        if(viewer.useEDL && showPointClouds  /* || params.magnifier */) { 
+            //Features.EXT_DEPTH不支持的话不会到这一块
+             
 			const uniforms = this.edlMaterial.uniforms;
             //if(viewer.useEDL){
                 uniforms.screenWidth.value = width;

+ 2 - 2
src/viewer/Scene.js

@@ -19,8 +19,8 @@ export class Scene extends EventDispatcher{
         //this.sceneOverlay = new THREE.Scene();  
 		this.scenePointCloud = new THREE.Scene();
 
-		this.cameraP = new THREE.PerspectiveCamera(this.fov, 1, 0.1, Potree.settings.cameraFar);
-		this.cameraO = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, Potree.settings.cameraFar);
+		this.cameraP = new THREE.PerspectiveCamera(this.fov, 1, Potree.config.view.near, Potree.config.view.near);
+		this.cameraO = new THREE.OrthographicCamera(-1, 1, 1, -1, Potree.config.view.near, Potree.settings.cameraFar);
         this.cameraP.limitFar = true//add
         
 		this.cameraVR = new THREE.PerspectiveCamera();

+ 7 - 4
src/viewer/map/Map.js

@@ -36,7 +36,7 @@ const MAX_VERTICAL_DIST_TO_BEST = 1
 
 
 
-
+//高德坐标拾取工具 : https://lbs.amap.com/tools/picker
 
 
 export class MapLayer extends EventDispatcher{ // 包括了 MapLayerBase SceneLayer
@@ -44,7 +44,7 @@ export class MapLayer extends EventDispatcher{ // 包括了 MapLayerBase SceneLa
         super()
         this.sceneGroup = new THREE.Object3D;
         this.sceneGroup.name = "MapLayer" 
-        
+         
         
         this.loadingInProgress = 0
         this.maps = [] 
@@ -55,7 +55,9 @@ export class MapLayer extends EventDispatcher{ // 包括了 MapLayerBase SceneLa
         this.changeViewer(viewer_) 
         //添加地图
         var map = new TiledMapOpenStreetMap(this, this.tileColor )
-        this.addMap(map)
+        this.addMap(map) 
+        
+
         //map.setEnable(false)
         
         
@@ -68,6 +70,7 @@ export class MapLayer extends EventDispatcher{ // 包括了 MapLayerBase SceneLa
     }
     
     addMapEntity(data){
+         
         if(!data || !data[0]){ 
             Potree.Log('平面图无数据','red')
             return
@@ -223,7 +226,7 @@ export class TiledMapBase extends EventDispatcher{
             this._zoomLevel = zoomLevel
             this.emit('zoomLevelChange',zoomLevel)
              
-            if(this.name == 'map')console.log(zoomLevel,viewer.mapViewer.camera.zoom)
+            //if(this.name == 'map')console.log(zoomLevel,viewer.mapViewer.camera.zoom)
         }
     }
     

+ 126 - 33
src/viewer/map/MapViewer.js

@@ -8,8 +8,8 @@ import {InputHandler} from "../../navigation/InputHandler.js";
 import {ViewerBase} from "../viewerBase.js"
 import math from "../../utils/math.js";
 //import CursorDeal from '../utils/CursorDeal' 
- 
- 
+import {Images360} from '../../modules/Images360/Images360'
+import Common from '../../utils/Common' 
 import {transitions, easing, lerp} from "../../utils/transitions.js";
 
 /* var centerCross = new THREE.Mesh(new THREE.SphereGeometry(1, 4, 4),new THREE.MeshBasicMaterial({
@@ -31,36 +31,52 @@ const markerSize = 1;
 
 var initCameraFeildWidth = 50
 var panoMarkerMats  
-
-
+ 
 
 export class MapViewer extends ViewerBase{
     constructor(dom){
         super(dom, {
-            clearColor: Potree.config.mapBG
+            clearColor: Potree.config.mapBG,
+            name: 'mapViewer'
         })
-       
+        this.visible = true
         this.initScene()
          
          
         this.mapLayer = new MapLayer(this, this.viewports[0])
         this.scene.add(this.mapLayer.sceneGroup)
         this.mapLayer.sceneGroup.position.setZ(mapHeight)
+        this.mapRatio = 0.5
+        this.splitDir = 'leftRight'
         
         
         //this.scene.add(centerCross)
         
         //CursorDeal.attachToViewer(this)
-        viewer.addEventListener("camera_changed", this.updateWhenAtViewer.bind(this)); 
-        viewer.addEventListener("global_mousemove", this.updateWhenAtViewer.bind(this))  //鼠标移动时reticule也动,所以直接就needRender
+        viewer.addEventListener("camera_changed", (e)=>{
+            if(e.viewport == viewer.mainViewport) this.updateCursor()
+            else this.updateWhenAtViewer() 
+        })
         
          
+        //viewer.addEventListener("global_mousemove", this.updateWhenAtViewer.bind(this))  //鼠标移动时reticule也动,所以直接就needRender
+        viewer.reticule.addEventListener('update',(e)=>{
+            this.needRender = true
+        })
+         
         
         viewer.scene.addEventListener("360_images_added", this.addPanos.bind(this))
         
         
         viewer.addEventListener("loadPointCloudDone",  this.initProjection.bind(this))
         
+        this.addEventListener('global_click',(e)=>{
+            if(!e.isTouch && e.button != THREE.MOUSE.LEFT)return
+            this.updateClosestPano(e.intersectPoint)
+        })
+        
+        
+        
         this.on('add',(e)=>{//添加其他mesh
             this.scene.add(e.object)
             if(e.name == 'route'){
@@ -70,6 +86,9 @@ export class MapViewer extends ViewerBase{
         })
         
         
+        
+        
+        
         if(!Potree.settings.isOfficial){
             let domRoot = viewer.renderer.domElement.parentElement; 
             let elAttach = $("<input type='button' value='map绑定'></input>");
@@ -94,6 +113,10 @@ export class MapViewer extends ViewerBase{
         
     }
     
+    
+    
+    
+    
     waitLoadDone(callback){//确保加载完后执行
         if(this.mapLayer.loadingInProgress == 0){
             callback()
@@ -187,15 +210,16 @@ export class MapViewer extends ViewerBase{
      
     
     updateCursor(){
+         
         var scale = math.getScaleForConstantSize( {//规定下最小最大像素
             minSize : 80,  maxSize : 180,   nearBound : initCameraFeildWidth*0.1 , farBound : initCameraFeildWidth*2,
             camera:this.camera , position: this.cursor.getWorldPosition(new THREE.Vector3()),
             resolution: this.viewports[0].resolution//2
         })
-        this.cursor.scale.set(scale, scale, scale);
-        this.cursor.position.copy(viewer.mainViewport.camera.position).setZ(cursorHeight)
+        this.cursor.scale.set(scale, scale, scale);//当地图缩放时
+        this.cursor.position.copy(viewer.mainViewport.camera.position).setZ(cursorHeight)//当场景镜头旋转移动时
         this.cursor.rotation.z = viewer.mainViewport.view.yaw
-        
+        this.needRender = true
     }
     
     addPanos(e){
@@ -248,7 +272,7 @@ export class MapViewer extends ViewerBase{
             let onclick = (e)=>{
                 viewer.images360.flyToPano(pano)
             }
-            pano.mapMarker.addEventListener('click', onclick);
+            pano.mapMarker.addEventListener('click', onclick); 
             
             pano.addEventListener('isVisible',(e)=>{//是否显示该点的mesh(不显示也能走) 
                 viewer.updateVisible(pano.mapMarker, 'panoVisible', e.visible )
@@ -275,6 +299,36 @@ export class MapViewer extends ViewerBase{
     
     
     
+    updateClosestPano(intersect){
+        if(viewer.images360.flying)return; 
+        intersect = intersect && intersect.orthoIntersect
+        if(!intersect)return
+        
+        intersect = intersect.clone().setZ(0)
+        
+        const minDis = 20 //距离鼠标不能太远
+
+        
+        var filterFuncs = []; 
+      
+        
+        filterFuncs.push((pano)=>{
+            return pano.position.clone().setZ(0).distanceTo(intersect) < minDis
+            
+        });
+        
+    
+        
+        
+        var pano = Common.find(viewer.images360.panos,  filterFuncs, [Images360.sortFunctions.floorDistanceToPoint(intersect)]);
+        if (pano && pano != viewer.images360.currentPano ) {
+           viewer.images360.flyToPano(pano)
+            
+        }   
+          
+    }
+    
+    
     fitPanosToViewport(){//使所有漫游点占满viewport 
         
         //var w = viewer.bound.boundSize.x;
@@ -330,20 +384,20 @@ export class MapViewer extends ViewerBase{
     
     
     updateWhenAtViewer(e){
-        if(this.attachedToViewer){
-            if(!e || e.viewport == this.viewports[0]){ 
-                if(this.started) this.mapLayer.update() 
-                
-            }
+        if(this.attachedToViewer){ 
+            if(this.started) this.mapLayer.update()  
+            
+            this.updateCursor() 
+            this.needRender = true
         } 
-        this.needRender = true
-        
-        this.updateCursor()//更改大小 
     }
     
     update(delta, areaSize ){
+        if(!this.visible && !this.attachedToViewer )return
+        
+        
         if(this.attachedToViewer){
-            if(this.mapLayer.needUpdate){//必须更新
+            if(this.mapLayer.needUpdate){//必须更新。(较少触发)
                 this.updateWhenAtViewer()
             }
             return
@@ -375,15 +429,17 @@ export class MapViewer extends ViewerBase{
         
     }
     
-    attachToMainViewer(state, desc, mapWidthRatio=0.5, options={}){//转移到viewer中。测量时展示or截图需要
+    attachToMainViewer(state, desc, mapRatio=0.5, options={}){//转移到viewer中。测量时展示or截图需要
         
         if(!Potree.settings.isOfficial)this.renderArea.style.display = state ? 'none':'block'
-         
+        
         if(state){
-            if(mapWidthRatio != 'dontSet'){
-                viewer.mainViewport.left = mapWidthRatio
-                viewer.mainViewport.width = 1-mapWidthRatio
-                this.viewports[0].width = mapWidthRatio; 
+            this.enabledOld = this.enabled
+            this.enabled = true
+            
+            if(mapRatio != 'dontSet'){
+                this.changeSplitScreenDir(options.dir, mapRatio)
+                 
                 if(this.attachedToViewer){ 
                     //this.fitPanosToViewport() 
                     viewer.updateScreenSize({forceUpdateSize:true})        
@@ -402,8 +458,9 @@ export class MapViewer extends ViewerBase{
             if(!this.attachedToViewer)return
              
             viewer.mainViewport.left = 0;
+            viewer.mainViewport.bottom = 0;
             viewer.mainViewport.width = 1;
-             
+            viewer.mainViewport.height = 1;
              
             this.viewports[0].width = 1;
             this.viewports[0].bottom = 0;
@@ -426,18 +483,53 @@ export class MapViewer extends ViewerBase{
         viewer.updateScreenSize({forceUpdateSize:true})
         
         
-        //mapWidthRatio != 'dontSet' && !options.dontFit && this.moveTo(...)//要写在updateScreenSize后面,因为要根据视图大小来fit
+        //mapRatio != 'dontSet' && !options.dontFit && this.moveTo(...)//要写在updateScreenSize后面,因为要根据视图大小来fit
         if(options.moveToCurrentPano){
             let boundSize = new THREE.Vector2(10,10)
             let duration = 1000
             this.moveTo(viewer.images360.currentPano.position.clone(), boundSize, duration)
-        }            
+        }    
+        this.needRender = true
     }
-  
     
+    changeSplitScreenDir(dir, mapRatio){//左右 | 上下
+        //if(!dir || dir == this.dir)return
+        if(dir )this.splitDir = dir
+        this.updateSplitSize(mapRatio)
+        /* if(this.attachedToViewer){ //如果已经分屏了,中途修改方向的话……
+            this.updateSplitSize()
+        } */ 
+    }
+    updateSplitSize(mapRatio){
+        if(mapRatio != void 0) this.mapRatio = mapRatio
+        
+        //console.log(this.mapRatio)
+        
+        if(this.splitDir == 'leftRight'){//地图在左方
+            viewer.mainViewport.left = this.mapRatio
+            viewer.mainViewport.width = 1-this.mapRatio
+            this.viewports[0].width = this.mapRatio; 
+            
+            viewer.mainViewport.bottom = this.viewports[0].bottom = 0
+            viewer.mainViewport.height = this.viewports[0].height = 1
+             
+        }else if(this.splitDir == 'upDown'){ //地图在下方
+            viewer.mainViewport.bottom = this.mapRatio
+            viewer.mainViewport.height = 1-this.mapRatio
+            this.viewports[0].height = this.mapRatio;  
+            
+            viewer.mainViewport.left = this.viewports[0].left = 0
+            viewer.mainViewport.width = this.viewports[0].width = 1
+            
+        }
+        if(this.attachedToViewer){ 
+            viewer.updateScreenSize({forceUpdateSize:true})
+        }
+    }
     
     render(params={}){
-        if(!this.needRender && !params.force)return
+       
+        if(!this.visible && !this.attachedToViewer || !this.needRender && !params.force)return
         
         let renderer = params.renderer || this.renderer
         
@@ -449,6 +541,7 @@ export class MapViewer extends ViewerBase{
         } 
         params.clear ? params.clear() : renderer.clear(); 
         
+         
         viewer.setCameraLayers(this.camera, ['map','mapObjects'  , 'bothMapAndScene'  ])
         
         if(this.mapGradientBG){//渲染背景
@@ -460,7 +553,7 @@ export class MapViewer extends ViewerBase{
         renderer.render(viewer.scene.scene, this.camera);
         //测量线
         //if(this.renderMeasure)viewer.dispatchEvent({type: "render.pass.perspective_overlay", viewer: viewer, camera:this.camera});
-        params.renderOverlay && params.renderOverlay({camera:this.camera, isMap:true })//其余如reticule
+        params.renderOverlay && params.renderOverlay({camera:this.camera, isMap:true })//其余如reticule 等场景层
         
         
         

+ 1 - 1
src/viewer/sidebar.js

@@ -143,7 +143,7 @@ export class Sidebar{
         pannel.find('button[name="exit"] ').on('click', SiteModel.leave.bind(SiteModel))
         pannel.find('button[name="building"] ').on('click', SiteModel.startInsertion.bind(SiteModel,'building'))
         pannel.find('button[name="floor"] ').on('click', ()=>{
-            SiteModel.addFloor(SiteModel.buildings[0], SiteModel.buildings[0].buildChildren[0])
+            SiteModel.addFloor(SiteModel.buildings[0], 'top')
         } )  
         pannel.find('button[name="room"] ').on('click', ()=>{
             SiteModel.startInsertion('room', SiteModel.buildings[0].buildChildren[0])

+ 147 - 27
src/viewer/viewer.js

@@ -56,13 +56,22 @@ import math from "../utils/math.js";
  
 import {UoMService}  from '../utils/UnitConvert'
 import {RouteGuider}  from '../navigation/RouteGuider'
+import {MeshDraw}  from '../utils/DrawUtil'
+
+
+
+
+
+
+
+
 
 let mapArea; 
 
 export class Viewer extends ViewerBase{
 	
 	constructor(domElement, mapArea_, args = {}){
-		super(domElement,args);
+		super(domElement, $.extend(args,{name:'mainViewer'}));
         window.viewer = this
         this.modules = { //add
             Clip : Clip,
@@ -80,10 +89,12 @@ export class Viewer extends ViewerBase{
         this.waitQueue = []  
         this.unitConvert = new UoMService();
         mapArea = mapArea_
+        this.visible = true
 		//-------------
         
-        this.supportExtFragDepth = !!this.renderer.getContext().getExtension('EXT_frag_depth') ;//iphoneX居然不支持
-        console.log('this.supportExtFragDepth ',this.supportExtFragDepth)
+        var supportExtFragDepth = !!Features.EXT_DEPTH.isSupported() ;//iphoneX居然不支持
+        //这意味着边缘增强和测量线遮挡失效
+        if(!supportExtFragDepth)console.error('ExtFragDepth unsupported! 边缘增强和测量线遮挡失效')
         
         
 		this.guiLoaded = false;
@@ -99,8 +110,19 @@ export class Viewer extends ViewerBase{
 		$(domElement).append(this.elMessages);
 		
          
+        this.paused  
+         
         document.addEventListener('visibilitychange',(e)=>{ 
+            console.log('visibilitychange', !document.hidden )
             this.emit('pageVisible', !document.hidden )
+            /* if(document.hidden){
+                this.paused = true
+            }else{
+                setTimeout(()=>{
+                    if(!document.hidden) this.paused = false
+                },1000)
+            } */
+            
         })
         
          
@@ -335,6 +357,7 @@ export class Viewer extends ViewerBase{
                 this.mapViewer = new MapViewer(mapArea/* $('#mapGaode')[0] */)
                 
                 
+                
                 //---------------------------
                 
                 
@@ -425,6 +448,8 @@ export class Viewer extends ViewerBase{
         //-----------------------add----------------------------------------------------
         
         
+         
+        
         {
             let ratio
             this.addEventListener('resize',(e)=>{
@@ -445,7 +470,7 @@ export class Viewer extends ViewerBase{
                     return pointDensity
                 },
                 set: (density)=>{
-                    if(density){  
+                    if(density && density != pointDensity){  
                         var config = Potree.config.pointDensity[density];
                         viewer.setPointBudget(config.pointBudget );
                         //Potree.maxPointLevel = config.maxLevel
@@ -839,7 +864,7 @@ export class Viewer extends ViewerBase{
 
 	setEDLEnabled (value) {
 		value = Boolean(value) && Features.SHADER_EDL.isSupported();
-
+        
 		if (this.useEDL !== value) {
 			this.useEDL = value;
 			this.dispatchEvent({'type': 'use_edl_changed', 'viewer': this});
@@ -2100,7 +2125,7 @@ export class Viewer extends ViewerBase{
 
 		TWEEN.update(timestamp);
         transitions.update(delta);
-        
+        this.transformationTool.update();
              
 
 		this.dispatchEvent({
@@ -2148,26 +2173,26 @@ export class Viewer extends ViewerBase{
         
         if(!camera.limitFar && result.lowestSpacing !== Infinity){
             
-            let near = result.lowestSpacing * 10.0;
+            //let near = result.lowestSpacing * 10.0;
             let far = -this.getBoundingBox().applyMatrix4(camera.matrixWorldInverse).min.z;
 
             far = Math.max(far * 1.5, 10000);
-            near = Math.min(100.0, Math.max(0.01, near));
-            near = Math.min(near, closestImage);
+            //near = Math.min(100.0, Math.max(0.01, near));
+            //near = Math.min(near, closestImage);
             far = Math.max(far, near + 10000);
 
-            if(near === Infinity){
+            /* if(near === Infinity){
                 near = 0.1;
-            }
+            } */
             
-            camera.near = near;
+            //camera.near = near;  //为了其他物体的显示,不修改near
             camera.far = far;
         }  
 
-        if(this.scene.cameraMode == CameraMode.ORTHOGRAPHIC) {//???
+        /* if(this.scene.cameraMode == CameraMode.ORTHOGRAPHIC) {//???
             camera.near = -camera.far;
-        }
-        if(near != camera.near || far != camera.far){
+        } */
+        if(/* near != camera.near ||  */far != camera.far){
             camera.updateProjectionMatrix()
         }  
          
@@ -2400,7 +2425,11 @@ export class Viewer extends ViewerBase{
     
 
 	renderDefault(params_={}){
+        
+        if(!this.visible   || this.paused  )return
+        
 		let pRenderer = this.getPRenderer();
+        
         let renderSize
         if(params_.target){
             renderSize =  new THREE.Vector2(params_.target.width, params_.target.height)
@@ -2492,8 +2521,9 @@ export class Viewer extends ViewerBase{
                 params.background = view.background
                 params.backgroundColor = view.backgroundColor
                 params.backgroundOpacity = view.backgroundOpacity
-                view.render || this.clear(params) 
-                pRenderer.clearTargets(params);  
+                
+                view.render || this.clear(params)  
+                pRenderer.clearTargets(params);
                 pRenderer.render(params);
                 
                 
@@ -2525,14 +2555,22 @@ export class Viewer extends ViewerBase{
     }
     
     renderOverlay(params){
+        
         let camera = params.camera ? params.camera : this.scene.getActiveCamera();
         
         
         
         
          //为什么要在点云之后渲染,否则透明失效 、 会被点云覆盖 
-         
-        let cameraLayers = params.cameraLayers || ['sceneObjects','marker','reticule','route',/* 'bothMapAndScene' */];
+        let cameraLayers
+
+        if(params.cameraLayers) cameraLayers = params.cameraLayers
+        else{
+            if(params.isMap)cameraLayers = ['reticule']
+            else cameraLayers = ['sceneObjects','marker','reticule'  /* 'bothMapAndScene' */];
+        }
+        
+   
         if(cameraLayers.length){
             this.setCameraLayers(camera,  cameraLayers, params.extraEnableLayers) //透明贴图层 skybox 、reticule marker 不能遮住测量线
             this.renderer.render(this.scene.scene, camera); 
@@ -2543,7 +2581,7 @@ export class Viewer extends ViewerBase{
         //清除深度 !!!!
         this.renderer.clearDepth(); 
 
-        this.transformationTool.update();
+        //this.transformationTool.update();
          
          
          
@@ -2638,6 +2676,7 @@ export class Viewer extends ViewerBase{
      
 	render(params){//add params
 		if(Potree.measureTimings) performance.mark("render-start");
+        // if(!window.unableSetSize)   return
 
 		//try{
             //console.log('rendering')//在unfocus页面时就会停止渲染
@@ -2787,7 +2826,7 @@ export class Viewer extends ViewerBase{
             viewer.updateScreenSize({forceUpdateSize:true, width, height}) //更新viewports相机透视
             
             //不同角度截图 得到三维的会不一样,因为focusOnObject是根据方向的
-            let promise = this.focusOnObject(info.measurement, 'measure', 0,    {basePanoSize:1024} )
+            let promise = this.focusOnObject(info.measurement, 'measure', 0,    /* {basePanoSize:1024} */ )
             promise.done(()=>{ 
                 console.log('promise.done') 
                 this.viewports.forEach(e=>{
@@ -2824,7 +2863,7 @@ export class Viewer extends ViewerBase{
                 
                 //调不通,暂时先用setTimeout
                  
-                setTimeout(waitMap.bind(this), 300)
+                setTimeout(waitMap.bind(this), 1)
             })
             
         }else{
@@ -2960,16 +2999,21 @@ export class Viewer extends ViewerBase{
                 this.mapViewer.moveTo(target.clone(), boundSizeMap, duration)
             }
             
-            
+            let dir = new THREE.Vector3().subVectors(cameraTemp.position, target).normalize()
+            position.copy(target).add(dir.multiplyScalar(dis))
             if(Potree.settings.displayMode == 'showPointCloud'){  //点云 
-                let dir = new THREE.Vector3().subVectors(cameraTemp.position, target).normalize()
-                position.copy(target).add(dir.multiplyScalar(dis))
+                
                  
             }else if(Potree.settings.displayMode == 'showPanos'){//全景 (比较难校准)
                 let pano = viewer.images360.fitPanoTowardPoint({
-                    point : target, 
+                    /*point : target, 
                     //bestDistance : dis * 0.5, //乘以小数是为了尽量靠近 
-                    boundSphere: boundOri.getBoundingSphere(new THREE.Sphere),
+                    boundSphere: boundOri.getBoundingSphere(new THREE.Sphere), */
+                    
+                    point : position,
+                    bestDistance : 0 , 
+                    
+                    
                 })
                 pano && viewer.images360.flyToPano({pano, target, duration, deferred, dontMoveMap:true  , basePanoSize:o.basePanoSize})//dontMoveMap不要移动map,否则flytopano会自动在map中focus到漫游点的位置,而非测量线了
                 
@@ -3288,6 +3332,82 @@ export class Viewer extends ViewerBase{
     }
     
     
+    
+    //调试时显示transformControl来调节object
+    transformObject(object){
+        if(!object.boundingBox){
+            object.boundingBox = new THREE.Box3() //任意大小 只是为了显示黄色外框
+            //??? computeBoundingBox
+        }
+        viewer.inputHandler.toggleSelection(object);   
+    }
+    
+    
+    addObjectTest(){//加水管
+        
+        if(Potree.settings.number == 't-8KbK1JjubE'){
+            
+            let boundingBox = new THREE.Box3()
+            boundingBox.min.set(-1,-1,-1); boundingBox.max.set(1,1,1)
+            
+            
+            let radius = 0.08;
+            let radialSegments = 5 
+            let radSegments = Math.PI*2 / radialSegments
+            var circlePts = [];//横截面
+            for(let i=0;i<radialSegments;i++){
+                let angle = radSegments * i;
+                circlePts.push(new THREE.Vector2(radius * Math.cos(angle),   radius * Math.sin(angle) ))
+            }  
+            var count = 0
+            var addMesh = (color, path, height)=>{//height:在path之上的高度,负数代表在path之下
+                var name = 'cylinder'+count
+                var mat = new THREE.MeshStandardMaterial({color, /* wireframe:true, */ depthTest:false, roughness:0.4,metalness:0.5}) 
+                let linePath = path.map(e=>new THREE.Vector3().copy(e).setZ(e.z+height))
+                let geo = MeshDraw.getExtrudeGeo( circlePts, null, linePath, 0.2)
+                var mesh = new THREE.Mesh(geo,mat);
+                mesh.name = name
+                window[name] = mesh
+                
+                mesh.boundingBox = boundingBox
+                mesh.matrixAutoUpdate = false
+                mesh.matrix.copy(viewer.scene.pointclouds[0].transformMatrix)
+                mesh.matrixWorldNeedsUpdate = true
+                
+                this.scene.scene.add(mesh);
+                 
+                count ++
+            }
+            
+            
+            let linePath, height 
+            
+            //地上管子 黄色
+            /* linePath = [{"x":-109.83,"y":-68.33,"z":-7.52},{"x":-95.17,"y":-59.3,"z":-7.38},  {"x":-38.75,"y":-24.01,"z":-6.01},{"x":0.5,"y":0.19,"z":-3.89},{"x":42.76,"y":26.88,"z":-1.03}
+               ,   {"x":44.27,"y":28.63,"z":-0.89},{"x":40.22,"y":35.37,"z":-0.67}// 拐弯向右 
+               ,    {"x":40.25,"y":36.47,"z":-0.6},{"x":38.69,"y":36.04,"z":18.04}// 拐弯向右 
+            ] */
+            linePath = [{"x":-109.83,"y":-68.33,"z":-7.52},{"x":-95.17,"y":-59.3,"z":-7.38},  {"x":-38.75,"y":-24.01,"z":-6.01},{"x":0.5,"y":0.19,"z":-3.89},{"x":39.29,"y":24.41,"z":-1.31}
+               ,{"x":43.58,"y":27.7,"z":-0.97},{"x":40.22,"y":35.37,"z":-0.67}// 拐弯向右 
+               ,   {"x":39.18,"y":36.71,"z":0.35},{"x":38.69,"y":36.04,"z":18.04} // 拐弯向上  
+            ]
+            height = radius + 0.05;
+            addMesh('#b86', linePath, height)
+             
+             
+            
+            //地下管子 藍色
+            linePath = [{"x":-108.24,"y":-70.61,"z":-7.52}, {"x":-57.8,"y":-39.31,"z":-6.72},{"x":-18.8,"y":-15.35,"z":-5.01},{"x":55.87,"y":31.67,"z":-0.04},{"x":110.53,"y":66.48,"z":5.14}
+            ]
+            height = -0.5;
+            addMesh('#48a', linePath, height)
+              
+            
+            
+        }
+        
+        
+    }
      
 };
 

+ 30 - 6
src/viewer/viewerBase.js

@@ -8,7 +8,7 @@ import { EventDispatcher } from "../EventDispatcher.js";
 export class ViewerBase extends EventDispatcher{
     constructor(domElement, args = {}){
         super()
-        
+        this.name = args.name
         this.renderArea = domElement 
         this.oldResolution = new THREE.Vector2()
         
@@ -66,7 +66,8 @@ export class ViewerBase extends EventDispatcher{
             canvas: canvas,
             context: context,
             
-        });     
+        }); 
+        
         this.renderer.sortObjects = true; //原先false 打开了renderOrder才奏效
         //this.renderer.setSize(width, height);
         this.renderer.autoClear = args.autoClear;
@@ -82,6 +83,13 @@ export class ViewerBase extends EventDispatcher{
         // NOTE: If extension errors occur, pass the string into this.renderer.extensions.get(x) before enabling
         // enable frag_depth extension for the interpolation shader, if available
         let gl = this.renderer.getContext();
+        
+        
+        
+            
+      
+        
+        
         gl.getExtension('EXT_frag_depth');
         gl.getExtension('WEBGL_depth_texture');
         gl.getExtension('WEBGL_color_buffer_float'); 	// Enable explicitly for more portability, EXT_color_buffer_float is the proper name in WebGL 2
@@ -96,13 +104,17 @@ export class ViewerBase extends EventDispatcher{
             gl.createVertexArray = extVAO.createVertexArrayOES.bind(extVAO);
             gl.bindVertexArray = extVAO.bindVertexArrayOES.bind(extVAO);
         }
+        
+        
+       
+        
     }
     
     
     
     
     updateScreenSize(o={}) { //有可能需要让viewport来判断,当窗口大小不变但viewport大小变时 
-          
+           
         var render = false, ratio, w, h;
         //记录应当render的大小
         if (o.width != void 0 && o.height != void 0) {
@@ -121,15 +133,24 @@ export class ViewerBase extends EventDispatcher{
                 this.screenSizeInfo.pixelRatio = window.devicePixelRatio  //如果player放在小窗口了,也要监测devicePixelRatio,因为缩放时client宽高不会改变
                 //config.isMobile ? (ratio = Math.min(window.devicePixelRatio, 2)) : (ratio = window.devicePixelRatio)
                 ratio = window.devicePixelRatio
-            }    
+            }     
         }
         if (render) {
             this.setSize(w, h, ratio); 
         } 
     } 
-    
+     
     setSize(width, height, devicePixelRatio){
+        
+        
+        console.log('setSize',width,height, this.name) 
+        
+         
+        //if(width == 0 || height == 0)return;
+        
         this.renderer.setSize(width, height, null, devicePixelRatio); // resize之后会自动clear(似乎因为setScissor ),所以一定要立刻绘制,所以setSize要在cameraChanged、update之前
+        
+       
         //this.composer.setSize(width, height);
         
         if(this.viewports){
@@ -139,6 +160,8 @@ export class ViewerBase extends EventDispatcher{
                 var width_ = width * view.width
                 var height_ = height * view.height
                 
+                if(height_ == 0)return  //avoid NAN
+                
                 view.setResolution(Math.floor(width_), Math.floor(height_), width, height )
                 let aspect = width_ / height_;  //camera的参数精确些,不用视口的归整的resolution像素值,否则hasChange无法为true, 导致canvasResize了但map没update从而闪烁
                 view.camera.aspect = aspect;
@@ -173,8 +196,9 @@ export class ViewerBase extends EventDispatcher{
     emitResizeMsg(e){//切换viewport渲染时就发送一次, 通知一些材质更新resolution。  
         if(!e.viewport.resolution.equals(this.oldResolution)){ 
             this.dispatchEvent($.extend(e, {type:'resize'})) 
+            this.oldResolution.copy(e.viewport.resolution)
         }
-        this.oldResolution.copy(e.viewport.resolution)
+        
         
     }