xzw 3 년 전
부모
커밋
d5e931e03a

+ 2 - 2
src/PointCloudOctreeGeometry.js

@@ -211,8 +211,8 @@ export class PointCloudOctreeGeometryNode extends PointCloudTreeNode{
 
 			let duration = performance.now() - tStart;
 			if(duration > 5){
-				let msg = `duration: ${duration}ms, numNodes: ${decoded.length}`;
-				console.log(msg);
+				/* let msg = `duration: ${duration}ms, numNodes: ${decoded.length}`;
+				console.log(msg); */
 			}
 
 			node.loadPoints();

+ 4 - 4
src/Potree.js

@@ -107,8 +107,8 @@ export const version = {
 };
 
 export let lru = new LRU();
-
-console.log('Potree ' + version.major + '.' + version.minor + version.suffix);
+ 
+//console.log('Potree ' + version.major + '.' + version.minor + version.suffix);
 
 export let pointBudget = 1 * 1000 * 1000;
 export let framenumber = 0;
@@ -181,7 +181,7 @@ export async function loadMapEntity(){
             
         }
         
-        viewer.mapViewer.mapLayer.addMapEntity(data)
+        viewer.mapViewer.mapLayer.addMapEntity(data.data || data)
     }
     if(Potree.fileServer){
         if(!Potree.settings.floorplanType || !Potree.settings.floorplanEnable)return /* 等待平面图类型定义好会加载 */
@@ -261,7 +261,7 @@ export async function loadPanos(center, callback){
 export function Log(value, color, fontSize){
     color = color || '#13f'
     fontSize = fontSize || 14
-    console.log(`%c${value}`, `color:${color};font-size:${fontSize}px`) 
+    console.warn(`%c${value}`, `color:${color};font-size:${fontSize}px`) 
 }
 
  

+ 1 - 1
src/PotreeRenderer.js

@@ -328,7 +328,7 @@ class Shader {
 		const tEnd = performance.now();
 		const duration = tEnd - tStart;
 
-		console.log(`shader compile duration: ${duration.toFixed(3)}`);
+		//console.log(`shader compile duration: ${duration.toFixed(3)}`);
 
 
 	}

+ 9 - 0
src/TextSprite.js

@@ -134,6 +134,10 @@ export class TextSprite extends THREE.Object3D{
 		texture.magFilter = THREE.LinearFilter;
 		texture.needsUpdate = true;
 		//this.material.needsUpdate = true; 
+        
+        if(this.sprite.material.map){
+            this.sprite.material.map.dispose()
+        }
 		this.sprite.material.map = texture;
 		 
         
@@ -157,6 +161,11 @@ export class TextSprite extends THREE.Object3D{
 		ctx.fill();
 		ctx.stroke();
 	}
+    
+    dispose(){
+        this.sprite.material.uniforms.map.value.dispose()
+        this.parent && this.parent.remove(this)
+    }
 
 }
 

+ 494 - 137
src/modules/Images360/Images360.js

@@ -13,28 +13,29 @@ import QualityManager from './tile/QualityManager'
 import TileDownloader from './tile/TileDownloader'
 import PanoRenderer from './tile/PanoRenderer' 
 import TilePrioritizer from './tile/TilePrioritizer'
-import { PanoSizeClass,Vectors} from '../../defines'
-
-
-//import Axis from '../../viewer/Axis'
+import { PanoSizeClass,Vectors,GLCubeFaces, PanoramaEvents} from '../../defines'
+ 
+import {transitions, easing, lerp} from "../../utils/transitions.js";
+ 
+ 
+var rot90 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1),  Math.PI/2 ); //使用的是刚好适合全景图的,给cube贴图需要转90°
+ 
 let raycaster = new THREE.Raycaster();
 //let currentlyHovered = null;
 
-var texLoader = new THREE.TextureLoader()
+let texLoader = new THREE.TextureLoader()
 let cm = new ModelTextureMaterial()
+let sm = new THREE.MeshBasicMaterial({side: THREE.BackSide});
 
-
-
+let tileArr = []
 let previousView = {
 	controls: null,
 	position: null,
 	target: null,
 };
-let sm = new THREE.MeshBasicMaterial({side: THREE.BackSide});
-var tileArr = []
 
