xzw 1 سال پیش
والد
کامیت
6b903ac25e

+ 53 - 22
src/PotreeRendererNew.js

@@ -736,8 +736,8 @@ export class Renderer {
         shader.setUniform1f("uOpacity", material.usePanoMap ? 1: material.opacity);
         shader.setUniform3f("uColor", material.color.toArray());
         
-       /*  let currentTextureBindingPoint = params.currentTextureBindingPoint
-        if (material.pointSizeType >= 0 && window.needvisibilityTexture) {
+        let currentTextureBindingPoint = params.currentTextureBindingPoint
+        if (material.pointSizeType >= 0/*  && window.needvisibilityTexture */) {
             
 			if (material.pointSizeType === PointSizeType.ADAPTIVE ||
 				material.activeAttributeName === "level of detail") {
@@ -749,7 +749,10 @@ export class Renderer {
 				const data = vnt.image.data;
 				data.set(visibilityTextureData.data);
 				vnt.needsUpdate = true;
-                 
+                
+                let webGLTexture = this.textures.get(vnt)  
+                webGLTexture.update();      //不加这个会闪烁
+                
                 
                 let vnWebGLTexture = this.textures.get(material.visibleNodesTexture);       //不知道为什么这段从renderOctree中移过来,会崩溃。暂时不移动了
                 if(vnWebGLTexture){
@@ -759,7 +762,39 @@ export class Renderer {
                     currentTextureBindingPoint++;
                 }   
 			}
-		} */  
+		}  
+        
+        
+        
+        
+        
+        
+        /* if (material.pointSizeType >= 0) {
+			if (material.pointSizeType === PointSizeType.ADAPTIVE ||
+				material.activeAttributeName === "level of detail") {
+
+				let vnNodes = (params.vnTextureNodes != null) ? params.vnTextureNodes : nodes;
+				visibilityTextureData = octree.computeVisibilityTextureData(vnNodes, camera);
+
+				const vnt = material.visibleNodesTexture;
+				const data = vnt.image.data;
+				data.set(visibilityTextureData.data);
+				vnt.needsUpdate = true;
+
+			}
+		} */
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
+        
         let transparent = false;
 		if(params.transparent !== undefined){
 			transparent = params.transparent && material.opacity < 1;
@@ -826,7 +861,7 @@ export class Renderer {
 
 			if (visibilityTextureData) {
 				let vnStart = visibilityTextureData.offsets.get(node);
-                console.log('vnStart',vnStart)
+                //console.log('vnStart',vnStart)
 				shader.setUniform1f("uVNStart", vnStart);
 			}  
 
@@ -1178,7 +1213,7 @@ export class Renderer {
 		let currentTextureBindingPoint = 0;
         
         
-        if (material.pointSizeType >= 0) {//最好搬到renderNodes
+        /* if (material.pointSizeType >= 0) {//最好搬到renderNodes
             if (material.pointSizeType === PointSizeType.ADAPTIVE ||
                 material.activeAttributeName === "level of detail") {
 
@@ -1192,7 +1227,7 @@ export class Renderer {
 
             }
         } 
-		
+		 */
 
 		{ // UPDATE SHADER AND TEXTURES
 			if (!this.shaders.has(material)) {
@@ -1215,11 +1250,7 @@ export class Renderer {
                 let numClipSpheres = (params.clipSpheres && params.clipSpheres.length) ? params.clipSpheres.length : 0;
                 let numClipPolygons = (material.clipPolygons && material.clipPolygons.length) ? material.clipPolygons.length : 0;
                     
-
-                let num_prism = material.prism ? 1 : 0
-                let prismPointCountSum = material.prism ? material.prism.points.length : 0 //点总个数
-                let prism_maxPointsCount = material.prism ? material.prism.points.length : 0 //单个prism最大点个数 (如果define也能传递个数数组,就不用再uniform里传了,呜 )
-
+ 
 
                 let defines = [
                     `#define num_shadowmaps ${shadowMaps.length}`,
@@ -1228,11 +1259,10 @@ export class Renderer {
                     `#define num_out_clipboxes ${num_out_clipboxes}`,   //改  
                     `#define num_highlightBox ${num_highlightBox}`,   //改  
                     `#define num_clipspheres ${numClipSpheres}`, 
-                    
-                    //测试: 
-                    `#define num_prism ${num_prism}`, 
-                    `#define prismPointCountSum ${prismPointCountSum}`,
-                    `#define prism_maxPointsCount ${prism_maxPointsCount}`,                    
+                     
+                    `#define num_prism ${material.prisms.length}`, //土方量数
+                    `#define prismPointCountSum ${material.prisms.pointsCount}`,//点总个数
+                    `#define prism_maxPointsCount ${material.prisms.maxPointsCount}`, //单个prism最大点个数 (如果define也能传递个数数组,就不用再uniform里传了,呜 )      
                     
                 ];
                     
@@ -1434,7 +1464,7 @@ export class Renderer {
             }
             
             
-            if(material.prism){ 
+            if(material.prisms.length){ 
                 const prismList = shader.uniformLocations["prismList[0]"];
                 gl.uniformMatrix3fv(prismList, false, material.uniforms.prismList.value);
                 
@@ -1473,6 +1503,7 @@ export class Renderer {
 			}
 
 
+            shader.setUniform1f("orthoMaxSize", material.uniforms.orthoMaxSize.value);
 			shader.setUniform1f("maxSize", material.uniforms.maxSize.value);
 			shader.setUniform1f("minSize", material.uniforms.minSize.value);
 
@@ -1516,13 +1547,13 @@ export class Renderer {
             //gl.TEXTURE_CUBE_MAP: 34067
             //gl.TEXTURE0=33984 , vnWebGLTexture.target=gl.TEXTURE_2D = 3353
             
-            let vnWebGLTexture = this.textures.get(material.visibleNodesTexture);//最好搬到renderNodes
+            /* let vnWebGLTexture = this.textures.get(material.visibleNodesTexture);//最好搬到renderNodes
             if(vnWebGLTexture){
                 shader.setUniform1i("visibleNodes", currentTextureBindingPoint); //为何之前写的是"visibleNodesTexture",但和"visibleNodes"效果相同?可shader里只有"visibleNodes"
                 gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
                 gl.bindTexture(vnWebGLTexture.target, vnWebGLTexture.id);
                 currentTextureBindingPoint++;
-            }  
+            }   */
 
 			let gradientTexture = this.textures.get(material.gradientTexture);
 			shader.setUniform1i("gradient", currentTextureBindingPoint);
@@ -1659,7 +1690,7 @@ export class Renderer {
 
          
 
-        params.currentTextureBindingPoint = currentTextureBindingPoint
+        params.currentTextureBindingPoint = ++currentTextureBindingPoint
         octrees.forEach(octree=>{  
             this.renderNodes(octree, nodes || octree.visibleNodes, visibilityTextureData, camera, target, shader, params);
         })
@@ -1725,7 +1756,7 @@ export class Renderer {
          
 		// RENDER
         
-        let mat = traversalResult.octrees[0].material
+        let mat = params.material || traversalResult.octrees[0].material
          
         if(Potree.settings.cloudSameMat && viewer.scene.volumes.length == 0 && mat.pointSizeType != PointSizeType.ADAPTIVE && mat.activeAttributeName != "level of detail"){
             this.renderOctree(traversalResult.octrees, null, camera, target, params);  //所有点云除了个别属性需要在shader中更新,其他都使用第一个点云的材质

+ 106 - 35
src/custom/modules/panos/Images360.js

@@ -668,6 +668,7 @@ export class Images360 extends THREE.EventDispatcher{
 
     flyToPano(toPano) {  //飞向漫游点
         if(!toPano)return
+        if(typeof toPano == 'number')toPano = this.panos[toPano]
         if(toPano instanceof Panorama){
             toPano = {pano: toPano}
         }
@@ -779,11 +780,13 @@ export class Images360 extends THREE.EventDispatcher{
         /* let maxTime = this.isAtPano() ? T.panoToPanoMax : T.flyIn 
         let duration = toPano.duration == void 0 ? (T.flyMinTime+Math.min(T.flytimeDistanceMultiplier * dis, maxTime)) : toPano.duration 
          */
-        let maxDis = this.isAtPano() ? T.maxDistanceThreshold : T.maxDistanceThresholdFlyIn
+        /* let maxDis = this.isAtPano() ? T.maxDistanceThreshold : T.maxDistanceThresholdFlyIn
         let duration = toPano.duration == void 0 ? Math.min(dis, T.maxDistanceThreshold) * T.flytimeDistanceMultiplier + T.flyMinTime : toPano.duration 
-         
-        
+          */
         
+        let maxDis = 7
+        let duration = toPano.duration == void 0 ? Math.min(dis, maxDis) * T.flytimeDistanceMultiplier + T.flyMinTime : toPano.duration 
+         
         
         
         if(toPano.useBound){
@@ -1216,55 +1219,120 @@ export class Images360 extends THREE.EventDispatcher{
         if(!ifNeighbour && map1[pano0.id] != void 0){
             ifNeighbour = map1[pano0.id]
         }
-          
+        let dis = pano0.position.distanceTo(pano1.position) 
           
         if(dontCompute)  return ifNeighbour 
-
+        
+        
+        
+        let ifSheltered = (mainPano, subPano)=>{ //该点前方近处是否都被遮挡
+            
+            /* if(mainPano.id == 9 && subPano.id == 6 || mainPano.id == 6 && subPano.id == 9  ){
+                console.log(1)
+            } */
             
-        let getNeighbour = (mainPano, subPano, jumpStep1, simpleJudge)=>{
-            //暂时只判断到pano,不判断到marker的方向
+            let vec = new THREE.Vector3().subVectors(subPano.position, mainPano.position).normalize() 
              
+            let getDir = (angle_, upDown)=>{  //基于vec的方向 向左向右旋转 
+                //if(upDown) vec.clone().applyAxisAngle(new THREE.Vector3(1, 0, 0), upDown);
+                return vec.clone().applyAxisAngle(new THREE.Vector3(0, 0, 1), angle_); 
+                 
+            } 
+            let minRatio = 0.5
+            let angles = [25,20,18,16,14,12,10,8,7,-7,-8,-10,-12,-14,-16,-18, -20,25]  //水平方向角度
+            let wellCount = 0 
+            for(let i=0; i<angles.length; i++){
+                let rad = THREE.Math.degToRad(angles[i])
+                let dir = getDir(rad)
+                let intersectPoint = viewer.images360.depthSampler.sample({dir}, mainPano, true) 
+                if(!intersectPoint || intersectPoint.distance * Math.cos(Math.abs(rad)) /* + margin */ > dis   ){//投影在vec方向的长度不超过漫游点间距 
+                    wellCount ++
+                }
+            }
+            if(wellCount / angles.length > minRatio){//合格个数
+                console.log('ifSheltered haha',  'id:', mainPano.id, subPano.id)
+                return true
+            }
+        }  
+        /*  
+        识别一定角度范围内是否有遮挡时
+        几种奇葩的情况: 
+            在墙的两边的但是墙是倾斜的漫游点:
+               A / 
+                /  
+               / B
+            从B出发和BA成20度的射线和墙面的交点会远于A,导致识别为无遮挡。
+            所以还是改为识别范围内多个深度图像素, 合格像素个数占比 至少要大于50%,因为半边墙壁是50%
+            如SG-9UsbysDufBw&formal&test 的 6、9点。  而SS-GTmFBp1JN8k&formal&test的 2、3两点是人物遮挡
+        */
+        
+        
+         
+        
+        
+            
+        let getNeighbour = (mainPano, subPano, jumpStep1)=>{
+            
             let dirPoints = []
             if(!jumpStep1){//跳过此步骤,因为之前算过不成功(虽然用另一个漫游点算的可能拍摄时间不同所以有概率不一样,如人走动)
                 dirPoints.push([subPano.position, mainPano.position])
             }
-            if(!simpleJudge){
+            if(dis < 20){//在远处去掉对floorPosition的判断
                 dirPoints.push([subPano.floorPosition.clone().add(new THREE.Vector3(0,0,0.1)), mainPano.position])
             }
+            if(dis < 12){//为了防止楼梯拐角、杂点遮挡。 尽量只在穿墙时不可通行
+                dirPoints.push([subPano.position.clone().add(new THREE.Vector3(0,0,0.8)), mainPano.position])
+                
+                let normal = math.getNormal2d({p1:subPano.position, p2:mainPano.position}).multiplyScalar(0.3)  //左右方向
+                
+                dirPoints.push([subPano.position.clone().add(new THREE.Vector3(normal.x,normal.y,0.1)), mainPano.position])
+                dirPoints.push([subPano.position.clone().add(new THREE.Vector3(-normal.x,-normal.y,0.1)), mainPano.position])
+            }
+             
+           
             for(let i=0; i<dirPoints.length; i++){
                 let dir = new THREE.Vector3().subVectors(dirPoints[i][0], dirPoints[i][1]).normalize();
                 let intersectPoint = viewer.images360.depthSampler.sample({dir}, mainPano, true) 
-                if(!intersectPoint || intersectPoint.distance+margin > pano0.position.distanceTo(pano1.position)){ 
+                if(!intersectPoint || intersectPoint.distance+margin > dirPoints[i][0].distanceTo(dirPoints[i][1])){ 
+                    if(i>2)console.log('haha',i,'id:',mainPano.id,subPano.id)
                     return true
                 }
             }
         } 
            
         if(!ifNeighbour && (map0[pano1.id] == void 0 || (computeTwoDir && map1[pano0.id] == void 0))) {//主方向为空且不为邻居
-            let simpleJudge = pano0.position.distanceToSquared(pano1.position) > 300 //在远处去掉对floorPosition的判断
+            
+          
+            
             if(pano0.depthTex || pano1.depthTex){
                              
                 if(map0[pano1.id] == void 0 && pano0.depthTex){
-                    let is = getNeighbour(pano0, pano1, null, simpleJudge)
+                    let is = getNeighbour(pano0, pano1)
                     if(is){
                         ifNeighbour = true
-                    }else if(simpleJudge){
+                    }else if(dis>16){
                         ifNeighbour = false
                     }                        
                     map0[pano1.id] = !!is        
                 }
                  
                 if(map1[pano0.id] == void 0 && pano1.depthTex){  
-                    let is = getNeighbour(pano1, pano0, !ifNeighbour, simpleJudge)
+                    let is = getNeighbour(pano1, pano0, !ifNeighbour)
                     if(is){
                         ifNeighbour = true
-                    }else if(simpleJudge){
+                    }else if(dis>16){
                         ifNeighbour = false
                     } 
                     map1[pano0.id] = !!is        
                 } 
                 ifNeighbour = !!ifNeighbour
                 
+                if(!ifNeighbour && pano0.depthTex && pano1.depthTex && dis<10){//再检查下 只要两方都没有被完全遮挡就算可通行
+                     if(ifSheltered(pano0,pano1) && ifSheltered(pano1,pano0)){
+                         ifNeighbour = map0[pano1.id] = map1[pano0.id] = true 
+                     }
+                }
+                
                 //console.log('isNeighbour', pano0, pano1, ifNeighbour)
                 /* if(ifNeighbour){ //需要标记成全部true吗,不标记也能get到,但标记了更直观,不标记保留信息更多
                     map0[pano1.id] = map1[pano0.id] = true
@@ -1401,28 +1469,31 @@ export class Images360 extends THREE.EventDispatcher{
             }  );
         } else {
             //如果离数据集较远,转动也很难找到点云,就飞到就近点:
-            let po = viewer.scene.pointclouds.find(e=>e.visibleNodes.some(a=>a.getLevel() > Math.ceil(e.maxLevel * 0.15) )) //虽然当点云在前方很远的地方也可能符合
-             
-            if(!po){//无可见点云
-                //console.log('no visi cloud')
-                
-                if(!this.panos.length){//如果场景中没有漫游点,如SG-t-XPf1k9pv3Zg 点击后回到可见区域
-                    let map = new Map() 
-                    let clouds = viewer.scene.pointclouds.filter(e=>e.root.geometryNode)
-                    clouds.forEach(e=>map.set(e, e.bound.distanceToPoint(this.position))) 
-                    clouds.sort((a,b)=>map.get(a) - map.get(b)) 
+            if(Potree.settings.displayMode == 'showPointcloud'){
+                let po = viewer.scene.pointclouds.find(e=>e.visibleNodes.some(a=>a.getLevel() > Math.ceil(e.maxLevel * 0.15) )) //虽然当点云在前方很远的地方也可能符合
+                 
+                if(!po){//无可见点云
+                    //console.log('no visi cloud')
                     
-                    viewer.flyToDataset({focusOnPoint:true, pointcloud:clouds[0], duration:500 })//飞最近的一个点云
+                    if(!this.panos.length){//如果场景中没有漫游点,如SG-t-XPf1k9pv3Zg 点击后回到可见区域
+                        if(viewer.scene.pointclouds.length == 0)return 
+                        let map = new Map() 
+                        let clouds = viewer.scene.pointclouds.filter(e=>e.root.geometryNode)
+                        clouds.forEach(e=>map.set(e, e.bound.distanceToPoint(this.position))) 
+                        clouds.sort((a,b)=>map.get(a) - map.get(b)) 
+                        
+                        viewer.flyToDataset({focusOnPoint:true, pointcloud:clouds[0], duration:500 })//飞最近的一个点云
+                        return deferred.promise();
+                    }
+                     
+                    this.flyToPano({
+                        pano: this.findNearestPano(),
+                        duration:500,
+                        callback: deferred.resolve.bind(deferred, !0)
+                    });
                     return deferred.promise();
+                     
                 }
-                 
-                this.flyToPano({
-                    pano: this.findNearestPano(),
-                    duration:500,
-                    callback: deferred.resolve.bind(deferred, !0)
-                });
-                return deferred.promise();
-                 
             }
              
             this.bump(direction);
@@ -2754,7 +2825,7 @@ Images360.prototype.updateCube = (function(){//增加细分的版本,且垂直
                 height = height == void 0 ? (Math.min(skyHeight,pano.ceilZ) - pano.floorPosition.z) : height
                 //let r = height (maxH - minH)* 0.14  // 高度越小,角度越小 
                 //let r = minR + ( maxR - minR) * THREE.Math.clamp((height - minH)  / (maxH - minH),0,1)   //THREE.Math.smoothstep(currentDis,  op.nearBound,  op.farBound);
-                let r = math.linearClamp(height, minH,maxH,   minR,  maxR) 
+                let r = math.linearClamp(height, [minH,maxH],   [minR,  maxR]) 
                 
                 
                 let getZ = (deg)=>{
@@ -2904,7 +2975,7 @@ Images360.prototype.updateCube = (function(){//增加细分的版本,且垂直
                          
                         let maxDis = 50, minDis = 0.5,  minR = 0.2, maxR = 1.2 
                         //let r = maxR - ( maxR - minR) * THREE.Math.clamp((dis2d - minDis)  / (maxDis - minDis),0,1) //dis2d越大,角度要越小  //THREE.Math.smoothstep(currentDis,  op.nearBound,  op.farBound);
-                        let r = math.linearClamp(dis2d, minDis,maxDis,   maxR,  minR) 
+                        let r = math.linearClamp(dis2d, [minDis,maxDis],   [maxR,  minR]) 
                         //console.log('dis2d',dis2d,'r',r) 
                          
                         

+ 9 - 8
src/custom/objects/tool/Measure.js

@@ -11,7 +11,7 @@ import {config} from '../../settings.js'
 import browser from "../../utils/browser.js";
 import {ctrlPolygon} from './ctrlPolygon.js'
 
- 
+
 let texLoader = new THREE.TextureLoader()  
 let defaultColor = new THREE.Color(config.measure.default.color);
 let highlightColor = new THREE.Color(config.measure.highlight.color);
@@ -22,7 +22,7 @@ var markerMats;
 var lineMats;  
 var planeMats 
  
-const textSizeRatio = math.linearClamp(window.outerWidth * window.outerHeight , 360*720,   1920*1080, 0.7, 1)  //pc字显示大一些 用
+const textSizeRatio = math.linearClamp(window.outerWidth * window.outerHeight , [360*720, 1920*1080], [0.7, 1])  //pc字显示大一些 用
  
 const lineDepthInfo = {
     clipDistance : 4,//消失距离
@@ -76,10 +76,7 @@ const angle = THREE.Math.degToRad(5);//显示水平垂直辅助线的最小角
 const guideShowMinAngle = {min: angle, max: Math.PI/2 - angle}
 
    
-
-    
  
-
 export class Measure extends ctrlPolygon{
 	constructor (prop) {
         prop.dimension = '2d'
@@ -505,7 +502,7 @@ export class Measure extends ctrlPolygon{
                 let dis2 = far.distanceToSquared(eyePos)
                 let diff = Math.abs(dis1/dis2)
                 diff<1 && (diff = 1/diff)
-                diff = math.linearClamp(diff,0, 30,    0,1 ) 
+                diff = math.linearClamp(diff,[0, 30],   [ 0,1 ]) 
                   
                   
                   
@@ -826,7 +823,7 @@ export class Measure extends ctrlPolygon{
 	}
     
     getCenter(/* update */){ 
-        if(this.closed){
+        if(this.center){
             return this.center.clone()
         }else{  
             let center = this.points.reduce(function(total, currentValue ){
@@ -1091,10 +1088,14 @@ export class Measure extends ctrlPolygon{
             prop.showEdges = true,
             prop.maxMarkers = 2,
             prop.minMarkers = 2 
-        }else if(prop.measureType == 'MulDistance'){//new 
+        }else if(prop.measureType == 'MulDistance'){ 
             prop.showDistances = true,  
             prop.showEdges = true, 
             prop.minMarkers = 2 
+        }else if(prop.measureType == 'MulDistance Ring'){
+            prop.showEdges = true,
+            prop.closed = true, 
+            prop.minMarkers = 3  
         }else if(prop.measureType == 'Ver MulDistance'){ 
             prop.showDistances = true,
             prop.atPlane = true,                

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

@@ -1,11 +1,12 @@
 import * as THREE from "../../../../libs/three.js/build/three.module.js";
 import {Measure} from "./Measure.js";
+
 import {Utils} from "../../../utils.js"; 
 import math from "../../utils/math.js";
 import {CameraMode} from "../../../defines.js"; 
 import {TextSprite} from '../TextSprite.js'
  
- 
+import {Prism} from "../../modules/volumeCompute/Prism.js";
  
  
  
@@ -413,7 +414,7 @@ export class MeasuringTool extends THREE.EventDispatcher{
 		let domElement = this.viewer.renderer.domElement;
  
  
-        let measure = new Measure(args);
+        let measure = args.measureType == 'MulDistance Ring' ? new Prism(args) : new Measure(args);
         this.scene.add(measure);
         measure.isNew = true
         
@@ -542,6 +543,10 @@ export class MeasuringTool extends THREE.EventDispatcher{
                 type: 'finish_inserting_measurement',
                 measure: measure
             }); */
+            
+            
+            
+            measure.dispatchEvent('createDone')
 		};
 
         measure.addEventListener('finish', end) //完成
@@ -709,4 +714,7 @@ export class MeasuringTool extends THREE.EventDispatcher{
             this.viewer.renderer.render(this.scene, o.camera );
         //}
 	}
+    
+    
+    
 };

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

@@ -4,7 +4,7 @@ import {ctrlPolygon} from './ctrlPolygon.js'
 import {LineDraw } from "../../utils/DrawUtil.js";
 import Sprite from '../../objects/Sprite.js'
 import {config} from '../../settings.js'
-
+ 
 import math from "../../utils/math.js";
 let texLoader = new THREE.TextureLoader() 
 

+ 46 - 19
src/custom/potree.shim.js

@@ -1154,6 +1154,7 @@ Potree.updateVisibility = function(pointclouds, camera, areaSize){
         //if(!pointcloud.visible) continue
 
 		pointcloud.updateMatrixWorld();
+         
 
 		if(!pointcloudTransformVersion.has(pointcloud)){
 			pointcloudTransformVersion.set(pointcloud, {number: 0, transform: pointcloud.matrixWorld.clone()});
@@ -1173,6 +1174,7 @@ Potree.updateVisibility = function(pointclouds, camera, areaSize){
 	}
     
     
+    
 	while (priorityQueue.size() > 0) {
 		let element = priorityQueue.pop(); //取出权重最大的一个
          
@@ -1203,11 +1205,17 @@ Potree.updateVisibility = function(pointclouds, camera, areaSize){
 		visible = visible && !(numVisiblePointsInPointclouds.get(pointcloud) + node.getNumPoints() > pointcloud.pointBudget); // pointcloud.pointBudget一直是Infinity
 		visible = visible && level <= maxLevel; //< 改为 <=
 		//visible = visible || node.getLevel() <= 2;
+        let pcWorldInverse = pointcloud.matrixWorld.clone().invert();
+        let m = pcWorldInverse.elements 
+        let pcWorldInvM3 =  new THREE.Matrix3().set(m[0],m[4],m[12],m[1],m[5],m[13],m[3],m[7],m[15]) //去掉z的
 
+        //pointcloud.pcMatrix3 = new THREE.Matrix3().set(m[0],m[4],m[12],m[1],m[5],m[13],m[3],m[7],m[15]) //去掉z的
+    
+    
 
         let intersectBox = (clipBox)=>{
 
-            let pcWorldInverse = pointcloud.matrixWorld.clone().invert();
+            
             let toPCObject = pcWorldInverse.multiply(clipBox.box.matrixWorld);  //box乘上点云逆矩阵
 
             /* let px = new THREE.Vector3(+0.5, 0, 0).applyMatrix4(pcWorldInverse);
@@ -1284,25 +1292,44 @@ Potree.updateVisibility = function(pointclouds, camera, areaSize){
                 visible = false  
             }
         }
-        
-        
+         
         //outside不做处理。因为node必须完全在clipBox内才能完全隐藏,而这里的intersect只能识别出部分在clipBox内。因而只能说明不在任意一个box内绝对可见,没有意义,这里需要找出不可见的。
-        /* if(visible && clipBoxes_out.length > 0){ //当有不可见box时,不在所有不可见box内才可见
-            let visi = true;
-            for(let i = 0,length=clipBoxes_out.length; i < length; i++){ 
-                if(intersectBox(clipBoxes_out[i])){
-                    visi = false;
-                    break;
-                } 
-            }
-            if(!visi){
-                visible = false  
-            }
-        }
-        */ 
-
-		// visible = ["r", "r0", "r06", "r060"].includes(node.name);
-		// visible = ["r"].includes(node.name);
+         
+         
+        let prism = pointcloud.material.activeAttributeName == 'prismHeight' && pointcloud.material.prisms && pointcloud.material.prisms.find(e=>e.computing)
+        if(prism){ 
+            let bound = box.clone().applyMatrix4(pointcloud.matrixWorld)
+            if(bound.intersectsBox(prism.prismBound)){
+                /* //node box是否包含points中的一个点
+                let box2 = new THREE.Box2().copy(box)
+                let points2d = prisms.points.map(e=>new THREE.Vector2().copy(e).applyMatrix3(pcWorldInvM3))
+                let intersect = points2d.some(e=>{ 
+                    return box2.containsPoint(e)
+                })   
+                
+                if(!intersect){
+                    //或者多边形中是否包含node box中的一个点
+                    intersect = [ 
+                        new THREE.Vector2(box.min.x, box.min.y),
+                        new THREE.Vector2(box.max.x, box.max.y),
+                        new THREE.Vector2(box.min.x, box.max.y),
+                        new THREE.Vector2(box.max.x, box.min.y),
+                    ].some(e=>{ 
+                        if(math.isPointInArea(points2d, null, e) ){
+                            return true
+                        }
+                        
+                    })
+                    //z是不是在外层已经判断好了?
+                    if(!intersect){
+                        visible = false   
+                    }
+                } */
+                //会有两个互不包含点但是交叉了的情况,所以就不仔细判断了(如横竖两个矩形构成十字架)
+            }else visible = false
+           
+        }   
+         
 
 		if (node.spacing) {
 			lowestSpacing = Math.min(lowestSpacing, node.spacing);

+ 5 - 9
src/custom/settings.js

@@ -1,6 +1,8 @@
 //xzw add  
 import browser from './utils/browser.js'
 
+
+ 
 const config = {//配置参数   不可修改
     displayMode:{ 
 		showPointCloud:{
@@ -77,15 +79,8 @@ const config = {//配置参数   不可修改
     
     transitionsTime:{
         flyMinTime : 650  ,  // 毫秒/米
-        flytimeDistanceMultiplier: 120 ,
-        /* panoToPanoMax: 1800 , 
-        flyIn:1000,
-        flyOut:1000,
-         */
+        flytimeDistanceMultiplier: 120 , 
         
-        flyTime:650,
-        maxDistanceThreshold:14,
-        maxDistanceThresholdFlyIn:5,
     }
     
     
@@ -458,7 +453,8 @@ let settings = {//设置   可修改
 }
 
 
-  
+Potree.config = config
+Potree.settings = settings
  
 settings.isLocalhost = settings.prefix.includes('localhost')
 

+ 1 - 1
src/custom/utils/Common.js

@@ -351,7 +351,7 @@ var Common = {
             if(timeStamp.length){
                 let dur = performance.now() - timeStamp[timeStamp.length-1].startTime;  //dur在iphoneX中静止有7,pc是2
                
-                count = Math.round(math.linearClamp(dur, durBound1,durBound2,   maxCount,  minCount))
+                count = Math.round(math.linearClamp(dur, [durBound1,durBound2],   [maxCount,  minCount]))
                  
                 if (maxHistory) {
                     if (!lastCount[name]) lastCount[name] = []

+ 1 - 1
src/custom/utils/SplitScreen4Views.js

@@ -167,7 +167,7 @@ SplitScreen4Views.split = function(o={}){
      
     this.enableMap(false)
     this.enableFloorplan(false)
-    viewer.mapViewer.setViewLimit('expand') //多数据集距离远时可以任意远,所以不限制了。但是这样就会看到地图边界了怎么办?
+    viewer.mapViewer.setViewLimit('null') //多数据集距离远时可以任意远,所以不限制了。但是这样就会看到地图边界了怎么办?超出后让地图隐藏?
     //viewer.dispatchEvent({'type': 'beginSplitView' }) 
     //viewer.updateScreenSize({forceUpdateSize:true})   
     

+ 1 - 17
src/custom/utils/browser.js

@@ -284,23 +284,7 @@ var browser = {
     urlQueryValue(key) {
         return this.urlHasValue(key, true) || ""
     },
-    /**
-     * 获取hash参数的值
-     * @param {String} key
-     * @returns String
-     */
-    urlHashValue(key) {
-        let querys = window.location.hash.substr(1).replace('/?', '').split("&")
-        for (let i = 0; i < querys.length; i++) {
-            let keypair = querys[i].split("=")
-
-
-            if (keypair.length === 2 && keypair[0] === key) {
-                return keypair[1]
-            }
-        }
-        return ""
-    },
+    
     /**
      * 判断是否存在hash
      * @param {String} key

+ 21 - 2
src/custom/utils/math.js

@@ -627,10 +627,29 @@ var math = {
     },
 
         
-    linearClamp(value,  x1,x2, y1, y2){//x为bound.min, bound.max
+    /* linearClamp(value,  x1,x2, y1, y2){//x为bound.min, bound.max
         value = THREE.Math.clamp(value, x1,x2)
         return y1 + ( y2 - y1) * (value - x1)  / (x2 - x1)  
-    }
+    } */
+    
+    linearClamp(value, xArr , yArr){ //xArr需要按顺序从小到大,yArr对应xArr中的值
+        
+        let len = xArr.length 
+        if(value < xArr[0]) return yArr[0]
+        if(value > xArr[len - 1]) return yArr[len - 1]
+        let i = 0 
+        
+        while(++i < len ){
+            if(value < xArr[i]){
+                let x1 = xArr[i-1], x2 = xArr[i], y1 = yArr[i-1], y2 = yArr[i] 
+                value = y1 + ( y2 - y1) * (value - x1)  / (x2 - x1)  
+                break
+            }
+        }
+        return value
+        
+         
+    } 
 };
 
  

+ 11 - 5
src/custom/viewer/ViewerNew.js

@@ -46,6 +46,8 @@ import {Clipping}  from '../modules/clipping/Clipping.js'
 import ParticleEditor from '../modules/Particles/ParticleEditor.js'
 import CamAniEditor from '../modules/CameraAnimation/CamAniEditor.js'  
 import PanoEditor  from '../modules/panoEdit/panoEditor.js' 
+import VolumeComputer from '../modules/VolumeCompute/VolumeComputer.js' 
+ 
 
 import {InputHandler} from "../../navigation/InputHandlerNew.js";
 
@@ -131,6 +133,7 @@ export class Viewer extends ViewerBase{
                 clipping: new Clipping,
                 ParticleEditor,
                 CamAniEditor, 
+                volumeComputer: new VolumeComputer
             }
         }
         {
@@ -2098,7 +2101,8 @@ export class Viewer extends ViewerBase{
 	
 	setCameraMode(mode){
 		this.scene.cameraMode = mode;
-
+        viewer.mainViewport.camera = mode == CameraMode.PERSPECTIVE ? this.scene.cameraP : this.scene.cameraO; //改
+         
 		for(let pointcloud of this.scene.pointclouds) {
 			pointcloud.material.useOrthographicCamera = mode == CameraMode.ORTHOGRAPHIC;
 		}
@@ -2809,14 +2813,16 @@ export class Viewer extends ViewerBase{
             let clipBoxes_in = clipBoxes.filter(e=>e.box.clipTask == ClipTask.SHOW_INSIDE && !e.box.highlight)
             let clipBoxes_out = clipBoxes.filter(e=>e.box.clipTask == ClipTask.SHOW_OUTSIDE && !e.box.highlight)
             let highlightBoxes = clipBoxes.filter(e=>e.box.highlight )
-			
+			let prismPolygons = this.modules.volumeComputer && this.modules.volumeComputer.entered ? viewer.scene.measurements.filter(e=>(e.measureType == 'MulDistance Ring') && !e.isNew) : []
+            
+            
             // set clip volumes in material
 			for(let pointcloud of visiblePointClouds){
                 let clipBoxes_in2 = [], clipBoxes_out2 = [], highlightBoxes2 = []
                 if(pointcloud.dataset_id == Potree.settings.originDatasetId){ //实时裁剪只对初始数据集有效
                     clipBoxes_in2 = clipBoxes_in,  clipBoxes_out2 = clipBoxes_out, highlightBoxes2 = highlightBoxes
                 }
-				pointcloud.material.setClipBoxes(bigClipInBox, clipBoxes_in2, clipBoxes_out2, highlightBoxes2);  
+				pointcloud.material.setClipBoxes(bigClipInBox, clipBoxes_in2, clipBoxes_out2, highlightBoxes2, prismPolygons);  
 			}
 		}  
 
@@ -3512,7 +3518,7 @@ export class Viewer extends ViewerBase{
         }else{ 
             let specialRender =  !!params.viewports 
             let viewports = params.viewports || this.viewports
-        
+             
             if(!this.needRender){
                 viewports = viewports.filter(v=>v.needRender) //可以渲染的条件是viewer或viewport的needRender为true
             }
@@ -4334,7 +4340,7 @@ export class Viewer extends ViewerBase{
         else pointcloud = this.scene.pointclouds.find(p => p.dataset_id == o.id);
          
         let duration = o.duration == void 0 ? 1000 : o.duration
-        if(o.focusOnPoint){//focus点云上一点,避免center区域刚好没有点
+        if(o.focusOnPoint || !pointcloud.panosBound){//focus点云上一点,避免center区域刚好没有点
             if(pointcloud.root.geometryNode){ 
                 let posArr = pointcloud.root.geometryNode.geometry.attributes.position.array
                 

+ 31 - 15
src/custom/viewer/map/Map.js

@@ -159,6 +159,7 @@ export class MapLayer extends THREE.EventDispatcher{ // 包括了 MapLayerBase S
      
      
     update(){
+        
         this.needUpdate = false
         if(this.disabled || !this.maps.find(e=>!e.disabled) || !this.maps.find(e=>e.objectGroup.visible)   )return  //add
         this.viewer.mapChanged = true
@@ -180,7 +181,7 @@ export class MapLayer extends THREE.EventDispatcher{ // 包括了 MapLayerBase S
         this.frustum.planes[5].setComponents(0, 0, 0, 0),
         i = !0 
         
-       
+        //console.log('-------------update-----------')
         for (r = 0; r < this.maps.length; r++){
             var map = this.maps[r] 
             i = map.update(this.frustum, this.sceneGroup) && i;
@@ -472,7 +473,10 @@ const loadDone = (tile, success)=>{
 }
  
 function addLoadTile(tile){
-    
+    /* if(tile.texURL && tile.texURL.includes('testdata') ){ 
+        console.error('addLoadTile',   tile.texURL.split('map_tiles/')[1] )
+    } */
+     
     if(tile.map.loadingInProgress < tile.map.maxLoading){
         if(!tile.mesh)return;  //有时候会遇到这种情况, 为什么没有被cancelLoad呢?
 
@@ -480,7 +484,7 @@ function addLoadTile(tile){
         tile.map.loadingInProgress ++ 
         tile.map.mapLayer.dispatchEvent('startLoad') 
         //console.log('addLoad', 'loadingInProgress',tile.map.mapLayer.loadingInProgress, Date.now())
-        //tile.texURL && tile.texURL.includes('testdata') && console.log('addLoadTile',   tile.texURL.split('map_tiles/')[1] )
+        //tile.texURL && tile.texURL.includes('testdata') && console.log('startloadTile ',   tile.texURL.split('map_tiles/')[1] )
          
         tile.loading = true
         let index = tile.map.mapLayer.waitQueue.indexOf(tile);
@@ -557,7 +561,11 @@ export class MapTile{
         return t.tilePresenceMap && t.tilePresenceMap.empty
     }
     
-    updateTile(t, e, n, i){ //真正显示mesh的是这一层,最高level, i==0的
+    updateTile(t, e, n, i){ //真正显示mesh的是这一层,最高level  
+            
+        //if(this.map.name.includes('floorplan'))console.log('updateTile',this.name)
+    
+    
         if(!this.mesh){
             this.createTileObject(t, e, n, i)
         }
@@ -575,14 +583,13 @@ export class MapTile{
     }
     
     updateSubTiles(entity, n, level, o, a, s, c){
-        for (var noContent = !0, u = [-.25 * o, .25 * o, -.25 * o, .25 * o], d = [.25 * o, .25 * o, -.25 * o, -.25 * o], p = 0; p < 4; ++p){
+        //if(entity.name.includes('floorplan'))console.log('updateSubTiles',this.name) //名字越长代表level越高
+        
+        
+        for (var childrenLoaded = !0, u = [-.25 * o, .25 * o, -.25 * o, .25 * o], d = [.25 * o, .25 * o, -.25 * o, -.25 * o], p = 0; p < 4; ++p){
             var h = c + p.toString(10);
             //一级(512):0 1 2 3分别为左上、右上、左下、右下。二级(1024)就是把一级的每一块分裂,如00 01 02 03分别是0的左上、右上、左下、右下……
-            /* if(entity.name == 'floorplan'){
-                console.log(1)
-            } */
-            
-            
+             
             if (!entity.tilePresenceMap || entity.tilePresenceMap[h]){
                 //去掉判断,直接显示
                 var f = a + u[p]
@@ -593,7 +600,9 @@ export class MapTile{
                 
                 if (entity.isTileVisible(tempVector, .5 * o, n)){ 
                     this.children[p] || (this.children[p] = new MapTile(this.map, this.objectGroup,this.tileColor, this, this.name+p ))
-                    noContent = noContent && this.children[p].update(entity, n, level - 1, .5 * o, f, m, h)  
+                    //childrenLoaded = childrenLoaded && this.children[p].update(entity, n, level - 1, .5 * o, f, m, h)   //这句会使若有一个tile还在加载,就阻断了。原版是这么写的。但是为了加快加载速度,改成下面两行。感觉直接全部updateTile也没太卡,不知道很大的场景会不会卡,单帧updateTile次数超过100次的话(应该不会吧,地图大小会限制住个数) -- 2023.12
+                    let childLoaded = this.children[p].update(entity, n, level - 1, .5 * o, f, m, h)  
+                    childrenLoaded = childrenLoaded && childLoaded
                 } else {
                     if (this.children[p]){
                         this.children[p].remove()
@@ -604,10 +613,17 @@ export class MapTile{
                 
             }
         }
-        return noContent && this.removeObject3D(),
-        noContent
+        return childrenLoaded && this.removeObject3D(), childrenLoaded //子项加载完,母项mesh可以去除。(最后母项的母项以及前面的都会被删除,只留最后的叶子结点)
 
     }
+    /* 
+    
+        一层层往后加载。加入第一次加载到第4层(因为level精细度是第4层),给第4层可见tile加上mesh。
+        然后下一次加载到第5层,那么第4层的mesh就要被清空(当它所属的第5层子集都加载完后)
+    
+    
+    
+     */
     
     createTileObject(t, e, n, a){
         var s = this;
@@ -966,7 +982,7 @@ export class TiledMapFromEntity extends TiledMapBase{
  
  
  
- https://lbs.amap.com/tools/picker  高德坐标拾取器,但和这里展示的不一样, 要用AMapWith84.aMapToWgs84({x: ,y: })转成84。  (qq or 手机登录)  所以potree本地和有AMapWith84函数的laser地图展现不一样
+ https://lbs.amap.com/tools/picker  高德坐标拾取器(手机登录),但和这里展示的不一样, 要用AMapWith84.aMapToWgs84({x: ,y: })转成84。  (qq or 手机登录)  所以potree本地和有AMapWith84函数的laser地图展现不一样
  https://www.google.com/maps/@77.7730021,-34.4952712,4z     google取点
  
  
@@ -981,7 +997,7 @@ export class TiledMapFromEntity extends TiledMapBase{
  
  
  图片地址中 tiles/4/3/9.png 第一个数字越高代表level越高,放得越大 . (tile.name.length也能反映出
- viewer.mapViewer.mapLayer.maps[1].objectGroup.children.map(e=>e.name.length)
+ viewer.mapViewer.mapLayer.maps[1].objectGroup.children.map(e=>e.name.length-1)
  
  
  目前看的几个场景floorplan原图是1米=33.03个像素  图宽度= 512*2^(max_depth-1) ,   map_size_m 代表整个地图是多少米

+ 40 - 19
src/materials/ExtendPointCloudMaterial.js

@@ -30,8 +30,8 @@ export class ExtendPointCloudMaterial extends PointCloudMaterial {
 			}
 		}
  
-		let maxSize = getValid(parameters.maxSize, 1550.0);
-		  
+		let maxSize = getValid(parameters.maxSize, 200.0);
+        let orthoMaxSize = getValid(parameters.orthoMaxSize, 3.0);
 		this._gradient = Gradients.RAINBOW//Gradients.SPECTRAL;//海拔贴图种类
 		this.gradientTexture = ExtendPointCloudMaterial.generateGradientTexture(this._gradient); 
 		//this.matcapTexture = ExtendPointCloudMaterial.generateMatcapTexture(this._matcap);
@@ -48,6 +48,7 @@ export class ExtendPointCloudMaterial extends PointCloudMaterial {
         Object.assign(this.uniforms,{
             resolution:    { type: 'v2',  value: new THREE.Vector2() },
             maxSize:			{ type: "f", value: maxSize },
+            orthoMaxSize:			{ type: "f", value: orthoMaxSize },
             gradient:			{ type: "t", value: this.gradientTexture },
             
             clipBoxes_in:  { type: "Matrix4fv", value: [] },
@@ -102,7 +103,7 @@ export class ExtendPointCloudMaterial extends PointCloudMaterial {
         this.clipBoxes_in = [];
         this.clipBoxes_out = [];
         this.highlightBoxes = [];
-		 
+		this.prisms = []
 		this.updateShaderSource();
 	}
 
@@ -168,7 +169,7 @@ export class ExtendPointCloudMaterial extends PointCloudMaterial {
 			defines.push('#define adaptive_point_size');
 		}
         
-        if(!Features.EXT_DEPTH.isSupported() && this.shape === PointShape.PARABOLOID){
+        if(!Features.EXT_DEPTH.isSupported(viewer.renderer.getContext()) && this.shape === PointShape.PARABOLOID){
             this.shape = PointShape.SQUARE ;//强行替换
         }
         
@@ -307,7 +308,7 @@ export class ExtendPointCloudMaterial extends PointCloudMaterial {
 
 	 
     
-	setClipBoxes (bigClipInBox, clipBoxes_in,clipBoxes_out, highlightBoxes) {
+	setClipBoxes (bigClipInBox, clipBoxes_in,clipBoxes_out, highlightBoxes, prismPolygons=[]) {
 		if (!clipBoxes_in || !clipBoxes_out) {
 			return;
 		}
@@ -340,23 +341,43 @@ export class ExtendPointCloudMaterial extends PointCloudMaterial {
 			}
 		} */
         
-        /* let polygon = viewer.scene.measurements.find(e=>e.measureType == 'Hor Area' && e.points.length > 2 && !e.isNew)
-        
-        if(polygon){ 
-            this.uniforms.prismList.value = new Float32Array(9);
-            this.uniforms.prismPoints.value = new Float32Array(2*polygon.points.length);
+  
+        if(prismPolygons.length){  
+            let pointsCount = prismPolygons.pointsCount = prismPolygons.reduce((w,c)=>{return w+c.points.length},0) 
+            this.uniforms.prismList.value = new Float32Array(9 * prismPolygons.length); 
+            this.uniforms.prismPoints.value = new Float32Array(2 * pointsCount);
+            
+            prismPolygons.maxPointsCount = 0//单个prism最大点个数 
+             
+            
+            
+            let pointIndex = 0
+            for(let i=0;i<prismPolygons.length;i++ ){ 
+                let bound = Potree.math.getBound(prismPolygons[i].points)
+                prismPolygons[i].prismBound = bound
+                let z = prismPolygons[i].horizonZ 
+                //z = Potree.browser.urlHasValue('zmin',true) ||  zs[0]  
+                bound.min.z = /* z - 2// */viewer.bound.boundingBox.min.z
+                bound.max.z = /* z + 4// */viewer.bound.boundingBox.max.z
+                 
+                this.uniforms.prismList.value.set([bound.min.z, z, bound.max.z, bound.min.x, bound.max.x, bound.min.y, bound.max.y,  prismPolygons[i].points.length ],9*i)
+                for(let j=0;j<prismPolygons[i].points.length;j++){
+                    this.uniforms.prismPoints.value.set([prismPolygons[i].points[j].x, prismPolygons[i].points[j].y] , 2*j+pointIndex);
+                }  
+                pointIndex += 2 * prismPolygons[i].points.length
+                
+                
+                prismPolygons.maxPointsCount = Math.max(prismPolygons.maxPointsCount, prismPolygons[i].points.length) 
+            }
+            
+            
+            
             
-            let z = polygon.points[0].z
-            let bound = Potree.math.getBound(polygon.points)
-            this.uniforms.prismList.value.set([z-1,z,z+1, bound.min.x,bound.max.x, bound.min.y, bound.max.y,  polygon.points.length ],0)
-            for(let i=0;i<polygon.points.length;i++){
-                this.uniforms.prismPoints.value.set([polygon.points[i].x,polygon.points[i].y] , 2*i);
-            }  
-        } */
+        } 
          
         let doUpdate = (this.clipBoxes_in.length !== clipBoxes_in.length) || (this.clipBoxes_out.length != clipBoxes_out.length)
                     || this.highlightBoxes.length !== highlightBoxes.length || this.bigClipInBox != bigClipInBox 
-                    //|| (this.prism != polygon)                                                                                                                                                                                                                                                                                                                                                                                  
+                    || (this.prisms.length != prismPolygons.length)                                                                                                                                                                                                                                                                                                                                                                                  
 		//this.clipBoxes = clipBoxes; 
 		if (doUpdate){
 			this.shaderNeedsUpdate = true 
@@ -368,7 +389,7 @@ export class ExtendPointCloudMaterial extends PointCloudMaterial {
         this.clipBoxes_in = clipBoxes_in
         this.clipBoxes_out = clipBoxes_out
         this.highlightBoxes = highlightBoxes
-        //this.prism = polygon
+        this.prisms = prismPolygons
 	}
 
 }

+ 55 - 12
src/materials/shaders/pointcloud_new.vs

@@ -117,7 +117,9 @@ uniform float uOrthoHeight;
 
 uniform float size;
 uniform float minSize;
-uniform float maxSize;
+uniform float maxSize; 
+uniform float orthoMaxSize;//add
+
 
 uniform float uPCIndex;
 uniform float uOctreeSpacing;
@@ -275,7 +277,7 @@ bool isBitSet(int number, int index){
 /**
  * find the LOD at the point position
  */
-float getLOD(){//////
+float getLOD(){//////we use this
 	 
 	vec3 offset = vec3(0.0, 0.0, 0.0);
 	int iOffset = int(uVNStart);
@@ -754,8 +756,8 @@ float getPointSize(){
 		if(uUseOrthographicCamera){
 			//pointSize = size * 100.0;  //加个乘数
             
-            pointSize = size / uOrthoWidth  * resolution.x; //改成近似adaptive_point_size根据窗口缩放
-            maxSize_ = 3.0;  //for panoEditor, when zoom in, need more details, rather than always same size
+            pointSize = size / uOrthoWidth  * resolution.x; //改成近似adaptive_point_size根据窗口缩放  size单位转化为米,如size为1代表一个点云在场景中1米宽
+            maxSize_ =  orthoMaxSize;    //for panoEditor, when zoom in, need more details, rather than always same size
 
 		}else{  //近大远小,模拟真实mesh,边缘放大
 			//pointSize = size * spacing * projFactor;  //spacing是attribute  为空  如果有这个值就能更自适应填补
@@ -768,7 +770,7 @@ float getPointSize(){
 		if(uUseOrthographicCamera) {
 			float worldSpaceSize = 1.0 * size * r / getPointSizeAttenuation();
 			pointSize = (worldSpaceSize / uOrthoWidth) * resolution.x;    //uScreenWidth;
-            maxSize_ = 3.0;
+            maxSize_ = orthoMaxSize;
 		} else {
 			float worldSpaceSize = 1.0 * size * r / getPointSizeAttenuation();
 			pointSize = worldSpaceSize * projFactor;
@@ -795,6 +797,29 @@ bool insideBox(mat4 clipBox, vec4 worldPos){//add
 }
 
 #if defined(num_prism) && num_prism > 0
+    #if defined(color_type_prismHeight)
+        vec3 percentToByte(float num){
+                                        //输出是0-1, shader精度不够,只够存3个数
+            float a = 1.0;
+            float result[4];
+            for(int i=0;i<3;i++){
+                a = i == 2 ? a/255.0 : a / 256.0 ; 
+                                           //分成256份,其中255份给当前位置,最后一份给后一个位置,而到了最后一个位置时没有下一个位置了所以只分成255份
+                if(num > a){
+                    float c = num / a;
+                    float r = floor(c);
+                    r = min(255.0, r);
+                    result[i] = r;
+                    num -= r * a;
+                }else{
+                    result[i] = 0.0;
+                }
+            } 
+            return vec3(result[0]/255.0, result[1]/255.0,result[2]/255.0);  
+            
+            //除以多少255还是256?  参考uPCIndex / 255.0 应该是255
+        } 
+    #endif
     
     int insidePrism(mat3 prismInfo, int pointIndexStart, vec4 worldPos){//是否在棱柱里 
      
@@ -825,9 +850,16 @@ bool insideBox(mat4 clipBox, vec4 worldPos){//add
         }
             
         if(inside){
+            #if defined(color_type_prismHeight)
+                vColor = percentToByte((worldPos.z - zMin) / (zMax - zMin)); 
+            #endif
+            
             return worldPos.z < zMid ? 1 : 2;
         }else return 0;    
     } 
+    
+    
+    
 #endif
  
 
@@ -955,17 +987,28 @@ void doClipping(vec4 world){
         int pointIndexStart = 0;
 		for(int i = 0; i < num_prism; i++){  
             highlight = insidePrism(prismList[i], pointIndexStart, world);
-            
+              
             if(highlight>0){
-                if(highlight == 1){
-                    vColor.r += 0.5; 
-                }else if(highlight == 2){
-                    vColor.g += 0.5;
-                }
+                #ifndef color_type_prismHeight 
+                    if(highlight == 1){
+                        vColor.r += 0.5; 
+                    }else if(highlight == 2){
+                        vColor.g += 0.5;
+                    }
+                #endif
                 break;
-            } 
+            }
+        
+                   
             pointIndexStart += int(round(prismList[i][2][1])); 
 		} 
+        
+        #ifdef color_type_prismHeight 
+            if(highlight==0){
+                gl_Position = vec4(100.0, 100.0, 100.0, 1.0);
+            }
+        #endif 
+        
 	#endif
  
 }

+ 1 - 1
src/navigation/FirstPersonControlsNew.js

@@ -429,7 +429,7 @@ export class FirstPersonControls extends THREE.EventDispatcher {
                             closeMin = 0                //所以若缩放不明显(双指滑动慢),就不设置最低值。(这时候穿越障碍物会比较困难。)
                         }
                         //console.log('closeMin',closeMin)
-                        let min = math.linearClamp(dis, disBound1, disBound2,  closeMin, standardMin) //触屏和滚轮不一样,触发较为连续,所以最小值设低一点。若要保持双指相对点云位置不变,理想最小值是0,但那样就无法穿越点云(最小值太小的话穿越密集点云如树丛很困难;太大会打滑)所以当离点云近时增大最小值 
+                        let min = math.linearClamp(dis, [disBound1, disBound2],  [closeMin, standardMin]) //触屏和滚轮不一样,触发较为连续,所以最小值设低一点。若要保持双指相对点云位置不变,理想最小值是0,但那样就无法穿越点云(最小值太小的话穿越密集点云如树丛很困难;太大会打滑)所以当离点云近时增大最小值 
                         speed = Math.sign(r) * THREE.Math.clamp(dis * Math.abs(r),   min, speed) 
                         
                         //console.log(speed, dis, e.scale)

+ 20 - 1
src/viewer/sidebarNew.js

@@ -482,7 +482,26 @@ export class Sidebar{
 			}
 		));
         
-        
+        // DISTANCE2
+		elToolbar.append(this.createToolIcon(
+			Potree.resourcePath + '/icons/distance.svg',
+			'[title]MulDistance Ring',
+			() => {
+				$('#menu_measurements').next().slideDown();
+				let measurement = this.measuringTool.startInsertion({
+					 
+					//showArea: false,
+					closed: true,
+                    minMarkers:3, 
+					measureType: 'MulDistance Ring'
+                });
+
+				let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
+				let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
+				$.jstree.reference(jsonNode.id).deselect_all();
+				$.jstree.reference(jsonNode.id).select_node(jsonNode.id);
+			}
+		));
         elToolbar.append(this.createToolIcon(
 			Potree.resourcePath + '/icons/distance.svg',
 			'[title]Ver MulDistance',

+ 16 - 0
改bug的历史.txt

@@ -2,6 +2,22 @@
 
 
 
+
+
+
+
+
+
+
+2023.12.15
+反馈说地图加载慢  
+https://laser.4dkankan.com/index.html?m=SS-3yiIoMBSnw&lang=zh#/data
+
+不稳定,有时候会卡住不加载,有时候加载很快
+
+修改了updateSubTiles中childLoaded的那一句。之前是遇到一个贴图没加载好的就停止继续执行(导致每次update至多只有一个贴图加载)。现在是放开了全部执行下去,反正也只是加到加载队列里。 效果明显提升,且不卡顿。
+
+
 2023.12.12
 
 本地版在合并站架式数据集后立即切换全景模式,首次,会无法切换。