-/* let sgHigh = new THREE.SphereGeometry(1, 128, 128);
- */
+const HighMapCubeWidth = 1
+ 
 export class Images360 extends EventDispatcher{
 
 	constructor(viewer, params){
@@ -52,12 +53,13 @@ export class Images360 extends EventDispatcher{
      
          
         //add:
-        let size = params.boundSize 
-        this.cube = new THREE.Mesh(new THREE.BoxBufferGeometry(  size.x, size.y, size.z ), cm);
+        let size = params.boundSize  
+        
+        this.cube = new THREE.Mesh(new THREE.BoxBufferGeometry(  Math.max(size.x, HighMapCubeWidth), Math.max(size.y, HighMapCubeWidth), Math.max(size.z, HighMapCubeWidth) ), cm);
         this.cube.position.copy(params.center) 
         this.cube.visible = false; 
         this.cube.layers.set(Potree.config.renderLayers.skybox)
-        this.cube.name = 'skybox'
+        this.cube.name = 'skyboxCube'
         viewer.scene.scene.add(this.cube)
           
       
@@ -66,8 +68,8 @@ export class Images360 extends EventDispatcher{
 
 		this.currentPano = null;
         this.mouseLastMoveTime = Date.now()    
-    
-    
+        this.scrollZoomSpeed = 0.06
+        this.zoomLevel = 1
     
         this.tileDownloader = new TileDownloader;
         this.qualityManager = new QualityManager
@@ -79,29 +81,62 @@ export class Images360 extends EventDispatcher{
         this.ultraHighPanoSize = this.qualityManager.getPanoSize(PanoSizeClass.ULTRAHIGH);
         this.tileDownloader.processPriorityQueue = !1;
         this.tileDownloader.tilePrioritizer = new TilePrioritizer(this.qualityManager, this.basePanoSize, this.standardPanoSize, this.highPanoSize, this.ultraHighPanoSize);    
-    
+       
+        
+        {//高分辨率cube 放大
+            this.addHighMapCube()
+            viewer.on(PanoramaEvents.Enter,(e)=>{
+                this.setHighMap(e.newPano)
+            })
+            viewer.on('panoSetZoom',(pano, zoomed)=>{
+                if(Potree.settings.displayMode == 'showPanos'){
+                    zoomed ? this.showHighMap() : this.hideHighMap() //add
+                } 
+            }) 
+             
+        }
+        
         
         
+        
+
+
+        let scroll = (e)=>{ 
+            let zoom;
+            if(Potree.settings.displayMode == 'showPanos' && Potree.settings.zoom.enabled){
+                if(e.delta > 0){
+                    zoom = 1 + this.scrollZoomSpeed 
+                }else{
+                    zoom = 1 - this.scrollZoomSpeed
+                }
+                e.delta != 0 && this.zoomBy(zoom)
+            }
+        }
+        viewer.addEventListener('global_mousewheel', scroll);
+
+
+
         viewer.addEventListener('global_click'/* "global_drop" */, (e) => {//不用"mouseup" 是因为 mouseup有drag object时也会触发
             if(Potree.settings.unableNavigate || this.flying  || e.button != THREE.MOUSE.LEFT  )return //
             
             /* if(currentlyHovered && currentlyHovered.pano){
 				this.focusPano(currentlyHovered.pano);
 			}else{//add */
-                if(!Potree.settings.dblToFocusPoint || this.currentPano){//双击不会focus点云 或者 已经focusPano了
+                if(!Potree.settings.dblToFocusPoint && this.currentPano){//双击不会focus点云 或者 已经focusPano了
                     this.flyToPanoClosestToMouse()   
                 }
-                
-                  
             //}  
         })
         
+
+
         viewer.addEventListener("global_mousemove", (e) => { 
             if(!Potree.settings.unableNavigate && Potree.settings.ifShowMarker && e.hoverViewport == viewer.mainViewport){//如果不显示marker,就在点击时再更新
                 this.updateClosestPano(e.intersectPoint)
             }
 		});
 
+
         if(!Potree.settings.isOfficial){
             this.domRoot = viewer.renderer.domElement.parentElement;
             let elUnfocus = $("<input type='button' value='unfocus'></input>");
@@ -172,7 +207,7 @@ export class Images360 extends EventDispatcher{
                     if(mode != displayMode){
                         let config = Potree.config.displayMode[mode]
                         let config2 
-                        
+                        let camera = viewer.scene.getActiveCamera()
                         
                         if(this.isAtPano() ){//this.currentPano
                             if(this.flying)config2 = config.transition 
@@ -231,9 +266,15 @@ export class Images360 extends EventDispatcher{
                         }
                         
                         this.cube.visible = config.atPano.showSkybox 
-                        this.cube.visible && this.cube.material.setProjectedPanos(this.currentPano, this.currentPano, 1)
-            
-                         
+                        if(this.cube.visible){
+                            this.cube.material.setProjectedPanos(this.currentPano, this.currentPano, 1)
+                        }else{
+                            this.smoothZoomTo(1)
+                            this.resetHighMap()
+                            this.hideHighMap() 
+                        }
+                        
+                        
                         
                         /* viewer.dispatchEvent({
                             type: "enableChangePos",
@@ -242,6 +283,15 @@ export class Images360 extends EventDispatcher{
                         }) */
                         viewer.mainViewport.unableChangePos = !config.canLeavePano
                         
+                        if(mode == 'showPanos'){  
+                            camera.far = viewer.farWhenShowPano 
+                        }else if(Potree.settings.limitFar){ 
+                            camera.far = Potree.settings.cameraFar;
+                                
+                        }  
+                        camera.updateProjectionMatrix() 
+
+                        
                         displayMode = mode
                         if(this.elDisplayModel){
                             this.elDisplayModel.value = mode == 'showPointCloud' ? ">>全景" : '>>点云'
@@ -383,7 +433,7 @@ export class Images360 extends EventDispatcher{
  
  
  
-    isAtPano(){//  
+    isAtPano(){//是否在某个漫游点上  
         return this.currentPano && viewer.scene.view.position.equals(this.currentPano.position)
     }
  
@@ -391,12 +441,26 @@ export class Images360 extends EventDispatcher{
  
  
 
+    updateProjectedPanos(){//更新材质贴图
+        //console.warn('updateProjectedPanos')
+        this.projectedPano0 && this.projectedPano1 && this.setProjectedPanos({pano0:this.projectedPano0, pano1:this.projectedPano1})
+    }
+     
 
- 
-
-
-    
 
+    setProjectedPanos(o={}){//设置cube和点云的材质贴图
+        this.cube.material.setProjectedPanos(o.pano0, o.pano1, o.progress)
+        if(o.ifPointcloud){
+            viewer.scene.pointclouds.forEach(e=>{
+                e.material.setProjectedPanos(o.pano0, o.pano1, o.progress, o.easeInOutRatio)
+            })
+        }
+        
+        //console.warn('setProjectedPanos  ', o.pano0.id , o.pano1.id)
+        this.projectedPano0 = o.pano0    
+        this.projectedPano1 = o.pano1
+        
+    }
 
 
 	
@@ -434,7 +498,7 @@ export class Images360 extends EventDispatcher{
         
         var duration = toPano.duration || 300+Math.min(Potree.config.transitionsTime.flySpeed * this.position.distanceTo(pano.position),  Potree.config.transitionsTime.panoToPano )  
         
-        //console.log("flyto "+pano.id + ' duration: ' + duration )     
+        //console.warn("flyto "+pano.id + ' duration: ' + duration )     
         
         this.nextPano = pano
         //不飞的话是否不要执行这段?
@@ -449,17 +513,14 @@ export class Images360 extends EventDispatcher{
             }
         } 
         
-		//this.load(pano).then( () => {  
-            this.cube.visible = config.atPano.showSkybox 
-            this.cube.visible && this.cube.material.setProjectedPanos(this.currentPano, pano, 0)
-            
-            
-            
-            
+		 
+        this.cube.visible = config.atPano.showSkybox 
+        /* this.cube.visible && this.cube.material.setProjectedPanos(this.currentPano, pano, 0)
+         
+        if(config.transition.showPoint){
             viewer.scene.pointclouds.forEach(e=>{
-                viewer.updateVisible(e, 'displayMode',config.transition.showPoint) 
-            }) 
-             
+                viewer.updateVisible(e, 'displayMode', true) 
+            })
             
             if(config.transition.pointUsePanoTex){
                 let easeInOutRatio = pointcloudVisi ? 0.3 : 0
@@ -467,43 +528,79 @@ export class Images360 extends EventDispatcher{
                     e.material.setProjectedPanos(this.currentPano, pano, 0, easeInOutRatio)
                 }) 
             } 
-               
             
-            const endPosition = pano.position.clone() 
-            this.flying = true
-            viewer.scene.view.setView(endPosition, target ,duration,  ()=>{//done
-                
-                if(!config.atPano.pointUsePanoTex){ 
-                    viewer.scene.pointclouds.forEach(e=>{
-                        e.material.stopProjectedPanos()
-                    })
-                }
-                //this.currentPano.exit()
-                //pano.enter()
-                this.currentPano = pano;
-                this.flying = false 
-                this.nextPano = null;
-                viewer.scene.pointclouds.forEach(e=>{
-                    viewer.updateVisible(e, 'displayMode',pointcloudVisi) 
-                })
-                done(true);
-            },(progress)=>{//onUpdate
-                this.cube.material.uniforms.progress.value = progress 
-                
+        } */
+        if(config.transition.showPoint){
+            viewer.scene.pointclouds.forEach(e=>{
+                viewer.updateVisible(e, 'displayMode', true) 
+            })
+        }            
+         
+        
+        this.setProjectedPanos({
+            progress:0,
+            ifSkybox: this.cube.visible,
+            ifPointcloud : config.transition.pointUsePanoTex,
+            easeInOutRatio : pointcloudVisi ? 0.3 : 0,
+            pano0:this.currentPano,
+            pano1:pano
+        })
+           
+         
+        
+        
+        
+        const endPosition = pano.position.clone() 
+        this.flying = true
+        
+        
+        this.beforeFlyToPano(pano,duration)
+        
+        viewer.scene.view.setView(endPosition, target ,duration,  ()=>{//done
+            
+            if(!config.atPano.pointUsePanoTex){ 
                 viewer.scene.pointclouds.forEach(e=>{
-                    e.material.uniforms.progress.value = progress 
+                    e.material.stopProjectedPanos()
                 })
-            }, easeName )
-            
-            {
-                toPano.duration = duration
-                toPano.easeName = easeName
-                this.emit('flyToPano', toPano)
             }
-        //})
+            //this.currentPano.exit()
+            //pano.enter()
+            this.currentPano = pano;
+            this.flying = false 
+            this.nextPano = null;
+            viewer.scene.pointclouds.forEach(e=>{
+                viewer.updateVisible(e, 'displayMode',pointcloudVisi) 
+            })
+            done(true);
+        },(progress)=>{//onUpdate
+            this.cube.material.uniforms.progress.value = progress 
+            
+            viewer.scene.pointclouds.forEach(e=>{
+                e.material.uniforms.progress.value = progress 
+            })
+        }, easeName )
+        
+        {
+            toPano.duration = duration
+            toPano.easeName = easeName
+            this.emit('flyToPano', toPano)
+        }
+        
     }
 
-
+    beforeFlyToPano(pano, duration){
+        if(Potree.settings.displayMode == 'showPanos'){
+            this.resetHighMap() 
+        }
+        
+        this.smoothZoomTo(1, duration / 2);  
+        
+                    
+       
+            
+        
+        
+    }
 
 
 	focusPano(toPano ){
@@ -535,7 +632,7 @@ export class Images360 extends EventDispatcher{
 
 		this.selectingEnabled = false;
  
-        //console.log("flyto "+pano.file.split('/').pop()  )
+        //console.warn("flyto "+pano.file.split('/').pop()  )
         var dur = toPano.duration == void 0 ? 700 : toPano.duration
         
         if(config.atPano.showSkybox){
@@ -548,22 +645,25 @@ export class Images360 extends EventDispatcher{
                 return ;
             }
         }
-		//this.load(pano).then( () => {
-            
-			//this.panos.forEach(e=>e.marker.material.depthTest = false) 
-            
+		  
              
             
-            this.cube.visible = config.atPano.showSkybox  
-            this.cube.visible && this.cube.material.setProjectedPanos(pano, pano, 0)
-             
-            if(config.atPano.pointUsePanoTex){//false
-                viewer.scene.pointclouds.forEach(e=>{
-                    e.material.setProjectedPanos(pano, pano, 0)
-                })
-            } 
+        this.cube.visible = config.atPano.showSkybox  
+        /* this.cube.visible && this.cube.material.setProjectedPanos(pano, pano, 0)
+         
+        if(config.atPano.pointUsePanoTex){//false
+            viewer.scene.pointclouds.forEach(e=>{
+                e.material.setProjectedPanos(pano, pano, 0)
+            })
+        }  */
              
-		//});
+        this.setProjectedPanos({
+            progress:0,
+            ifSkybox: this.cube.visible,
+            ifPointcloud : config.atPano.pointUsePanoTex, 
+            pano0:pano,
+            pano1:pano
+        })
  
         
         let newCamPos = pano.position.clone()
@@ -633,55 +733,29 @@ export class Images360 extends EventDispatcher{
 
 
 
+ 
 
-
-    /* bump(direction) {//撞墙弹回效果
-        if (!this.flying) {
-            var t, i, n, r = settings.transition,
-                o = (r.flytimeMaxDistanceThreshold * r.flytimeDistanceMultiplier + r.flyTime) / 10,
-                a = this.camera.getWorldDirection().dot(direction),
-                s = Math.abs(a) > .5;
-            if (s)
-                t = function() {
-                    transitions.start(lerp.property(this.cameraControls.cameras[ViewMode.PANORAMA], "zoom", a > 0 ? 1.04 : .96), o, i, 0, easing.easeInOutSine, "bumpZStart")
-                }
-                .bind(this),
-                i = function() {
-                    transitions.start(lerp.property(this.cameraControls.cameras[ViewMode.PANORAMA], "zoom", 1), 3 * o, n, 0, easing.easeInOutSine, "bumpZRelax")
-                }
-                .bind(this);
-            else {
-                var l = this.camera.position.clone(),
-                    c = direction.clone();
-                this.raycaster.set(l, c);
-                var h = this.model.floors.reduce(function(e, t) {
-                        return e.concat(t.collider.children)
-                    }, []),
-                    d = this.raycaster.intersectObjects(h),
-                    p = d.length > 0 ? d[0].distance / 25 : .04,
-                    g = l.clone().add(c.multiplyScalar(p));
-                t = function() {
-                        transitions.start(lerp.vector(this.cameraControls.cameras[ViewMode.PANORAMA].position, g), o, i, 0, easing.easeInOutSine, "bumpTStart")
-                    }
-                    .bind(this),
-                    i = function() {
-                        transitions.start(lerp.vector(this.cameraControls.cameras[ViewMode.PANORAMA].position, l), 5 * o, n, 0, easing.easeInOutSine, "bumpTRelax")
-                    }
-                    .bind(this)
-            }
+    bump(direction) {//撞墙弹回效果
+        if (!this.flying) {  
+            this.flying = !0 
             
+            let distance = Potree.settings.displayMode == 'showPanos' ? 0.4 : 0.2;//感觉点云模式比全景模式更明显,所以降低
+            let currentPos = this.position.clone()
+            let endPosition = new THREE.Vector3().addVectors(this.position, direction.clone().multiplyScalar(distance)) 
             
-            n = (){
-                this.mode == "panorama" && (this.flying = !1)  //改
-            }
-            
-            this.flying = !0,
-            t()
+            let duration = 150 
+            viewer.scene.view.setView(endPosition, null , duration,  ()=>{//done
+                viewer.scene.view.setView(currentPos, null , duration*5,  ()=>{//done
+                    this.flying = !1 
+                },null,'easeInOutSine')
+             
+            } ,(progress)=>{//onUpdate
+                 
+            },  'easeInOutSine' ) 
         }
-    };
- */
-
-
+        //备注:将4dkk中的‘前后方向变化fov、左右方向移动镜头’ 都改为移动镜头。 因为这里无法判断左右离壁距离。
+ 
+    }
 
 
 
@@ -735,7 +809,7 @@ export class Images360 extends EventDispatcher{
                 callback: deferred.resolve.bind(deferred, !0)
             }  );
         } else {
-            //this.bump(direction);
+            this.bump(direction);
             deferred.resolve(!1);
         }
 
@@ -869,7 +943,7 @@ export class Images360 extends EventDispatcher{
             this.updatePanoRenderer(vectorForward) 
         }
         
-        
+        this.updateZoomPano();
         
 
 	}
@@ -997,6 +1071,291 @@ export class Images360 extends EventDispatcher{
 		
 	}
 
+
+
+    //---------------scroll zoom ------------------------------------------
+    
+    
+    /* zoomIn = function() { //放大
+        this.zoomBy(1 + this.zoomSpeed);
+    }
+    zoomOut = function() {//缩小
+        this.zoomBy(1 - this.zoomSpeed);
+    } */
+    zoomBy(e) {//以倍数
+        this.zoomTo(this.zoomLevel * e);
+    } 
+    zoomTo(zoomLevel) {//缩放到某绝对zoomLevel
+        let zoom = Potree.settings.zoom
+        if (zoom.enabled) {
+            zoomLevel = THREE.Math.clamp(zoomLevel, zoom.min, zoom.max)
+            if(zoomLevel == this.zoomLevel) return;
+                
+            /* if (zoomLevel > this.zoomLevel) {
+                this.emit(ZoomEvents.ZoomIn);
+                zoomLevel === settings.zoom.max && this.emit(ZoomEvents.ZoomMax);
+            } else if (zoomLevel < this.zoomLevel) {
+                this.emit(ZoomEvents.ZoomOut);
+                zoomLevel === settings.zoom.min && this.emit(ZoomEvents.ZoomMin);
+            } */ 
+            
+            this.zoomLevel = zoomLevel;
+            viewer.setFOV(Potree.config.view.fov * (1 / this.zoomLevel))
+           
+        }
+    }
+     
+
+    zoomFovTo( fov ) { //通过fov来算zoomLevel 
+        let zoomLevel = this.baseFov / fov;
+        this.zoomTo( zoomLevel );
+    }
+	smoothZoomTo(aimLevel, dur=0) {
+		var currentLevel = this.zoomLevel 
+		if(currentLevel == aimLevel)return;	
+			
+		var fun = (progress)=>{
+            //progress > 1 && (progress = 1) 
+            let level = currentLevel * (1 - progress) +  aimLevel * progress 
+            this.zoomTo(level, !0)
+        }
+        
+			 
+		transitions.start(fun, dur, null, null, 0  , easing['easeInOutQuad'] )
+	}
+    
+    
+    /* zoomDefault{
+        this.zoomTo(1, !0)
+    } 
+    smoothZoomToDefault(e, t) {
+        var i, n = this.zoomLevel,
+            r = function(e) {
+                e > 1 && (e = 1),
+                    i = n * (1 - e) + e,
+                    this.zoomTo(i, !0)
+            }
+            .bind(this),
+            o = function() {
+                this.zoomDefault(),
+                    t && window.setTimeout(t, 50)
+            }
+            .bind(this);
+        transitions.start(r, e, o, null, 0, easing[settings.transition.blendEasing])
+    } */
+
+    
+
+    updateZoomPano() { 
+        if (!this.panoRenderer.zoomPanoRenderingDisabled && Potree.settings.displayMode == 'showPanos') {
+            var currentPano = this.currentPano;
+            if (currentPano) {
+                var activationThreshold =  Potree.settings.navTileClass == '2k' && Potree.settings.tileClass == '4k' ? 1.7 : Potree.settings.zoom.activationThreshold//1.1
+                var t = this.zoomLevel > activationThreshold,
+                    n = !(this.flying && this.nextPano && this.nextPano !== this.currentPano),
+                    r = t && n;
+                this.tileDownloader.tilePrioritizer.setZoomingActive(r);
+                this.panoRenderer.setZoomingActive(r, currentPano, !0);
+                
+                var o = (pano, zoomedFlag)=>{
+                    this.panoRenderer.resetRenderStatus(pano.id, !1, !0, this.qualityManager.getMaxNavPanoSize());
+                    this.panoRenderer.clearAllQueuedUploadsForPano(pano.id);
+                    this.panoRenderer.renderPanoTiles(pano.id, null, !1, !1);
+                    pano.setZoomed(zoomedFlag);
+                }
+                  
+                
+                if (r && (!currentPano.zoomed || this.qualityManager.zoomLevelResolution && this.qualityManager.zoomLevelResolution != '4k')) {
+                    currentPano.zoomed || o(currentPano, !0); 
+                    
+                    if(Potree.settings.navTileClass == '1k' && Potree.settings.tileClass != '1k' && this.zoomLevel < 2){
+                        this.panoRenderer.enableHighQuality( function() {//开启2k 
+                            if(Potree.settings.tileClass != '4k')  o(currentPano, !0); 
+                        }.bind(this));
+                    }else{ 
+                        this.panoRenderer.enableUltraHighQualityMode(function() {//开启4k getMaxZoomPanoSize
+                            this.qualityManager.useUltraHighResolutionPanos && (Potree.settings.zoom.max = Potree.config.ultraHighQualityMaxZoom);
+                            o(currentPano, !0)
+                        }.bind(this));
+                    } 
+                } else {  
+                    !t && currentPano.zoomed && o(currentPano, !1);
+                }
+                
+                
+                
+                if(r && Potree.settings.navTileClass == '1k' && Potree.settings.tileClass == '4k'  ){ //目前只有手机端navTileClass == '1k'
+                    var change = (zoomedFlag)=>{ 
+                        this.qualityManager.updateMaximums()//更新maxZoomPanoSize
+                        this.panoRenderer.setupZoomRenderTarget() //更新renderTarget  
+                        //currentPano.setZoomed(t);//更新uniforms贴图 
+                    }
+                    this.qualityManager.zoomLevelResolution = this.zoomLevel >= 2 ? '4k' : this.zoomLevel > 1.1 ? '2k' : '1k'
+                    
+                    if(this.oldZoomLevel < 2 && this.zoomLevel >= 2){//1k/2k-4k
+                        change()
+                        o(currentPano, t)
+                    }else if(this.oldZoomLevel <= Potree.settings.zoom.activationThreshold && this.zoomLevel > Potree.settings.zoom.activationThreshold){//1k-2k
+                        change()
+                    }else if(this.oldZoomLevel > 2 && this.zoomLevel <= 2){//4k-2k/1k
+                        change()
+                        o(currentPano, t)
+                    }else if(this.oldZoomLevel > Potree.settings.zoom.activationThreshold && this.zoomLevel <= Potree.settings.zoom.activationThreshold){//2k-1k
+                        change() 
+                    } 
+                    this.oldZoomLevel = this.zoomLevel  
+                }   
+            }
+        }
+    }
+
+
+
+
+
+
+    //--------------------
+
+
+    addHighMapCube(){//创建8*8的tile  cube   主要因手机版崩溃  要在电脑端测试得设置maxRenderTargetSize
+        
+        if( Potree.settings.tileClass == '4k' && this.qualityManager.maxRenderTargetSize == 2048){
+            
+            var geo = new THREE.PlaneGeometry(1, 1, 1, 1)
+            var cube = new THREE.Object3D;
+            for(var cubeIndex=0; cubeIndex<6; cubeIndex++){
+                var face = new THREE.Object3D;
+                for(var i=0;i<8;i++){
+                    for(var j=0;j<8;j++){
+                        var tile = new THREE.Mesh(geo, new THREE.MeshBasicMaterial({
+                            //side:THREE.DoubleSide
+                        }))
+                        tile.position.set(i-3.5, j-3.5, -4);
+                        
+                        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)  
+                        
+                        
+                        tile.visible = false 
+                        face.add(tile)
+                    }
+                }
+                switch(cubeIndex){
+                    case GLCubeFaces.GL_TEXTURE_CUBE_MAP_POSITIVE_X: 
+                        face.rotation.set(0,Math.PI/2,0);
+                        break;
+                    case GLCubeFaces.GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+                        face.rotation.set(0,-Math.PI/2,0);
+                        break;
+                    case GLCubeFaces.GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+                        var rot1 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,1,0),Math.PI)
+                        var rot2 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1,0,0),Math.PI/2)
+                        
+                        face.quaternion.copy(rot1).multiply(rot2)
+                        //face.rotation.set(Math.PI/2,0,0);
+                        break;
+                    case GLCubeFaces.GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+                        //face.rotation.set(-Math.PI/2,0,0);
+                        var rot1 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,1,0),Math.PI)
+                        var rot2 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1,0,0),-Math.PI/2)
+                        
+                        face.quaternion.copy(rot1).multiply(rot2)
+                        break;
+                    case GLCubeFaces.GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+                        face.rotation.set(0,Math.PI,0);
+                        break;
+                    case GLCubeFaces.GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+                        face.rotation.set(0,0,0);
+                   
+                }  
+                face.scale.set(1,-1,1)
+                cube.add(face) 
+            }
+            cube.name = 'highMapCube'
+            this.highMapCube = cube
+            viewer.scene.scene.add(cube)
+            //cube.scale.set(0.01,0.01,0.01)
+            
+            this.highMapCube.visible = false; 
+            viewer.setObjectLayers(this.highMapCube, 'sceneObjects'/* 'skybox' */) //如果是skybox层,点云可见时会被遮住,depthTest为false呢? 但不会遮住场景物体
+            console.warn('addHighMapCube')
+            
+        }    
+        
+    }
+    
+    
+    isHighMapLoaded( cubeFace, tileX, tileY){
+        var tile = this.highMapCube.children[cubeFace].children[tileX*8+tileY];
+        return !!tile.material.map
+    }
+    
+    
+    updateHighMap(tex, cubeFace, tileX, tileY){ 
+        //console.warn('updateHighMap')
+        var tile = this.highMapCube.children[cubeFace].children[tileX*8+tileY]; 
+        
+        tile.material.map = tex;
+        
+        tile.material.opacity = 1;
+        tile.material.transparent = false
+        
+        
+        tile.visible = true
+        tile.material.needsUpdate = true  //发现每次开始放大但还未放大到4k时也会把之前加载过的4k加载
+    }
+    
+    
+    
+    resetHighMap(){ 
+    
+        if(!this.highMapCube)   return 
+        console.warn('resetHighMap')
+        this.highMapCube.children.forEach(e=>e.children.forEach(tile=>{
+            if(tile.material.map){
+                tile.material.map.dispose() 
+                tile.material.map.loaded = !1 
+                tile.material.map.version = 0  
+                
+                var h = viewer.renderer.properties.get(tile.material.map)
+                viewer.renderer.getContext().deleteTexture(h.__webglTexture)
+                //类似app.sceneRenderer.deallocateCubeTexture(tile.material.map) 
+                 
+                tile.material.map = null            
+                /* tile.material.opacity = 0.4;
+                tile.material.transparent = true */
+                tile.material.needsUpdate = true
+                tile.visible = false 
+            }
+        }))
+        this.highMapCube.visible = false;
+    }
+    
+    setHighMap(pano){
+        if(!this.highMapCube)   return 
+        this.highMapCube.position.copy(pano.position)
+ 
+        //可以利用第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 ) )
+    }
+    
+    showHighMap(){ 
+        if(!this.highMapCube)   return 
+        console.warn('showHighMap')
+        this.highMapCube.visible = true; 
+    } 
+    hideHighMap(){ 
+        if(!this.highMapCube)   return
+        console.warn('hideHighMap')        
+        this.highMapCube.visible = false;
+    }
+    //缩小后继续显示cube呢还是不显示?  不显示的话,就要把cube上的复制到renderTarget上……会不会又崩溃,or没加载的显示???
+    
+    
+    
 };
 
 
@@ -1132,10 +1491,8 @@ Images360.sortFunctions =  {//排序函数,涉及到两个item相减
 export class Images360Loader{ 
 
     static async load(viewer, params, callback ){
-
-		 
-		
-		let center = viewer.transform.lonlatToLocal.inverse(viewer.bound.center)
+  
+		let center = params.center.clone()
         center = {lat:center.y, lon:center.x} //中心点 
         
         Potree.loadPanos(center,(data)=>{
@@ -1158,7 +1515,7 @@ export class Images360Loader{
             })
             
             
-            viewer.setObjectLayers(images360.node, 'marker')
+            viewer.setObjectLayers(images360.node, 'marker'/* 'sceneObjects' */)
              
             viewer.images360 = window.images360 = images360//add
             images360.tileDownloader.setPanoData(images360.panos, [] /* , Potree.settings.number */);

+ 49 - 31
src/modules/Images360/Panorama.js

@@ -73,7 +73,9 @@ class Panorama extends EventDispatcher{
         this.pointcloud = viewer.scene.pointclouds.find(e=>e.dataset_id == o.dataset_id) || viewer.scene.pointclouds[0]
         this.pointcloud.panos.push(this)
         this.pointcloud.addEventListener('isVisible',(e)=>{ 
-            viewer.updateVisible(this, 'pointcloudVisi', e.visible) 
+            if(e.reason == 'datasetSelection'){//数据集隐藏时漫游点也隐藏
+                viewer.updateVisible(this, 'pointcloudVisi', e.visible) 
+            }
         })
         this.addEventListener('isVisible',(e)=>{//是否显示该点的mesh(不显示也能走)
             this.marker.visible = e.visible
@@ -101,7 +103,11 @@ class Panorama extends EventDispatcher{
             qua = [qua[1], qua[2], qua[3], qua[0]] 
             this.quaternion = new THREE.Quaternion().fromArray(qua)
             this.quaternion4dkk = math.convertVisionQuaternion(this.quaternion)//4dkk内使用的quaternion 
+            
             this.quaternion = new THREE.Quaternion().multiplyQuaternions(this.quaternion,  rot90);//全景图和Cube的水平采样起始坐标相差90度,cubeTex转90度
+            
+            this.rotation4dkk = new THREE.Euler().setFromQuaternion(this.quaternion4dkk)
+            this.rotation = new THREE.Euler().setFromQuaternion(this.quaternion) 
          //}
          
          
@@ -217,6 +223,8 @@ class Panorama extends EventDispatcher{
         let floorPosition = this.originFloorPosition.clone().applyMatrix4(this.pointcloud.transformMatrix);
         this.setPosition(position, floorPosition) 
         this.panoMatrix = new THREE.Matrix4().multiplyMatrices(this.oriPanoMatrix, this.pointcloud.rotateMatrix) 
+    
+        //quaternion也变下  
     }
     
     setPosition(position, floorPosition){
@@ -225,7 +233,11 @@ class Panorama extends EventDispatcher{
         this.mesh.position.copy(this.position)
         this.marker.position.copy(this.floorPosition) 
         this.marker.position.z+=0.1//会被点云遮住
-        this.label && (this.label.position.copy(this.floorPosition), this.label.position.z+=0.2)
+        if(this.label){
+            this.label.position.copy(this.floorPosition), this.label.position.z+=0.2
+            this.label.update()
+        }
+          
     }
     
     
@@ -250,12 +262,20 @@ class Panorama extends EventDispatcher{
         if(!e.byMap) this.emit('hoverOff', {byMainView:true})
     }
     
+    
+    
+    setZoomed(zoomed){
+        this.zoomed = zoomed;
+        Potree.settings.displayMode == 'showPanos' && this.updateSkyboxForZoomLevel(); //放大后换成zoomTarget贴图
+        viewer.emit('panoSetZoom', this, zoomed)
+        
+    }
+    
+    
     enter(){ 
         this.setZoomed(!1),
-        this.dispatchEvent({type:PanoramaEvents.Enter, oldPano:old, newPano:this  }  ),
+        viewer.emit(PanoramaEvents.Enter,  {oldPano:old, newPano:this  }  )
         old = this 
-        //this.model.setHighMap(this)//add
-        
         //console.log("enter pano "+ this.id)
     } 
 
@@ -279,42 +299,40 @@ class Panorama extends EventDispatcher{
         
         //console.log("exit pano "+ this.id)
         
-        this.emit(PanoramaEvents.Exit, this); 
+        viewer.emit(PanoramaEvents.Exit, this); 
+    }
+    
+    
+    updateSkyboxForZoomLevel(){
+        if(this.minimumTiledPanoLoaded){
+            this.images360.updateProjectedPanos();
+        }
+         
     }
-
     
     getSkyboxTexture(){
-        /* if(this.tiled)
-        { */
-            if(this.minimumTiledPanoLoaded)
+     
+        if(this.minimumTiledPanoLoaded)
+        {
+            if(this.zoomed && this.images360.qualityManager.maxRenderTargetSize > this.images360.qualityManager.maxNavPanoSize)//change 如果放大后和不放大都是2k就不用这个
             {
-                if(this.zoomed && this.images360.qualityManager.maxRenderTargetSize > this.images360.qualityManager.maxNavPanoSize)//change 如果放大后和不放大都是2k就不用这个
-                {
-                    return this.images360.panoRenderer.zoomRenderTarget.texture;   
-                }
-                else
-                {
-                    
-                    this.tiledPanoRenderTarget.texture.mapping = THREE.UVMapping//add
-                    return this.tiledPanoRenderTarget.texture;
-                }
+                return this.images360.panoRenderer.zoomRenderTarget.texture;   
             }
             else
             {
-                return null;
+                
+                this.tiledPanoRenderTarget.texture.mapping = THREE.UVMapping//add
+                return this.tiledPanoRenderTarget.texture;
             }
-        /* }
+        }
         else
-        { 
-            return this.solidSkybox;
-        }*/
+        {
+            return null;
+        }
+         
     }
     
-    setZoomed(e){
-        this.zoomed = e;
-        //this.updateSkyboxForZoomLevel();
-        //e ? this.model.showHighMap() : this.model.hideHighMap() //add
-    }
+   
     
     isLoaded(e){
         //if (this.tiled) {
@@ -363,7 +381,7 @@ class Panorama extends EventDispatcher{
         if(e === this.id)
         {
             this.minimumTiledPanoLoaded = !0;
-            //this.updateSkyboxForZoomLevel();//更新贴图 setProjected
+            this.updateSkyboxForZoomLevel();//更新贴图 setProjected
             t > this.highestPartialTileRenderOpCompleted && (this.highestPartialTileRenderOpCompleted = t);//应该是更新最高获取到的Partial size
             !n && t > this.highestFullTileRenderOpCompleted && (this.highestFullTileRenderOpCompleted = t); //应该是更新最高获取到的Full size
             //this.emit("load", t);

+ 7 - 2
src/modules/datasetAlignment/Alignment.js

@@ -6,7 +6,9 @@ import SplitScreen from "../../utils/SplitScreen"
 
 
 var Alignment = {
-     
+    SplitScreen, 
+    handleState:null,  //'translate'|'rotate'
+    
     setMatrix :  function(pointcloud){
         var vec1 = pointcloud.position     //position为数据集内部的偏移,在navvis中对应的是dataset.pointCloudSceneNode的children[0].position
         var vec2 = pointcloud.translateUser
@@ -54,7 +56,10 @@ var Alignment = {
     } 
     
     ,
-    
+    switchHandle:function(state){
+        this.handleState = state
+        
+    }
     
     
 }

+ 5 - 5
src/navigation/FirstPersonControls.js

@@ -131,7 +131,7 @@ export class FirstPersonControls extends EventDispatcher {
                     let moveVec = Utils.getOrthoCameraMoveVec(e.drag.pointerDelta, camera )
                       
                       
-                    if(viewport.alignmenet && e.drag.intersectStart){//如果拖拽着点云  修改模型位置
+                    if(viewport.alignment && viewport.alignment.handleState == 'translate' && e.drag.intersectStart){//如果拖拽着点云  修改模型位置
                         this.viewer.dispatchEvent({
                             type : "translatePointcloud", 
                             vec : moveVec
@@ -144,7 +144,7 @@ export class FirstPersonControls extends EventDispatcher {
                     
                     
                 }else{  
-                    if(viewport.alignmenet && e.drag.intersectStart){//如果拖拽着点云 
+                    if(e.drag.intersectStart){//如果拖拽着点云 
                          
                         if(e.drag.z == void 0){//拖拽开始
                             let pointerStartPos2d = e.drag.intersectStart.location.clone().project(camera);//识别到的点云点的位置
@@ -183,7 +183,8 @@ export class FirstPersonControls extends EventDispatcher {
                             speed = FirstPersonControls.boundPlane.distanceToPoint(this.currentViewport.position)   
                             speed = Math.max(1 , speed) 
                         }  */
-                        let speed = camera.position.distanceTo(window.viewer.reticule.position)   
+                        let lastIntersect = viewport.lastIntersect ? (viewport.lastIntersect.location || viewport.lastIntersect) : viewer.bound.center  //该viewport的最近一次鼠标和点云的交点
+                        let speed = camera.position.distanceTo(lastIntersect)   
                         let fov = cameraLight.getHFOVForCamera(camera, camera.aspect, 1)
                         let ratio = speed  * Math.tan(THREE.Math.degToRad(fov)/2) 
                         this.translationDelta.x -= e.drag.pointerDelta.x  * ratio
@@ -220,8 +221,7 @@ export class FirstPersonControls extends EventDispatcher {
                 let limit = Potree.config.OrthoCameraLimit.zoom
                 zoom = THREE.Math.clamp(zoom, limit.min,limit.max )
                 
-                if(camera.zoom != zoom){
-                    console.log('zoom')
+                if(camera.zoom != zoom){ 
                     camera.zoom = zoom
                     camera.updateProjectionMatrix()
                 }

+ 31 - 16
src/navigation/InputHandler.js

@@ -306,9 +306,12 @@ export class InputHandler extends EventDispatcher {
 			}
 		}
 
+
+        
+        
+
 		if (!this.drag) {
-			let target = this.hoveredElements
-				.find(el => (
+			let target = e.button == THREE.MOUSE.LEFT && this.hoveredElements.find(el => (//只有左键能拖拽
 					el.object._listeners &&
 					el.object._listeners['drag'] &&
 					el.object._listeners['drag'].length > 0));
@@ -319,6 +322,10 @@ export class InputHandler extends EventDispatcher {
 				this.startDragging(null);
 			}
 		}
+        
+        
+        
+        
         //add
         this.drag.pointerDragStart = this.pointer.clone()
         this.drag.intersectStart = this.intersectPoint;
@@ -540,7 +547,7 @@ export class InputHandler extends EventDispatcher {
 		}
  
         //add
-        let intersectPoint = viewport.noPointcloud ? null : Utils.getMousePointCloudIntersection(
+        let intersectPoint = viewport.noPointcloud? null : Utils.getMousePointCloudIntersection(
             viewport,
             this.mouse,
             this.pointer, 
@@ -549,14 +556,18 @@ export class InputHandler extends EventDispatcher {
             this.viewer.scene.pointclouds,
             {pickClipped: true});
             
-            
-        if(viewport.name == 'mapViewport'){ 
+          
+        if(viewport.camera.type == 'OrthographicCamera'/*  == 'mapViewport' */){ 
             let pos3d = new THREE.Vector3(this.pointer.x,this.pointer.y,-1).unproject(viewport.camera); //z:-1朝外   
-            intersectPoint = pos3d.clone().setZ(0);//z初始默认为0
-             
+            if(!intersectPoint){
+                intersectPoint = {}
+            }   
+            intersectPoint.orthoIntersect = pos3d.clone()
+               
         }    
+        
  
-		if (this.drag) {//有按下鼠标拖拽(不一定拖拽了物体)
+		if (this.drag) {//有拖拽(不一定拖拽了物体, 也不一定按下了鼠标
 			this.drag.mouse = e.buttons; 
             this.drag.hoverViewport = this.hoverViewport
 			/* this.drag.mouseDelta.x = this.mouse.x - this.drag.end.x;
@@ -565,7 +576,7 @@ export class InputHandler extends EventDispatcher {
 			this.drag.end.set(this.pointer.x, this.pointer.y);
             
             
-			if (this.drag.object && (e.buttons == MOUSE.LEFT || e.buttons == MOUSE.NONE)) {//add LEFT  如果按下右键或中建,就暂停拖拽:
+			if (this.drag.object && (e.buttons == MOUSE.NONE || !this.drag.notPressMouse )){//add notPressMouse 如果标记是不需要按鼠标的拖拽,则一旦按下鼠标,就暂停拖拽物体(改为拖拽场景):(如添加测量时突然拖拽画面)
 				if (this.logMessages) console.log(this.constructor.name + ': drag: ' + this.drag.object.name);
 				this.drag.object.dispatchEvent({
 					type: 'drag',
@@ -630,7 +641,7 @@ export class InputHandler extends EventDispatcher {
 
             //仅在鼠标不按下时更新:
             
-            if(intersectPoint &&  viewport.alignment ){
+            if(viewport.alignment && intersectPoint && intersectPoint.location ){
                 viewer.dispatchEvent({
                     type : "CursorChange", action : "add",  name:"movePointcloud"
                 })
@@ -670,7 +681,7 @@ export class InputHandler extends EventDispatcher {
         this.intersectPoint = intersectPoint 
         
         
-        
+        intersectPoint && (this.hoverViewport.lastIntersect = intersectPoint)
         
         /* for (let inputListener of this.getSortedListeners()) {
             inputListener. */this.viewer.dispatchEvent({
@@ -740,6 +751,7 @@ export class InputHandler extends EventDispatcher {
         
         this.viewer.dispatchEvent({
             type: "startDragging",
+            drag: this.drag,
             hoverViewport: this.hoverViewport
         })
         /* console.log('startDragging')
@@ -888,15 +900,18 @@ export class InputHandler extends EventDispatcher {
 		raycaster.ray.set(ray.origin, ray.direction);  
         raycaster.camera = camera //add
         
-        /* let {origin,direction}  = this.getMouseDirection()
-        let raycaster = new THREE.Raycaster();
-		raycaster.ray.set(origin, direction); */
+      
         
         
 		raycaster.params.Line.threshold = 0.2;
-        raycaster.layers.enableAll()//add
+        //raycaster.layers.enableAll()//add
+        viewer.setCameraLayers(raycaster,   //设置能识别到的layers(如空间模型里只有mapViewer能识别到marker)
+            ['sceneObjects','mapObjects','measure','marker','transformationTool'],
+            this.hoverViewport && this.hoverViewport.extraEnableLayers
+        )
+        
         
-        this.viewer.emit('raycaster', {viewport: this.hoverViewport})//add
+        viewer.emit('raycaster', {viewport: this.hoverViewport})//add
 		let intersections = raycaster.intersectObjects(interactables.filter(o => o.visible), true); //原本是false 检测不到children
          
         intersections = intersections.map(e=>{//add 转化为interactables

+ 4 - 3
src/navigation/RouteGuider.js

@@ -62,7 +62,8 @@ export class RouteGuider extends EventDispatcher{
                 }) 
             }
         }
-         
+        polesMats.shadowMat.map.anisotropy = 4 
+        
         this.poleStart = this.createPole(polesMats, 'start') 
         this.poleEnd = this.createPole(polesMats, 'end') 
         
@@ -271,10 +272,10 @@ export class RouteGuider extends EventDispatcher{
             
             
             Potree.fileServer.get(url).then((data)=>{
-                console.log(data)
+                console.log(data.data)
                 if(!this.routeStart || !this.routeEnd)return 
                 
-                data.forEach(item=>{
+                data.data.forEach(item=>{
                     let pos = viewer.transform.lonlatToLocal.forward(item.location.slice(0))
                     pos = new THREE.Vector3().fromArray(pos)
                     this.route.push(pos)

+ 45 - 7
src/settings.js

@@ -78,7 +78,8 @@ const config = {//配置参数   不可修改
     }
     ,
     view:{
-        fov:50,  //navvis:50
+        fov:50,  //navvis:50 
+        
     },
     
     pointDensity:{
@@ -103,6 +104,10 @@ const config = {//配置参数   不可修改
     
     
     
+    clip:{
+        color: '#FFC266', //map
+        
+    },
     
     
     measure:{
@@ -127,9 +132,12 @@ const config = {//配置参数   不可修改
      
     
     renderLayers:{//渲染层,方便分批渲染管理,替代scene的创建。数字不代表顺序。
+        bg: 0, 
+        bg2: 100,
         
         skybox: 1,
-        pointcloud: 0,
+        pointcloud: 11,
+        sceneObjects:2,//default
         marker: 2,
         reticule: 3,
         measure:4,  
@@ -138,9 +146,26 @@ const config = {//配置参数   不可修改
         transformationTool:7,
         route:10,
         map:8,
-        mapObjects:9,
+        mapObjects:9,//default
+        
+        siteModeOnlyMapVisi:12,//只能mapViewer可见
+        siteModelMapUnvisi:13,//只有mapViewer不可见
+        siteModeSideVisi:14,//只有侧面可见
     },
     
+    
+    siteModel:{
+        names:{
+            'building': '建筑',
+            'floor':'楼层',
+            'room':'房间'
+        },
+        floorHeightDefault: 5,//一层楼的高度
+        
+        
+    },
+    
+     
     tiling: {
         panoPreRenderRepeatDelay: 2500,
         panoPreRenderDelay: 500,
@@ -174,7 +199,8 @@ const config = {//配置参数   不可修改
         }
     }
     ,
-    
+    highQualityMaxZoom: 2,
+    ultraHighQualityMaxZoom: 3,
 }
 /* 显示模式:
 
@@ -189,6 +215,7 @@ function getPrefix(){
     return v[0]
 }
 
+ 
 let settings = {//设置   可修改
     number: '', //场景序号
     isOfficial:false,
@@ -199,12 +226,23 @@ let settings = {//设置   可修改
     ifShowMarker:true,//显示漫游点
     floorplanType:null,//平面图类型 'default' | 'diy'
     floorplanEnable:false,
-    cameraFar : 300, //相机最远范围 1-300
-    limitFar: true, //是否使用setting的cameraFar来限制(如在点云裁剪时为false)
+    cameraFar : 10000, //相机最远范围 1-300
+    //limitFar: true, //是否使用setting的cameraFar来限制(如在点云裁剪时为false)
     showPanoMesh:false, //显示小球,
     dblToFocusPoint:false,//调试时如果需要双击飞向某个点云的点,就打开。此时不在漫游点的话单击将无法漫游。//因和单击漫游冲突 
     
-    unableNavigate : false//进入如裁剪界面时 禁止漫游
+    unableNavigate : false,//进入如裁剪界面时 禁止漫游
+    
+    zoom:{
+        enabled : true,
+        min:1,
+        max: config.highQualityMaxZoom,
+        activationThreshold: 1.1,
+    },
+    
+    navTileClass:'2k',  //默认加载到
+    tileClass:'4k',     //最高可达
+    
 }
 
 

+ 2 - 2
src/utils.js

@@ -1160,8 +1160,8 @@ Utils.computePointcloudsBound = function(pointclouds){
         pointcloud.bound = boundingBox_
         boundingBox.union(boundingBox_)
     })
-    var boundSize = boundingBox.getSize()
-    var center = boundingBox.getCenter()
+    var boundSize = boundingBox.getSize(new THREE.Vector3)
+    var center = boundingBox.getCenter(new THREE.Vector3)
     return {boundSize, center, boundingBox}
 }
 

+ 23 - 6
src/utils/CursorDeal.js

@@ -1,4 +1,6 @@
 
+import Common from './Common' 
+
 
 //处理cursor优先级
 
@@ -6,14 +8,27 @@
 var CursorDeal = {
     priorityEvent : [//在前面的优先级高
         {"movePointcloud":'move'},
-        {"measure_isIntersectSelf":'not-allowed'},
+        {"markerMove":'grab'},
+        {"polygon_isIntersectSelf":'not-allowed'},
+        {"polygon_AtWrongPlace":'not-allowed'},
+        {'mapClipMove':'move'},
+        {'mapClipRotate':`url({Potree.resourcePath}/images/rotate-cursor.png), url({Potree.resourcePath}/images/rotate-cursor.cur),auto`},
+        {'siteModelFloorDrag':'row-resize'},
     ], 
     list:[], //当前存在的cursor状态
     currentCursorIndex:null,
     
-    attachToViewer : function(viewer){
+    init : function(viewer){
+        
+        this.priorityEvent.forEach(e=>{//刚开始Potree.resourcePath没值,现在换
+            for(let i in e){
+                e[i] = Common.replaceAll(e[i],'{Potree.resourcePath}',Potree.resourcePath)
+            }
+        })
         
-        this.domElement = viewer.renderArea;
+         
+        
+        this.domElements = [viewer.renderArea, viewer.mapViewer.renderArea];
         
         viewer.addEventListener("CursorChange",(e)=>{
             if(e.action == 'add'){
@@ -60,24 +75,26 @@ var CursorDeal = {
         if(o.addItem){
             var addIndex = this.priorityEvent.indexOf(o.addItem) 
             if(addIndex < this.currentCursorIndex || this.currentCursorIndex == void 0){ 
-                this.domElement.style.cursor = o.addItem[o.name] 
+                this.domElements.forEach(e=>e.style.cursor = o.addItem[o.name] )
                 this.currentCursorIndex = addIndex
             }  
         }else{
             var levelMax = {index:null, cursor:null }
             this.list.forEach(name=>{
                 var priorityItem = this.priorityEvent.find(e=>e[name])
-                var index = this.priorityEventindexOf(priorityItem)
+                var index = this.priorityEvent.indexOf(priorityItem)
                 if(index < levelMax.index){
                     levelMax.index = index;
                     levelMax.cursor = priorityItem[name]
                 }
             })
             this.currentCursorIndex = levelMax.index
-            this.domElement.style.cursor = levelMax.cursor || ''  
+            this.domElements.forEach(e=>e.style.cursor = levelMax.cursor || '')
         }
         
     }
+    
+     
 }
 
 

+ 74 - 60
src/utils/DrawUtil.js

@@ -12,22 +12,10 @@ import {LineMaterial} from "../../libs/three.js/lines/LineMaterial.js";
 var defaultColor = new THREE.Color(1,1,1);//config.applicationName == "zhiHouse" ? Colors.zhiBlue : Colors.lightGreen;
 
 var LineDraw = {
-    /* 
-        普通线
-    */
-	createLine: function (posArr, o) {
-		var e = new THREE.BufferGeometry
-			, p = new Float32Array(6);
-
-		e.addAttribute("position", new THREE.BufferAttribute(p, 3));
-		//这句新旧版写法不同  旧版这样:e.addAttribute("position",Float32Array,2,3);
-		var p = e.attributes.position.array;
-		for (var i = 0; i < 2; i++) {
-			p[i * 3] = posArr[i].x;
-			p[i * 3 + 1] = posArr[i].y;
-			p[i * 3 + 2] = posArr[i].z;
-		}
-		var mat = o.mat || new THREE[o.deshed ? "LineDashedMaterial" : "LineBasicMaterial"]({
+    
+	createLine: function (posArr, o={}) {
+        //多段普通线  (第二个点和第三个点之间是没有线段的, 所以不用在意线段顺序)
+        var mat = o.mat || new THREE[o.deshed ? "LineDashedMaterial" : "LineBasicMaterial"]({
 			linewidth: o.linewidth || 1,
 			//windows无效。 似乎mac/ios上粗细有效 ? 
 			color: o.color || defaultColor,
@@ -36,25 +24,25 @@ var LineDraw = {
             dashSize : o.dashSize || 0.1,
             gapSize: o.gapSize || 0.1
 		})
-        
-		var line = new THREE.Line(e, mat);
+        var line = new THREE.LineSegments(new THREE.BufferGeometry, mat);
 		line.renderOrder = o.renderOrder || 4
-        o.deshed && line.computeLineDistances()
-		//同tagStem;   //如果不加高,可能会部分被model遮住
-		return line;
+  
+        this.moveLine(line, posArr)
+        
+		return line;  
 
 	},
 	moveLine: function (line, posArr) {
-		var p = line.geometry.attributes.position.array;
-		for (var i = 0; i < 2; i++) {
-			if (posArr[i] == void 0)
-				continue;
-			p[i * 3] = posArr[i].x;
-			p[i * 3 + 1] = posArr[i].y;
-			p[i * 3 + 2] = posArr[i].z;
-		}
+        if(posArr.length == 0)return
+        let position = []
+        posArr.forEach(e=>position.push(e.x,e.y,e.z))
+        line.geometry.setAttribute('position', new THREE.Float32BufferAttribute(new Float32Array(position), 3));
+      
 		line.geometry.attributes.position.needsUpdate = true;
 		line.geometry.computeBoundingSphere();
+        if(line.material instanceof THREE.LineDashedMaterial){
+            line.computeLineDistances()
+        }
 	}  
 	,
      /* 
@@ -126,7 +114,7 @@ var LineDraw = {
 			color: o.color || 0xffffff,
 			linewidth: o.linewidth || 5, // in pixels
 			//vertexColors: THREE.VertexColors,//THREE.VertexColors,
-			resolution:  o.resolution,// to be set by renderer, eventually
+			resolution:  o.resolution || new THREE.Vector2(100,100),// to be set by renderer, eventually
 			//viewportOffset:  o.viewportOffset,
 			transparent:true, //o.dontAlwaysSeen ? false : true,
 			depthTest:   false,//  o.alwaysShow ? false : true,//o.dontAlwaysSeen ? true : false
@@ -134,8 +122,8 @@ var LineDraw = {
             dashSize : o.dashSize || 0.1,
             gapSize: o.gapSize || 0.1,
             
-            useDepth: o.useDepth,  
-            dashed :o.dashed
+            useDepth: !!o.useDepth,  
+            dashed: !!o.dashed
            /*  transparent:o.dontAlwaysSeen ? false : true,
 			depthTest:o.dontAlwaysSeen ? true : false
              */
@@ -186,7 +174,9 @@ var LineDraw = {
 	},
 	moveFatLine: function(line, posArr){
 		var geometry = line.geometry;
-		geometry.setPositions( posArr );  
+		geometry.setPositions( [
+            ...posArr[0].toArray(), ...posArr[1].toArray(),  
+        ]);  
         
         
         if(line.material.defines.USE_DASH != void 0){
@@ -197,34 +187,46 @@ var LineDraw = {
         
         
         
-	}
+	},
+    
+    updateLine: function(line, posArr){
+        if(line instanceof Line2){
+            LineDraw.moveFatLine(line,posArr) 
+        }else{
+            LineDraw.moveLine(line,posArr)
+        }  
+    }
+    
 }
 
 var MeshDraw = { 
-    
+    getShape:function(points, holes){
+        var shape = new THREE.Shape();
+        shape.moveTo( points[0].x, points[0].y );
+        for(var i=1,len=points.length; i<len; i++){
+            shape.lineTo(points[i].x, points[i].y ) 
+        } 
+        
+        /* var holePath = new THREE.Path()
+                .moveTo( 20, 10 )
+                .absarc( 10, 10, 10, 0, Math.PI * 2, true ) 
+            arcShape.holes.push( holePath );
+         */
+        if(holes){//挖空
+            holes.forEach((points)=>{
+                var holePath = new THREE.Path()
+                holePath.moveTo( points[0].x, points[0].y )
+                for(var i=1,len=points.length; i<len; i++){
+                    holePath.lineTo(points[i].x, points[i].y ) 
+                } 
+                shape.holes.push( holePath );
+            }) 
+        }
+        return shape        
+    },
     getShapeGeo: function(points, holes){//获取任意形状(多边形或弧形)的形状面  //quadraticCurveTo() 这是弧形的含函数
-		var shape = new THREE.Shape();
-		shape.moveTo( points[0].x, points[0].y );
-		for(var i=1,len=points.length; i<len; i++){
-			shape.lineTo(points[i].x, points[i].y ) 
-		} 
 		
-		/* var holePath = new THREE.Path()
-				.moveTo( 20, 10 )
-				.absarc( 10, 10, 10, 0, Math.PI * 2, true ) 
-			arcShape.holes.push( holePath );
-		 */
-		if(holes){//挖空
-			holes.forEach((points)=>{
-				var holePath = new THREE.Path()
-				holePath.moveTo( points[0].x, points[0].y )
-				for(var i=1,len=points.length; i<len; i++){
-					holePath.lineTo(points[i].x, points[i].y ) 
-				} 
-				shape.holes.push( holePath );
-			}) 
-		} 
-		var geometry = new THREE.ShapeBufferGeometry( shape );  //ShapeGeometry
+		var geometry = new THREE.ShapeBufferGeometry( this.getShape(points, holes) );  //ShapeGeometry
         
        /*  var matrix = new THREE.Matrix4();//将竖直的面变为水平
 		matrix.set(//z = y 
@@ -235,13 +237,25 @@ var MeshDraw = {
 		)
 		geometry.applyMatrix(matrix) */
 		//geometry.computeVertexNormals();//对于光照需要的是点法线
-        
-        
-        
+         
 		return geometry;
 		
 		
 	},
+    
+    
+    getExtrudeGeo:  function(points, height){//获得挤出棱柱
+        var shape = this.getShape(points)
+        var extrudeSettings = {
+            steps: 1,
+            bevelEnabled: false,
+            depth: height,
+        };
+        var geometry = new THREE.ExtrudeBufferGeometry( shape, extrudeSettings );
+        return geometry;
+    },
+    
+    
 	getUnPosPlaneGeo : function(){//获取还没有赋值位置的plane geometry
 		var e = new Uint16Array([0, 1, 2, 0, 2, 3])
 		//	, t = new Float32Array([-.5, -.5, 0, .5, -.5, 0, .5, .5, 0, -.5, .5, 0])
@@ -249,7 +263,7 @@ var MeshDraw = {
 			, g = new THREE.BufferGeometry;
 		g.setIndex(new THREE.BufferAttribute(e, 1)),
 		//g.addAttribute("position", new n.BufferAttribute(t, 3)),
-		g.addAttribute("uv", new THREE.BufferAttribute(i, 2)) 
+		g.setAttribute("uv", new THREE.BufferAttribute(i, 2)) 
 		return function(){
 			return g
 		}	 

+ 122 - 242
src/utils/Measure.js

@@ -3,7 +3,7 @@ import * as THREE from "../../libs/three.js/build/three.module.js";
 import {TextSprite} from "../TextSprite.js"; 
 import {Utils} from "../utils.js";
 import  Label  from "./Label.js";
-import {LineDraw,MeshDraw} from "../utils/DrawUtil";
+import {LineDraw} from "../utils/DrawUtil";
 import math from "./math.js";
 import {MOUSE} from "../defines.js"; 
 import DepthBasicMaterial from "../materials/DepthBasicMaterial.js";
@@ -13,16 +13,15 @@ import {config} from '../settings'
 import {ctrlPolygon} from './ctrlPolygon'
 
 
-let texLoader = new THREE.TextureLoader() 
-const defaultNormal = new THREE.Vector2(0,1)
+let texLoader = new THREE.TextureLoader()  
 let color = new THREE.Color(config.measure.lineColor)
 let textColor = new THREE.Color(config.measure.textColor)
 let highLightColor = new THREE.Color(config.measure.highLightColor)
-var sphereMats;  
+var markerMats;  
 var lineMats;  
 var planeMats 
 
-const sphereSizeInfo = {
+const markerSizeInfo = {
     minSize : 25 ,  maxSize : 65,   nearBound : 0.2, farBound : 8,
 }
 const labelSizeInfo = {width2d:200}
@@ -46,13 +45,15 @@ const subLabelProp = {
 
 export class Measure extends ctrlPolygon{
 	constructor (prop) {
+        prop.dimension = '2d'
+        
 		super('measure',prop);
 		this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
 		 
         
         this.name = this.measureType + this.constructor.counter  //'Measure_' + this.constructor.counter;
          
-		this._showDistances = true;
+		/* this._showDistances = true;
 		this._showCoordinates = false;
 		this._showArea = false;
 		this._closed = true;
@@ -60,46 +61,23 @@ export class Measure extends ctrlPolygon{
 		this._showCircle = false;
 		this._showHeight = false;
 		this._showEdges = true;
-		this._showAzimuth = false;
-
-		//this.sphereGeometry = new THREE.SphereGeometry(0.4, 10, 10);
+		this._showAzimuth = false; */
+ 
 		this.color = new THREE.Color(config.measure.lineColor)//new THREE.Color(0xff0000);
 
 		
-		this.sphereLabels = [];
+		this.markerLabels = [];
 		this.edgeLabels = [];
 		this.angleLabels = [];
 		this.coordinateLabels = [];
         this.area = {value:0,string:''}
+         
         
-        
-        
-        if(this.showArea){
-            this.areaLabel = this.createAreaLabel();
-            this.areaPlane = this.createAreaPlane(); 
-            this.add(this.areaPlane)
-            this.add(this.areaLabel)
-        }
-        
-        if(this.showCircle){ 
-            this.circleRadiusLabel = createCircleRadiusLabel();
-            this.circleRadiusLine = createCircleRadiusLine();
-            this.circleLine = createCircleLine();
-            this.circleCenter = createCircleCenter();
-            this.add(this.circleRadiusLabel);
-            this.add(this.circleRadiusLine);
-            this.add(this.circleLine);
-            this.add(this.circleCenter);
-        }
-        if(this.showAzimuth){
-            this.azimuth = createAzimuth();
-            this.add(this.azimuth.node);
+        if(this.closed/* this.showArea */){
+            this.areaLabel = this.createAreaLabel(); 
+            this.add(this.areaLabel) 
         }
         
-		
-        /* this.heightLabel = createHeightLabel();
-		this.add(this.heightEdge);
-		this.add(this.heightLabel); */
 		 
         //add:
         if(this.maxMarkers > 2 || this.faceDirection){
@@ -114,6 +92,7 @@ export class Measure extends ctrlPolygon{
         
         //addMarkers:
         this.initData(prop)
+        
 	}
  
  
@@ -122,181 +101,90 @@ export class Measure extends ctrlPolygon{
  
  
  
-	update() {
-		if (this.points.length === 0) {
-			return;
-		}else{ 
-            if(this.showCoordinates){
-                let point = this.points[0];
-                let position = point 
-                this.markers[0].position.copy(position);
-
-                { // coordinate labels
-                    let coordinateLabel = this.coordinateLabels[0];
-                    
-                    let lonlat = viewer.transform.lonlatToLocal.inverse(position.toArray())
-                    let EPSG4550 = viewer.transform.lonlatTo4550.forward(lonlat)
-                    let pos = [
-                        position.toArray(),
-                        lonlat,
-                        EPSG4550
-                    ] 
-                    //let msg = position.toArray().map(p => Utils.addCommas(p.toFixed(2))).join(" / ");
-                    let msg = pos.map(a=> 
-                         a.map(p => Utils.addCommas(p.toFixed(10))).join(", ") 
-                    ).join("<br>") 
-                    coordinateLabel.setText(msg);
-                    coordinateLabel.setPos(position)
-                    coordinateLabel.setVisible(true)//this.showCoordinates;
-                }
-                return;
-            }
-			 
+	update(ifUpdateMarkers) { 
+        super.update(ifUpdateMarkers)
+        
+        if(this.showCoordinates){
+            let point = this.points[0];
+            let position = point 
+            this.markers[0].position.copy(position);
 
-            let lastIndex = this.points.length - 1;
+            { // coordinate labels
+                let coordinateLabel = this.coordinateLabels[0];
+                
+                let lonlat = viewer.transform.lonlatToLocal.inverse(position.toArray())
+                let EPSG4550 = viewer.transform.lonlatTo4550.forward(lonlat)
+                let pos = [
+                    position.toArray(),
+                    lonlat,
+                    EPSG4550
+                ] 
+                //let msg = position.toArray().map(p => Utils.addCommas(p.toFixed(2))).join(" / ");
+                let msg = pos.map(a=> 
+                     a.map(p => Utils.addCommas(p.toFixed(10))).join(", ") 
+                ).join("<br>") 
+                coordinateLabel.setText(msg);
+                coordinateLabel.setPos(position)
+                coordinateLabel.setVisible(true)//this.showCoordinates;
+            }
+            return 
+        }
+         
+        let lastIndex = this.points.length - 1;
             
        
-            for (let i = 0; i <= lastIndex; i++) {
-                let index = i;
-                let nextIndex = (i + 1 > lastIndex) ? 0 : i + 1;
-                let previousIndex = (i === 0) ? lastIndex : i - 1;
+        for (let index = 0; index <= lastIndex; index++) {
+            
+            let nextIndex = (index + 1 > lastIndex) ? 0 : index + 1;
+            let previousIndex = (index === 0) ? lastIndex : index - 1;
 
-                let point = this.points[index];
-                let nextPoint = this.points[nextIndex];
-                let previousPoint = this.points[previousIndex];
+            let point = this.points[index];
+            let nextPoint = this.points[nextIndex];
+            let previousPoint = this.points[previousIndex];
 
+         
+         
+         
+            if(this.showDistances){ // edge labels
+                let edgeLabel = this.edgeLabels[index];
+
+                let center = new THREE.Vector3().add(point);
+                center.add(nextPoint);
+                center = center.multiplyScalar(0.5); 
+                edgeLabel.setPos(center) 
+                let distance = point.distanceTo(nextPoint);
                 
+                var text = viewer.unitConvert.convert(distance, 'distance', void 0, this.unitSystem, 0.1 , true)//distance要传0.1 这个factor
 
-                if(this.showEdges){ // edges
-                    let edge = this.edges[index];
-  
-                    this.updateLine(edge, point, nextPoint)
-                      
-                    edge.visible = index < lastIndex || this.closed;
-                    
-                }
-
-                if(this.showDistances){ // edge labels
-                    let edgeLabel = this.edgeLabels[i];
-
-                    let center = new THREE.Vector3().add(point);
-                    center.add(nextPoint);
-                    center = center.multiplyScalar(0.5); 
-                    edgeLabel.setPos(center) 
-                    let distance = point.distanceTo(nextPoint);
-                    
-                    var text = viewer.unitConvert.convert(distance, 'distance', void 0, this.unitSystem, 0.1 , true)//distance要传0.1 这个factor
- 
-                    /* let suffix = "m";
-                    let txtLength = Utils.addCommas(distance.toFixed(2));
-                    edgeLabel.setText(`${txtLength} ${suffix}`); */
-                    edgeLabel.setText(text)
-                    
-                    
-                    edgeLabel.shouldVisi = (index < lastIndex || this.closed && this.points.length > 2) && distance>0 
-                    
-                    
-                    /* this.closed || */ edgeLabel.setVisible(edgeLabel.shouldVisi)  
-                     
-                }
+                edgeLabel.setText(text)
+                 
+                edgeLabel.shouldVisi = (index < lastIndex || this.closed && this.points.length > 2) && distance>0 
                 
-                if(this.showAngles)
-                { // angle labels
-                    /* let angleLabel = this.angleLabels[i];
-                    let angle = this.getAngleBetweenLines(point, previousPoint, nextPoint);
-
-                    let dir = nextPoint.position.clone().sub(previousPoint.position);
-                    dir.multiplyScalar(0.5);
-                    dir = previousPoint.position.clone().add(dir).sub(point.position).normalize();
-
-                    let dist = Math.min(point.position.distanceTo(previousPoint.position), point.position.distanceTo(nextPoint.position));
-                    dist = dist / 9;
-
-                    let labelPos = point.position.clone().add(dir.multiplyScalar(dist));
-                    angleLabel.position.copy(labelPos);
-
-                    let msg = Utils.addCommas((angle * (180.0 / Math.PI)).toFixed(1)) + '\u00B0';
-                    angleLabel.setText(msg);
-
-                    angleLabel.visible = (index < lastIndex || this.closed) && this.points.length >= 3 && angle > 0;
-                 */
                 
-                }
+                /* this.closed || */ edgeLabel.setVisible(edgeLabel.shouldVisi)  
+                 
             }
             
-            if(this.showArea && this.point2dInfo){ // update area   
-                
-                this.updateAreaPlane()
-                
+        } 
+
+        
+        if(this.showArea && this.point2dInfo){ // update area 
+           /*  if(this.points.length>2){
+                this.area = {value:0};
+                this.areaLabel.setVisible(false)
+            }else{ */
                 let area = Math.abs(math.getArea(this.point2dInfo.points2d))//this.getArea();
-                 
-                this.areaLabel.setPos(this.center); 
-                
                 let msg = viewer.unitConvert.convert(area, 'area', void 0, this.unitSystem/* , 0.1 */ )
                 this.area = {value:area, string:msg}
                 
+                this.areaLabel.setPos(this.center);
                 this.areaLabel.setText(msg);
                 this.areaLabel.setVisible(true)
-            }
-
-            if(this.showCircle){ // update circle stuff
-                const circleRadiusLabel = this.circleRadiusLabel;
-                const circleRadiusLine = this.circleRadiusLine;
-                const circleLine = this.circleLine;
-                const circleCenter = this.circleCenter;
-
-                const circleOkay = this.points.length === 3;
-
-                circleRadiusLabel.visible = this.showCircle && circleOkay;
-                circleRadiusLine.visible = this.showCircle && circleOkay;
-                circleLine.visible = this.showCircle && circleOkay;
-                circleCenter.visible = this.showCircle && circleOkay;
-
-                if(circleOkay){
-
-                    const A = this.points[0];
-                    const B = this.points[1];
-                    const C = this.points[2];
-                    const AB = B.clone().sub(A);
-                    const AC = C.clone().sub(A);
-                    const N = AC.clone().cross(AB).normalize();
-
-                    const center = Potree.Utils.computeCircleCenter(A, B, C);
-                    const radius = center.distanceTo(A);
-
-
-                    const scale = radius / 20;
-                    circleCenter.position.copy(center);
-                    circleCenter.scale.set(scale, scale, scale);
-
-                    //circleRadiusLine.geometry.vertices[0].set(0, 0, 0);
-                    //circleRadiusLine.geometry.vertices[1].copy(B.clone().sub(center));
-
-                    circleRadiusLine.geometry.setPositions( [
-                        0, 0, 0,
-                        ...B.clone().sub(center).toArray()
-                    ] );
-
-                    circleRadiusLine.geometry.verticesNeedUpdate = true;
-                    circleRadiusLine.geometry.computeBoundingSphere();
-                    circleRadiusLine.position.copy(center);
-                    circleRadiusLine.computeLineDistances();
-
-                    const target = center.clone().add(N);
-                    circleLine.position.copy(center);
-                    circleLine.scale.set(radius, radius, radius);
-                    circleLine.lookAt(target);
-                    
-                    circleRadiusLabel.visible = true;
-                    circleRadiusLabel.position.copy(center.clone().add(B).multiplyScalar(0.5));
-                    circleRadiusLabel.setText(`${radius.toFixed(3)}`);
-
-                }
-            }
-
+            //}  
+        } 
              
-        }
-		viewer.mapViewer.emit('content_changed')  
+         
+		  
 	};
 
  
@@ -305,14 +193,11 @@ export class Measure extends ctrlPolygon{
 
 	addMarker (o={}) {
          
-        let sphere = new Sprite({mat:this.getSphereMaterial('default'), sizeInfo: sphereSizeInfo, name:"measure_point"} )
-        viewer.setObjectLayers(sphere, 'measure' )
-        sphere.renderOrder = 3 
-        sphere.sphereSelectStates = {}
-        
+        let marker = new Sprite({mat:this.getMarkerMaterial('default'), sizeInfo: markerSizeInfo, name:"measure_point"} )
+        viewer.setObjectLayers(marker, 'measure' )
+        marker.renderOrder = 3 
+        marker.markerSelectStates = {} 
         
-         
-        this.updateMarker(sphere, o.point)
         
         let edge
 		{ // edges 
@@ -334,7 +219,7 @@ export class Measure extends ctrlPolygon{
             
 		}
         
-        super.addMarker({point:o.point, marker:sphere,  edge})
+        super.addMarker({point:o.point, marker:marker,  edge})
         
         
         
@@ -376,9 +261,7 @@ export class Measure extends ctrlPolygon{
 			this.add(edgeLabel);
 		}
 
-		if(this.showAngles){ // angle labels
-			 
-		}
+		
 
 		if(this.showCoordinates){ // coordinate labels 
             let coordinateLabel = new Label({
@@ -398,13 +281,13 @@ export class Measure extends ctrlPolygon{
 		let event = {
 			type: 'marker_added',
 			measurement: this,
-			sphere: sphere
+			marker: marker
 		};
 		this.dispatchEvent(event);
 
 		//this.setMarker(this.points.length - 1, point);
         
-        return sphere;//add
+        return marker;//add
 	};
 
 
@@ -417,16 +300,17 @@ export class Measure extends ctrlPolygon{
 
 
     editStateChange(state){ //主要针对edgeLabels显示切换,编辑时显示
+         
         if(!state){
             this.editStateTimer = setTimeout(()=>{
                 if(!this.isEditing){
-                    viewer.dispatchEvent({type:"endMeasureMove"})
+                    this.dispatchEvent({type:'editStateChange',state:false})   
                     this.closed && this.edgeLabels.forEach(e=>e.setVisible(false) )
                 }
             },100)
         }else{
             if(!this.isEditing){
-                viewer.dispatchEvent({type:"measureMovePoint"})
+                this.dispatchEvent({type:'editStateChange',state:true})   
                 this.closed && this.edgeLabels.forEach(e=>e.setVisible(e.shouldVisi)  )
                 clearTimeout(this.editStateTimer)
             } 
@@ -440,25 +324,25 @@ export class Measure extends ctrlPolygon{
 
 
     
-    setMarkerSelected(sphere, state, hoverObject){
+    setMarkerSelected(marker, state, hoverObject){
         
-        //console.warn(sphere.id , state, hoverObject)
+        //console.warn(marker.id , state, hoverObject)
         
         
-        sphere.sphereSelectStates[hoverObject] = state
+        marker.markerSelectStates[hoverObject] = state
         let absoluteState = false
-        for(var i in sphere.sphereSelectStates){
-            if(sphere.sphereSelectStates[i]){
+        for(var i in marker.markerSelectStates){
+            if(marker.markerSelectStates[i]){
                 absoluteState = true; break;
             }
         }
         if(absoluteState){
-            sphere.material = this.getSphereMaterial('select')
+            marker.material = this.getMarkerMaterial('select')
         }else{
-            sphere.material = this.getSphereMaterial('default')
+            marker.material = this.getMarkerMaterial('default')
         }
         
-        sphere.selected = absoluteState
+        marker.selected = absoluteState
         
         viewer.mapViewer.emit('content_changed') 
     }
@@ -507,17 +391,18 @@ export class Measure extends ctrlPolygon{
         viewer.mapViewer.emit('content_changed')
     }
     
-	removeMarker(index){
+	removeMarker(index ){  
         super.removeMarker(index)
+         
         this.coordinateLabels.splice(index, 1);
+         
+        let edgeIndex = index//(index === 0) ? 0 : (index - 1);
         if(this.edgeLabels[edgeIndex]){ 
-            this.edgeLabels[edgeIndex].parent.remove(this.edgeLabels[edgeIndex])
+            this.edgeLabels[edgeIndex].dispose() 
             this.edgeLabels.splice(edgeIndex, 1);
         }
-        if(this.angleLabels[index]){
-            this.angleLabels[index].remove()
-            this.angleLabels.splice(index, 1);
-        }
+         
+        this.update(); 
         this.dispatchEvent({type: 'marker_removed', measurement: this});
     }
     
@@ -535,9 +420,8 @@ export class Measure extends ctrlPolygon{
     dispose(){//add
         var labels = this.edgeLabels.concat(this.coordinateLabels)
         this.areaLabel && labels.push(this.areaLabel)
-        labels.forEach(e=>e.remove())
-    
-        this.parent.remove(this)
+        labels.forEach(e=>e.dispose())
+        super.dispose()
     }
     
      
@@ -655,16 +539,17 @@ export class Measure extends ctrlPolygon{
             viewer.focusOnObject(this, 'measure')
         })
         viewer.setObjectLayers(areaLabel, 'measure' )
-      
+        areaLabel.visible = false
+        
         return areaLabel;
         
         
     }
 
     
-    getSphereMaterial(type) {
-        if(!sphereMats){
-            sphereMats = {  
+    getMarkerMaterial(type) {
+        if(!markerMats){
+            markerMats = {  
                 default:    new DepthBasicMaterial({  
                     transparent: !0,
                     opacity: 1,
@@ -678,9 +563,9 @@ export class Measure extends ctrlPolygon{
                      
                 }),   
             }
-            Measure.sphereMats = sphereMats
+            Measure.markerMats = markerMats
         }
-        return sphereMats[type]
+        return markerMats[type]
         
     }
     
@@ -737,17 +622,12 @@ export class Measure extends ctrlPolygon{
         return super.createAreaPlane(planeMats.default)
     }
     
-    updateLine(line, p1,p2){
-       
-        LineDraw.moveFatLine(line,[
-            ...p1.toArray(), ...p2.toArray(),  
-        ])
-    }
+     
 	raycast (raycaster, intersects) {
 		for (let i = 0; i < this.points.length; i++) {
-			let sphere = this.markers[i];
+			let marker = this.markers[i];
 
-			sphere.raycast(raycaster, intersects);
+			marker.raycast(raycaster, intersects);
 		}
 
 		// recalculate distances because they are not necessarely correct
@@ -840,7 +720,7 @@ export class Measure extends ctrlPolygon{
 
 
     setUnitSystem(unitSystem){
-        console.log(this.name +':' +this.unitSystem)
+        //console.log(this.name +':' +this.unitSystem)
         if(unitSystem != this.unitSystem){
             if(unitSystem == "metric"){
                 
@@ -1067,7 +947,7 @@ function createCircleLine(){
 }
 
 function createCircleCenter(){
-	const sg = new THREE.SphereGeometry(1, 32, 32);
+	const sg = new THREE.markerGeometry(1, 32, 32);
 	const sm = new THREE.MeshNormalMaterial();
 	
 	const circleCenter = new THREE.Mesh(sg, sm);
@@ -1147,7 +1027,7 @@ function createAzimuth(){
 		node: null,
 	};
 
-	const sg = new THREE.SphereGeometry(1, 32, 32);
+	const sg = new THREE.markerGeometry(1, 32, 32);
 	const sm = new THREE.MeshNormalMaterial();
 
 	{

+ 53 - 23
src/utils/MeasuringTool.js

@@ -178,6 +178,23 @@ export class MeasuringTool extends EventDispatcher{
 		e.scene.addEventListener('measurement_removed', this.onRemove);
 	}
 
+
+    editStateChange(e){
+        //console.log("editStateChange" , e.state)
+        let state = e.state
+        if(!state){
+            state = viewer.scene.measurements.some(e=>e.isEditing)
+        }
+        
+        if(state){
+            viewer.dispatchEvent({type:"measureMovePoint"})
+        }else{
+            viewer.dispatchEvent({type:"endMeasureMove"})
+        }
+        
+    }
+
+
 	startInsertion (args = {}, callback, cancelFun) {
         
         
@@ -222,40 +239,31 @@ export class MeasuringTool extends EventDispatcher{
          
         
         measure.editStateChange(true)
+        measure.addEventListener('editStateChange', this.editStateChange.bind(this))
         let timer;
 
 
         let continueDrag = (marker)=>{
             timer = setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag
                 this.viewer.inputHandler.startDragging(marker,
-                    {endDragFun} 
+                    {endDragFun, notPressMouse:true} 
                 ); 
             },1)  
         }
 
-		let endDragFun = (e) => {
-            
-                
-            
+		let endDragFun = (e) => {  
 			if (e.button == THREE.MOUSE.LEFT /* e.drag.mouse == MOUSE.LEFT */) {
 				if (measure.points.length >= measure.maxMarkers) {
-                    end({complete:true});
+                    end({finish:true});
 				}else{
                     if(measure.points.length == 1){//点击第一下,恢复可见
-                        measure.markers[0].visible = true;
-                        /* if(e.drag.hoverViewport.name == 'mapViewport'){//如果在地图点击,直接使用地图上的
-                            let pos2d = e.drag.hoverViewport.end;
-                            let newPos = new THREE.Vector3(pos2d.x,pos2d.y,-1).unproject(e.drag.hoverViewport.camera); //z:-1朝外   
-                            
-                        } */
-                        
-                        
+                        measure.markers[0].visible = true; 
                     }
                     
-                    var marker = measure.addMarker(measure.points[measure.points.length - 1].clone())
+                    var marker = measure.addMarker({point:measure.points[measure.points.length - 1].clone()})
                      
                     if(args.isRect && measure.markers.length == 3){
-                        measure.addMarker(measure.points[0].clone())
+                        measure.addMarker({point:measure.points[0].clone()})
                     }
                     measure.editStateChange(true) //重新激活reticule状态
                     continueDrag(marker) 
@@ -269,10 +277,26 @@ export class MeasuringTool extends EventDispatcher{
 		};
 
 		let end = (e={}) => {//确定、结束
+            if(!measure.isNew)return
             if(args.minMarkers != void 0){
-                if(!e.complete && measure.markers.length<=args.minMarkers){//右键  当个数不够时取消 
-                    this.viewer.scene.removeMeasurement(measure)
-                    cancelFun && cancelFun()
+                if(!e.finish && measure.markers.length<=args.minMarkers){//右键  当个数不够时取消
+                    //this.viewer.scene.removeMeasurement(measure)
+                    //cancelFun && cancelFun()
+                    //重新开始画
+                    let pointCount = measure.points.length-1
+                    for(let i=0;i<pointCount;i++){
+                        measure.removeMarker(i)
+                    }  
+                    if(measure.showArea){
+                        measure.point2dInfo = null
+                        measure.area = {value:0};
+                        measure.areaLabel && measure.areaLabel.setVisible(false)
+                    }
+                    
+                    
+                    measure.markers[0].visible = false
+                    continueDrag(measure.markers[0])
+                    measure.editStateChange(true)
                     return
                     
                     /* if(!Potree.settings.isOfficial) this.viewer.scene.removeMeasurement(measure)
@@ -283,7 +307,7 @@ export class MeasuringTool extends EventDispatcher{
                     } */
                 } 
             }
-            if (!e.complete && measure.markers.length > 3) {
+            if (!e.finish && measure.markers.length > 3) {
 				measure.removeMarker(measure.points.length - 1); 
 			}
             measure.isNew = false
@@ -299,6 +323,7 @@ export class MeasuringTool extends EventDispatcher{
 
         
         let Exit = (e)=>{//模拟右键点击 
+            console.log('Exit')
             if(this.viewer.inputHandler.drag){//还未触发drop的话
                 this.viewer.inputHandler.drag.object.dispatchEvent({
                     type: 'drop',
@@ -309,7 +334,7 @@ export class MeasuringTool extends EventDispatcher{
                 });
                 this.viewer.inputHandler.drag = null 
             }else{
-                end()  //未结束时添加新的measure时会触发
+                end({finish:true})  //未结束时添加新的measure时会触发
             }
         }
         this.viewer.addEventListener('cancel_insertions', Exit);
@@ -326,8 +351,8 @@ export class MeasuringTool extends EventDispatcher{
         }
 		  
           
-        var marker = measure.addMarker(new THREE.Vector3(0, 0, 0))
-        this.viewer.inputHandler.startDragging(marker , {endDragFun}); 
+        var marker = measure.addMarker({point:new THREE.Vector3(0, 0, 0)})
+        this.viewer.inputHandler.startDragging(marker , {endDragFun, notPressMouse:true} ); //notPressMouse代表不是通过按下鼠标来拖拽
              
         if(measure.maxMarkers > 1){
             marker.visible = false
@@ -351,6 +376,11 @@ export class MeasuringTool extends EventDispatcher{
     
     
 	update(){
+        return;
+        
+        
+        
+        
 		let camera = this.viewer.scene.getActiveCamera();
 		let domElement = this.renderer.domElement;
 		let measurements = this.viewer.scene.measurements;

+ 23 - 2
src/utils/math.js

@@ -12,7 +12,21 @@ var math = {
         
         
     },
-    
+    convertQuaternion: {
+        ZupToYup: function(e){//navvis -> 4dkk  //不同于convertVisionQuaternion
+            let rotation = new THREE.Euler(-Math.PI/2,0,0)   
+            let quaternion = new THREE.Quaternion().setFromEuler(rotation)
+            return e.clone().premultiply(quaternion)
+            //return new THREE.Quaternion(e.x,e.z,-e.y,e.w).multiply((new THREE.Quaternion).setFromAxisAngle(new THREE.Vector3(1,0,0), THREE.Math.degToRad(90)))
+        },
+        YupToZup: function(e){//4dkk -> navvis
+            let rotation = new THREE.Euler(Math.PI/2,0,0)
+            let quaternion = new THREE.Quaternion().setFromEuler(rotation)
+            return e.clone().premultiply(quaternion)
+        },
+        
+        
+    },
 	 
     convertVisionQuaternion: function(e) {
         return new THREE.Quaternion(e.x,e.z,-e.y,e.w).multiply((new THREE.Quaternion).setFromAxisAngle(new THREE.Vector3(0,1,0), THREE.Math.degToRad(90)))
@@ -29,7 +43,14 @@ var math = {
     getVec2Cos :  function(dir1,dir2){ 
         return dir1.dot(dir2) / dir1.length() / dir2.length()    
     },
-     
+    getAngle:function(vec1, vec2, axis){//带方向的角度 vector3
+        var angle = vec1.angleTo(vec2)
+        var axis_ = vec1.clone().cross(vec2);
+        if(axis_[axis] < 0){
+            angle *= -1
+        }
+        return angle
+    }, 
     
     closeTo : function(a,b, num){ 
         if(num != void 0)return Math.abs(a-b) < num;

+ 18 - 31
src/viewer/EDLRenderer.js

@@ -100,29 +100,7 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 
 		renderer.setRenderTarget(oldTarget);
 	}
-
-	clear(params={}){
-		//this.initEDL();
-		const viewer = this.viewer;
-
-		const {renderer, background} = viewer;
-      
-		if(background === "skybox"){
-			renderer.setClearColor(0x000000, 0);
-		} else if (background === 'gradient') {
-			renderer.setClearColor(0x000000, 0);
-		} else if (background === 'black') {
-			renderer.setClearColor(0x000000, 1);
-		} else if (background === 'white') {
-			renderer.setClearColor(0xFFFFFF, 1);
-		} else {
-			renderer.setClearColor(0x000000, 0);
-		}
-		
-		params.target || renderer.clear();
-   
-		this.clearTargets(params);
-	}
+ 
 
 	renderShadowMap(visiblePointClouds, camera, lights){
 
@@ -199,9 +177,10 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 
 
         viewer.renderer.setRenderTarget(params.target || null);
-        
-        {//绘制背景
-            if(viewer.background === "skybox"){
+        let background = params.background || viewer.background;
+        let backgroundOpacity = params.backgroundOpacity == void 0 ? viewer.backgroundOpacity : params.backgroundOpacity//如果想完全透明,只需要backgroundOpacity为0
+        if(backgroundOpacity != 0){//绘制背景
+            if(background === "skybox"){
                 viewer.skybox.camera.rotation.copy(viewer.scene.cameraP.rotation);
                 viewer.skybox.camera.fov = viewer.scene.cameraP.fov;
                 viewer.skybox.camera.aspect = viewer.scene.cameraP.aspect;
@@ -210,16 +189,24 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
                 viewer.skybox.parent.updateMatrixWorld();
 
                 viewer.skybox.camera.updateProjectionMatrix();
-            }else if (viewer.background === 'gradient') { 
-           
-            }         
-            viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
+                
+                viewer.renderer.render(viewer.skybox.scene, viewer.skybox.camera);
+            }else if(background === 'gradient'){ 
+                viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg);
+                viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
+            }else if(background === 'overlayColor'){//在不clear的前提下加一层背景色 
+                viewer.scene.bg2.material.color.copy(params.backgroundColor)
+                viewer.scene.bg2.material.opacity = params.backgroundOpacity
+                viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg2);
+                viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
+            }  
+            
         }
         
         //skybox 
         viewer.setCameraLayers(camera, ['skybox'])
         viewer.renderer.render(viewer.scene.scene, camera);
-        
+         
         
         //pointcloud
         viewer.setCameraLayers(camera, ['pointcloud'])

+ 46 - 5
src/viewer/Scene.js

@@ -19,8 +19,10 @@ 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, 1000*1000);
-		this.cameraO = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 1000*1000);
+		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.limitFar = true//add
+        
 		this.cameraVR = new THREE.PerspectiveCamera();
 		this.cameraBG = new THREE.Camera();
 		this.cameraScreenSpace = new THREE.OrthographicCamera(-1, 1, 1, -1, 0.1, 10);
@@ -55,7 +57,7 @@ export class Scene extends EventDispatcher{
         this.axisArrow = new Axis();
         this.scene.add(this.axisArrow)
         this.axisArrow.visible = false
-        
+        viewer.setObjectLayers(this.axisArrow, 'sceneObjects')
         
         
         
@@ -395,8 +397,20 @@ export class Scene extends EventDispatcher{
 		this.directionalLight.lookAt( new THREE.Vector3(0, 0, 0));
 		this.scenePointCloud.add( this.directionalLight );
 		
-		let light = new THREE.AmbientLight( 0x555555 ); // soft white light
+		let light = new THREE.AmbientLight( 0x555555 ); // soft white light 
 		this.scenePointCloud.add( light );
+        
+        
+        
+        //add:
+        let light2 = new THREE.AmbientLight( 16777215, 0.8 ); //给空间模型的box 
+        viewer.setObjectLayers(light2, 'sceneObjects')
+        this.scene.add(light2)
+        let light3 = new THREE.DirectionalLight( 16777215, 0.1); //给空间模型的box 
+        light3.position.set( 10, 10, 10 );
+		light3.lookAt( new THREE.Vector3(0, 0, 0));
+        viewer.setObjectLayers(light3, 'sceneObjects')
+        this.scene.add(light3)
 
 		{ // background
 			let texture = Utils.createBackgroundTexture(512, 512);
@@ -415,9 +429,26 @@ export class Scene extends EventDispatcher{
 			//this.sceneBG.add(bg);
             this.scene.add(bg)
             bg.layers.set(Potree.config.renderLayers.bg)
-            this.cameraBG.layers.set(Potree.config.renderLayers.bg);
+            
 		}
 
+        { // background color
+			  
+			let bg2 = new THREE.Mesh(
+				new THREE.PlaneBufferGeometry(2, 2, 1),
+				new THREE.MeshBasicMaterial({
+					transparent : true
+				})
+			);
+			bg2.material.depthTest = false;
+			bg2.material.depthWrite = false;
+            bg2.name = 'bg2' 
+            this.scene.add(bg2)
+            bg2.layers.set(Potree.config.renderLayers.bg2) 
+            this.bg2 = bg2
+		}
+
+
 		// { // lights
 		// 	{
 		// 		let light = new THREE.DirectionalLight(0xffffff);
@@ -442,6 +473,16 @@ export class Scene extends EventDispatcher{
 		// }
 	}
 	
+    /* switchBg(type){//add
+        let bg,;
+        if(type == 'gradient'){
+            bg
+        }else if(type == 'overlayColor'){
+            
+        }
+    } */
+    
+    
 	addAnnotation(position, args = {}){		
 		if(position instanceof Array){
 			args.position = new THREE.Vector3().fromArray(position);

+ 19 - 2
src/viewer/sidebar.html

@@ -270,7 +270,8 @@ Thanks to all the companies and institutions funding Potree:
                 <span>平移</span>
                 <div><button>-x</button><button>+x</button><span class='gap'></span> <button>-y</button><button>+y</button> <span class='gap'> <button>-z</button><button>+z</button></div>
             </li>
-             
+            <button name='rotTool'></button> 
+            <button name='moveTool'></button> 
         </div>
 
         <h3 class="accordion-header ui-widget"><span>点云下载</span></h3>
@@ -282,7 +283,23 @@ Thanks to all the companies and institutions funding Potree:
 
 
 
-
+        <h3 class="accordion-header ui-widget"><span>空间模型</span></h3>
+        <div id="siteModel"  class="accordion-content ui-widget pv-menu-list">
+            <button name='start'>开始</button>
+            <button name='exit'>退出</button>
+            <li name='build'>
+                <button name='building'>创建建筑</button>
+                <button name='floor'>添加楼层</button>
+                <button name='room'>创建房间</button>
+            </li> 
+            <li name='edit'>
+                <button name='removeLastMarker'>去除最后一个点</button>
+                <button name='selectFloor'>选中第一个楼层</button>
+                <button name='selectBuilding'>选中第一个建筑</button>
+                <button name='selectRoom'>选中第一个房间</button>
+                
+            </li> 
+        </div>
 
 
 

+ 23 - 1
src/viewer/sidebar.js

@@ -60,6 +60,7 @@ export class Sidebar{
         //add
 		this.initAlignment();
         this.initClipModel();
+        this.initSiteModel()
 		$('#potree_version_number').html(Potree.version.major + "." + Potree.version.minor + Potree.version.suffix);
 	}
 
@@ -128,7 +129,28 @@ export class Sidebar{
         buttons.eq(1).on('click', Clip.download.bind(Clip))
         buttons.eq(2).on('click', Clip.leave.bind(Clip))
     }
-    
+    initSiteModel(){
+        let SiteModel = viewer.modules.SiteModel
+        var pannel = $('#siteModel');
+        pannel.find('button[name="start"] ').on('click', SiteModel.enter.bind(SiteModel))
+        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])
+        } )
+        pannel.find('button[name="room"] ').on('click', ()=>{
+            SiteModel.startInsertion('room', SiteModel.buildings[0].buildChildren[0])
+        })
+        pannel.find('button[name="selectBuilding"] ').on('click', ()=>{
+            SiteModel.selectEntity(SiteModel.buildings[0] )
+        } )
+        pannel.find('button[name="selectFloor"] ').on('click', ()=>{
+            SiteModel.selectEntity(SiteModel.buildings[0].buildChildren[0])
+        } )
+        pannel.find('button[name="selectRoom"] ').on('click', ()=>{
+            SiteModel.selectEntity(SiteModel.buildings[0].buildChildren[0].buildChildren[0])
+        } )
+    }
     
 
 	initToolbar(){

+ 95 - 49
src/viewer/viewer.js

@@ -40,6 +40,10 @@ import Common from '../utils/Common'
 
 import {Clip} from '../modules/clipModel/Clip'
 import {Alignment} from "../modules/datasetAlignment/Alignment.js";
+import {SiteModel} from "../modules/siteModel/SiteModel.js";
+
+
+
 
 import Magnifier from "../utils/Magnifier.js";
 import Reticule from "../navigation/Reticule.js";
@@ -63,7 +67,9 @@ export class Viewer extends ViewerBase{
         this.modules = { //add
             Clip : Clip,
             Alignment : Alignment,
-            RouteGuider : new RouteGuider
+            SiteModel : SiteModel,
+            RouteGuider : new RouteGuider,
+            
         }
         
         
@@ -71,8 +77,7 @@ export class Viewer extends ViewerBase{
         //add -------- 
         this.navigateMode = 'free' // 'panorama'; 'free'自由模式是只显示点云或者未进入到漫游点, 
         this.isEdit = true
-        this.waitQueue = [] 
-        CursorDeal.attachToViewer(this)//ADD
+        this.waitQueue = []  
         this.unitConvert = new UoMService();
         mapArea = mapArea_
 		//-------------
@@ -323,6 +328,10 @@ export class Viewer extends ViewerBase{
                 
                 
                 this.mapViewer = new MapViewer(mapArea/* $('#mapGaode')[0] */)
+                CursorDeal.init(this)//ADD
+                
+                this.modules.SiteModel.init()
+                
                 //-----------
                 
                 
@@ -416,7 +425,26 @@ export class Viewer extends ViewerBase{
                 }
             })
         }
-        
+        {
+            
+            let cameraFar = Potree.settings.cameraFar
+            Object.defineProperty(Potree.settings , "cameraFar",{ 
+                get: function() {
+                    return cameraFar
+                },
+                set: (far)=>{
+                    if(far != cameraFar){
+                        if(Potree.settings.displayMode != 'showPanos'){
+                            this.mainViewport.camera.far = far;
+                            this.mainViewport.camera.updateProjectionMatrix()
+                        }
+                    }
+                }
+            })
+            
+            
+            
+        }
         
         
 	}
@@ -565,6 +593,7 @@ export class Viewer extends ViewerBase{
 		}
 
 		this.background = bg;
+        this.backgroundOpacity = 1//add
 		this.dispatchEvent({'type': 'background_changed', 'viewer': this});
 	}
 
@@ -1335,7 +1364,7 @@ export class Viewer extends ViewerBase{
 			elButtons.append(imgMenuToggle);
 			elButtons.append(imgMapToggle);
 
-
+            /*
 			VRButton.createButton(this.renderer).then(vrButton => {
 
 				if(vrButton == null){
@@ -1369,10 +1398,10 @@ export class Viewer extends ViewerBase{
 					this.dispatchEvent({type: "vr_end"});
 				});
 			});
-
-			/* this.mapView = new MapView(this);
+  
+            this.mapView = new MapView(this);
 			this.mapView.init(); */
-
+ 
 			i18n.init({
 				lng: 'en',
 				resGetPath: Potree.resourcePath + '/lang/__lng__/__ns__.json',
@@ -2004,13 +2033,7 @@ export class Viewer extends ViewerBase{
         //改:不根据点云修改视野near far
         var near = camera.near, far = camera.far
         
-        if(Potree.settings.displayMode == 'showPanos'){
-            camera.near = 0.1; 
-            camera.far = viewer.farWhenShowPano 
-        }else if(Potree.settings.limitFar){
-            camera.near = 0.1;
-            camera.far = Potree.settings.cameraFar; 
-        }else if(result.lowestSpacing !== Infinity){
+        if(!camera.limitFar && result.lowestSpacing !== Infinity){
             
             let near = result.lowestSpacing * 10.0;
             let far = -this.getBoundingBox().applyMatrix4(camera.matrixWorldInverse).min.z;
@@ -2026,16 +2049,15 @@ export class Viewer extends ViewerBase{
             
             camera.near = near;
             camera.far = far;
-        }else{
-             
-        } 
+        }  
 
         if(this.scene.cameraMode == CameraMode.ORTHOGRAPHIC) {//???
             camera.near = -camera.far;
         }
         if(near != camera.near || far != camera.far){
             camera.updateProjectionMatrix()
-        }
+        }  
+         
         //注:pointcloud.visibleNodes会随着near far自动更新
     }
 
@@ -2237,6 +2259,33 @@ export class Viewer extends ViewerBase{
 
 	}
 
+    clear(params={}){
+        let background = params.background || this.background;
+        let backgroundOpacity = params.backgroundOpacity == void 0 ? this.backgroundOpacity : params.backgroundOpacity//如果想完全透明,只需要backgroundOpacity为0
+		let renderer = this.renderer
+        //let gl = renderer.getContext()
+         
+        if(background instanceof THREE.Color){ //add
+            renderer.setClearColor(background, backgroundOpacity);
+        }else if(background === "skybox"){
+			renderer.setClearColor(0x000000, 0);
+		} else if (background === 'gradient') {
+			renderer.setClearColor(0x000000, 0);
+		} else if (background === 'black') {
+			renderer.setClearColor(0x000000, 1);
+		} else if (background === 'white') {
+			renderer.setClearColor(0xFFFFFF, 1);
+		} else {
+			renderer.setClearColor(0x000000, 0);
+		}
+		
+		params.target || renderer.clear();
+   
+		 
+	}
+
+
+
 	renderDefault(params_={}){
 		let pRenderer = this.getPRenderer();
         let renderSize
@@ -2251,7 +2300,7 @@ export class Viewer extends ViewerBase{
            
         
         var viewports = params_.viewports || this.viewports
-        let needSResize = viewports.length > 1 || params_.resize  
+        let needSResize = viewports.filter(e=>e.active).length > 1 || params_.resize  
         
         
         
@@ -2259,6 +2308,7 @@ export class Viewer extends ViewerBase{
             let params = $.extend({},params_);
             //if(!params.target){
                 params.camera = params.camera || view.camera;
+                params.extraEnableLayers = view.extraEnableLayers
             //}
             
             if(!view.active)return
@@ -2296,13 +2346,18 @@ export class Viewer extends ViewerBase{
             
             //needSResize && this.emitResizeMsg({resolution: params_.target ? new THREE.Vector2(width,height) : view.resolution2, left:view.left,  bottom:view.bottom })//resize everything  such as lines  targets 
             
+            
+            
             viewer.dispatchEvent({type: "render.begin",  viewer: viewer, viewport:view, params });
             
             if(view.render){
-               view.render({target: params_.target, renderer:this.renderer, renderOverlay: this.renderOverlay.bind(this) })
+                view.render({
+                    target: params_.target, renderer:this.renderer,   clear:this.clear.bind(this),
+                    renderOverlay: this.renderOverlay.bind(this), force:!view.noPointcloud //如果要渲染点云,必须也一直渲染地图,否则地图会被覆盖(点云目前未能获取是否改变,也可能有其他动态物体,所以还是一直渲染的好)
+                })
             } 
             
-            
+             
             
             
             if(!view.noPointcloud ){
@@ -2310,38 +2365,29 @@ export class Viewer extends ViewerBase{
                 //if(!params.target){ 
                     params.width = width; params.height = height;
                 //}
+                if(view.render){
+                    params.noBG = true
+                }
                 
                 
                 
-                this.scene.pointclouds.forEach(e=>{
-                    if(view.differentPointMat){
-                        if(view.name == "MainView"){ 
-                            e.material.activeAttributeName = viewer.matBeforeSplitscreen.colorType 
-                            e.material.color.copy(viewer.matBeforeSplitscreen.color)
-                            e.material.useFilterByNormal = false
-                            e.material.opacity = viewer.matBeforeSplitscreen.opacity 
-                        }else{ 
-                            e.material.activeAttributeName = "color"
-                            e.material.color.set(e.color)
-                            e.material.useFilterByNormal = true
-                            e.material.opacity = 0.09
-                        }
-                    }                 
-                })
-                
+                view.beforeRender && view.beforeRender(view)
                 
                 this.updateViewPointcloud(params.camera, new THREE.Vector2(params.width,params.height), true)
-                pRenderer.clear(params); 
+                
+                params.background = view.background
+                params.backgroundColor = view.backgroundColor
+                params.backgroundOpacity = view.backgroundOpacity
+                view.render || this.clear(params) 
+                pRenderer.clearTargets(params);  
                 pRenderer.render(params);
                 
                 
-                 
+                this.renderOverlay(params) 
             } 
             
              
-            if(!view.render){
-                this.renderOverlay(params)
-            }
+             
             this.dispatchEvent({type: "render.end",  viewer: this, viewport:view  });
         })
         
@@ -2358,7 +2404,7 @@ export class Viewer extends ViewerBase{
         
         
         if(!params.magnifier){//为什么要在点云之后渲染,否则透明失效 、 会被点云覆盖 
-            this.setCameraLayers(camera, ['marker','reticule','route']) //透明贴图层 skybox 、reticule marker 不能遮住测量线
+            this.setCameraLayers(camera, ['sceneObjects','marker','reticule','route'], params.extraEnableLayers) //透明贴图层 skybox 、reticule marker 不能遮住测量线
             this.renderer.render(this.scene.scene, camera); 
         } 
         this.dispatchEvent({type: "render.pass.scene", viewer: viewer});
@@ -2391,9 +2437,9 @@ export class Viewer extends ViewerBase{
     
     
     
-    setCameraLayers(camera, enableLayers){//add
-        camera.layers.disableAll()
-        enableLayers.forEach(e=>{
+    setCameraLayers(camera, enableLayers, extraEnableLayers=[]){//add
+        camera.layers.disableAll() 
+        enableLayers.concat(extraEnableLayers).forEach(e=>{
             let layer = Potree.config.renderLayers[e]
             if(layer == void 0){
                 console.error('setCameraLayer没找到layer!');
@@ -2879,8 +2925,8 @@ export class Viewer extends ViewerBase{
 	};
 
     updateModelBound(){
-        this.bound = Utils.computePointcloudsBound(this.scene.pointclouds)
-             
+        this.bound = Utils.computePointcloudsBound(this.scene.pointclouds) 
+        viewer.farWhenShowPano = this.bound.boundSize.length() * 2//全景漫游时要能看到整个skybox
     }
     
     waitForLoad(object, isLoadedCallback){//等待加载时显示loading。主要是贴图