xzw пре 3 година
родитељ
комит
6f438f5cff
43 измењених фајлова са 3533 додато и 1724 уклоњено
  1. 2 150
      examples/4dkk.html
  2. 8 0
      gulpfile.js
  3. 5 3
      libs/three.js/build/three.module.js
  4. 3 41
      note.txt
  5. 1 1
      src/Enum.js
  6. 11 1
      src/EventDispatcher.js
  7. 19 4
      src/PointCloudOctree.js
  8. 2 3
      src/Potree.js
  9. 42 80
      src/PotreeRenderer.js
  10. 2 2
      src/Potree_update_visibility.js
  11. 9 5
      src/TextSprite.js
  12. 121 5
      src/defines.js
  13. 14 10
      src/materials/PointCloudMaterial.js
  14. 3 3
      src/materials/shaders/pointcloud.fs
  15. 38 13
      src/materials/shaders/pointcloud.vs
  16. 644 280
      src/modules/Images360/Images360.js
  17. 35 28
      src/modules/Images360/ModelTextureMaterial.js
  18. 279 23
      src/modules/Images360/Panorama2.js
  19. 66 54
      src/navigation/FirstPersonControls.js
  20. 44 28
      src/navigation/InputHandler.js
  21. 20 8
      src/navigation/Reticule.js
  22. 98 5
      src/settings.js
  23. 20 1
      src/utils.js
  24. 101 0
      src/utils/Common.js
  25. 1 1
      src/utils/CursorDeal.js
  26. 274 26
      src/utils/DrawUtil.js
  27. 5 4
      src/utils/Magnifier.js
  28. 1130 643
      src/utils/Measure.js
  29. 156 169
      src/utils/MeasuringTool.js
  30. 57 42
      src/utils/math.js
  31. 2 2
      src/viewer/Axis.js
  32. 17 18
      src/viewer/EDLRenderer.js
  33. 25 11
      src/viewer/HQSplatRenderer.js
  34. 13 9
      src/viewer/LoadProject.js
  35. 2 5
      src/viewer/PotreeRenderer.js
  36. 1 1
      src/viewer/PropertyPanels/AreaPanel.js
  37. 2 2
      src/viewer/PropertyPanels/PropertiesPanel.js
  38. 15 2
      src/viewer/SaveProject.js
  39. 3 2
      src/viewer/View.js
  40. 3 3
      src/viewer/map.js
  41. 69 3
      src/viewer/potree.css
  42. 91 11
      src/viewer/sidebar.js
  43. 80 22
      src/viewer/viewer.js

+ 2 - 150
examples/4dkk.html

@@ -41,11 +41,7 @@
 	<script type="module">
 
 	import * as THREE from "../libs/three.js/build/three.module.js";
-    import {Alignment} from "../src/modules/datasetAlignment/Alignment.js";
-    import {Utils} from "../src/utils.js"
-   
-    
-    
+     
     
         var number = window.location.href.substring(window.location.href.indexOf("=") + 1);
         if (number.indexOf("&") != -1) {
@@ -56,153 +52,9 @@
         }
         
         Potree.settings.number = number || 't-o5YMR13'// 't-iksBApb'
-         
-        
-        
-		window.viewer = new Potree.Viewer(document.getElementById("potree_render_area"));
-		
-		viewer.setEDLEnabled(true);
-		viewer.setFOV(60);
-		viewer.setPointBudget(2_000_000);
-		viewer.loadSettingsFromURL();
-		 
-		viewer.loadGUI(() => {
-			viewer.setLanguage('en');
-			$("#menu_appearance").next().show();
-			viewer.toggleSidebar();
-		});
-
+        Potree.start(document.getElementById("potree_render_area"), number);
         
-        var datasetPath = `https://testlaser.4dkankan.com/indoor/${number}/api/datasets`
-        Potree.loadDatasets(datasetPath,  (data)=>{
-         
-            var datasetLength = data.length 
-            var loaded = 0
-            var loadDone = function(){
-                 //var url =   "../data/"+number+"/filter.json"
-                var url = `https://testlaser.4dkankan.com/indoor/${number}/api/images/filter?hidden=false&lat=22.3666054305652&lon=113.59566752095002&radius=200000&site_model_entity=`
-                
-                
-                var {boundSize, center} = Utils.computePointcloudsBound(viewer.scene.pointclouds)
-                
-                viewer.bound = {boundSize, center}
-                
-                Potree.Images360Loader.load2(url, viewer, {boundSize, center}).then( images => {
-                    viewer.scene.add360Images(images);
-                });
-                
-                 
-                viewer.scene.view.setView(//position, target
-                    center.clone().add(new THREE.Vector3(10,10,10)), 
-                    center
-                )
-            
-            }
-            
-            
-            data.forEach((dataset,index)=>{
-                var name = dataset.name 
-                var locationLonLat = dataset.location.slice(0,2)
-                
-                
-                if(!viewer.transform){
-                
-                    proj4.defs("NAVVIS:TMERC", "+proj=tmerc +ellps=WGS84 +lon_0=" + locationLonLat[0].toPrecision(15) + " +lat_0=" + locationLonLat[1].toPrecision(15));
-                    proj4.defs("WGS84", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs");
-                    //proj4.defs("pointcloud", viewer.getProjection()); //不用从cloud里拿了
-                
-                    let transform1 = proj4("WGS84", "NAVVIS:TMERC"); //这个ok  TMERC是展开的平面投影
-                    let transform2 = proj4("+proj=tmerc +lat_0=0 +lon_0=123 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs;");
-                    viewer.transform = {
-                        lonlatToLocal : transform1,
-                        lonlatTo4550 : transform2       // 转大地坐标EPSG:4550  
-                    } 
-                    // proj4(fromProjection, toProjection, coordinates)
-                    //let transform = proj4("WGS84", "pointcloud");
-                 
-                    
-                }
-            
-            
-                
-                
-                
-                
-                var cloudPath = 'https://laser.4dkankan.com/data/'+number+'/data/'+ name +'/webcloud/cloud.js' 
-                Potree.loadPointCloud(cloudPath, name, e => {
-                    let scene = viewer.scene;
-                    let pointcloud = e.pointcloud;
-                    
-                    let material = pointcloud.material;
-                    material.size =  0.7;
-                    material.minSize =  0.1//2.0;
-                    material.pointSizeType = Potree.PointSizeType.ATTENUATED//Potree.PointSizeType.ADAPTIVE;//FIXED
-                    material.shape = Potree.PointShape.SQUARE;
-                    //material.activeAttributeName = "rgba";
-                    
-                    /*
-                    material.activeAttributeName = "color";
-                    material.color.set(dataset.color)
-                    material.opacity = 0.05
-                    material.size = 0.2;
-                    material.useEDL = false
-                    */
-                    scene.addPointCloud(pointcloud);
-                     
-                    pointcloud.dataset_id = dataset.id;//供漫游点找到属于的dataset点云
-                    pointcloud.panos = [] 
-                    
-                    //旋转中心
-                    //var center = new THREE.Vector3().addVectors(pointcloud.position, pointcloud.boundingBox.getCenter())  
-                     
-                    //偏移
-                    //当只有一个dataset时,无论如何transform 点云和漫游点都能对应上。
-                    var location = viewer.transform.lonlatToLocal.forward(locationLonLat)  //transform.inverse()
-                    //初始化位置 
-                    pointcloud.matrixAutoUpdate = false   //最好禁止updateMatrix  直接使用matrixWorld
-                    pointcloud.orientationUser = 0  
-                    pointcloud.translateUser = new THREE.Vector3;
-                    
-                    viewer.sidebar.addAlignmentButton(pointcloud) 
-                    Alignment.rotate(pointcloud, null, dataset.orientation)  
-                    Alignment.translate(pointcloud, new THREE.Vector3(location[0], location[1], dataset.location[2])) 
-                    
-                    pointcloud.updateMatrixWorld()
-                    
-                    
-                    console.log(`%c点云${name}旋转值:${pointcloud.orientationUser}, 位置${pointcloud.translateUser.toArray()}`,"color:#13f;font-size:17px"   )
-                    
-                    
-                    //-------------------
-                     
-                    viewer.mapView.showSources(false);
- 
-                    loaded ++;
-                    if(loaded == datasetLength)loadDone()
-                });
-                    
-            })
-            
-            
-        })
-
-		 
-        
-                
-
           
-        window.testTransform = function(locationLonLat, location1, location2){
-            proj4.defs("NAVVIS:test", "+proj=tmerc +ellps=WGS84 +lon_0=" + locationLonLat[0].toPrecision(15) + " +lat_0=" + locationLonLat[1].toPrecision(15));
-            
-            let transform = proj4("WGS84", "NAVVIS:test"); //这个ok  navvis里也是这两种转换 见proj4Factory
-            if(location1){//经纬度
-                return transform.forward(location1) 
-            }else{
-                return transform.inverse(location2) 
-            }            
-            
-        }
-
 		/*
         数据集校准 平移后
         单个数据集:

+ 8 - 0
gulpfile.js

@@ -72,8 +72,16 @@ let shaders = [
 	"src/materials/shaders/edl.fs",
 	"src/materials/shaders/blur.vs",
 	"src/materials/shaders/blur.fs",
+    
+    "src/materials/shaders/copyCubeMap.vs",
+	"src/materials/shaders/copyCubeMap.fs",
+	"src/materials/shaders/basicTextured.vs",
+	"src/materials/shaders/basicTextured.fs",
 ];
 
+
+'src/**/*.js',
+
 // For development, it is now possible to use 'gulp webserver'
 // from the command line to start the server (default port is 8080)
 gulp.task('webserver', gulp.series(async function() {

+ 5 - 3
libs/three.js/build/three.module.js

@@ -23591,6 +23591,8 @@ function WebGLRenderer( parameters ) {
 		_this.state = state;
 		_this.info = info;
 
+        _this._textures = textures;//add 
+        
 	}
 
 	initGLContext();
@@ -23665,8 +23667,8 @@ function WebGLRenderer( parameters ) {
 
 	};
 
-	this.setSize = function ( width, height, updateStyle ) {
-
+	this.setSize = function ( width, height,  updateStyle, devicePixelRatio ) {//改
+        if (devicePixelRatio != void 0) _pixelRatio = devicePixelRatio;  //add
 		if ( xr.isPresenting ) {
 
 			console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
@@ -50456,7 +50458,7 @@ Object.defineProperties( BufferAttribute.prototype, {
 Object.assign( BufferAttribute.prototype, {
 	setDynamic: function ( value ) {
 
-		console.warn( 'THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.' );
+		//console.warn( 'THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.' );
 		this.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );
 		return this;
 

+ 3 - 41
note.txt

@@ -33,47 +33,9 @@ PointCloudOctreeGeometryNode-geometry
 Aa123456
 
 
+  
+label再改回mesh,因为需要遮挡。 (或者能够算出是否遮挡住了。navvis怎么多重遮挡的?)
 
-显示模式:
-
-1只显示点云: 滚轮为前进后退,方向键可以行走。进入漫游点时自动变为混合(这样全景可以弥补缝隙),过渡时只显示点云。
-2只显示全景: 不能任意行走。 过渡时显示贴图材质非edl的点云(否则有折痕不贴合)。
-3混合:都显示。 不能任意行走。过渡时显示贴图材质非edl的点云(因为只显示点云的话不太美,点云很碎,不细腻)
-
-
-settings:{
-	displayMode:{
-
-		showPointCloud{
-			atPano:{
-                showPoint: true,
-                showPanorama
-                
-			},
-            leavePano:{
-
-            }    
-		},
-
-		showPanoramas:{
-
-		},
-
-		showBoth:{
-		}
-
-	}
-
-
-
-
-}
- 
-
-
-
-
-
-
+热点可能也要遮挡。。。。
 
 

+ 1 - 1
src/Enum.js

@@ -11,7 +11,7 @@ class EnumItem{
 	}
 };
 
-class Enum{
+class Enum{//??????做什么用的
 
 	constructor(object){
 		this.object = object;

+ 11 - 1
src/EventDispatcher.js

@@ -95,5 +95,15 @@ export class EventDispatcher{
 		}
 
 	}
-
+    
+    
+    //add 
+    emit(type){ 
+        this.dispatchEvent({type, arguments: Array.from(arguments).slice(1, arguments.length) })
+    }
+    on(type, fun){
+        this.addEventListener(type,(ev)=>{
+            fun.apply(this, ev.arguments)
+        })
+    }
 }

+ 19 - 4
src/PointCloudOctree.js

@@ -14,8 +14,14 @@ export class PointCloudOctreeNode extends PointCloudTreeNode {
 		this.children = [];
 		this.sceneNode = null;
 		this.octree = null;
+         
+        
+        
+        
 	}
 
+    
+
 	getNumPoints () {
 		return this.geometryNode.numPoints;
 	}
@@ -103,7 +109,7 @@ export class PointCloudOctreeNode extends PointCloudTreeNode {
 export class PointCloudOctree extends PointCloudTree {
 	constructor (geometry, material) {
 		super();
-
+    
 		this.pointBudget = Infinity;
 		this.pcoGeometry = geometry;
 		this.boundingBox = this.pcoGeometry.boundingBox;
@@ -114,7 +120,8 @@ export class PointCloudOctree extends PointCloudTree {
 		this.level = 0;
 		this.position.copy(geometry.offset);
 		this.updateMatrix();
-
+        
+        
 		{
 
 			let priorityQueue = ["rgba", "rgb", "intensity", "classification"];
@@ -155,7 +162,9 @@ export class PointCloudOctree extends PointCloudTree {
 		this.profileRequests = [];
 		this.name = '';
 		this._visible = true;
-
+        this.isVisible = true//add
+        
+        
 		{
 			let box = [this.pcoGeometry.tightBoundingBox, this.getBoundingBoxWorld()]
 				.find(v => v !== undefined);
@@ -1142,7 +1151,13 @@ export class PointCloudOctree extends PointCloudTree {
 		}
 
 	}
-
+    /* get isVisible(){//add 手动在数据集选择是否显示(和是否全景图、隐藏点云无关)
+        return this._visible 
+    }
+    set isVisible(visi){
+        this._visible = visi
+        //this.visible = 
+    } */
 }
 
 

+ 2 - 3
src/Potree.js

@@ -79,7 +79,7 @@ export {VRControls} from "./navigation/VRControls.js";
 //add:
 export {Alignment} from "./modules/datasetAlignment/Alignment.js";
 export {config, settings} from "./settings.js";
- 
+export {start} from "./start.js";
 
 
 
@@ -153,8 +153,7 @@ export async function loadDatasets(path, callback){
 
 
 
-
-
+ 
 
 export function loadPointCloud(path, name, callback){
 	let loaded = function(e){

+ 42 - 80
src/PotreeRenderer.js

@@ -456,8 +456,7 @@ class WebGLTexture {
 		this.gl = gl;
 
 		this.texture = texture;
-		this.id = gl.createTexture();
-
+		this.id = gl.createTexture(); 
 		this.target = gl.TEXTURE_2D;
 		this.version = -1;
 
@@ -508,7 +507,8 @@ class WebGLTexture {
 			gl.texImage2D(this.target, level, internalFormat,
 				width, height, border, srcFormat, srcType,
 				data);
-		} else if ((texture instanceof THREE.CanvasTexture) || (texture instanceof THREE.Texture)) {
+		}/* else if(texture instanceof THREE.CubeTexture){//add 
+        } */else if ((texture instanceof THREE.CanvasTexture) || (texture instanceof THREE.Texture)) {
 			data = texture.image;
 
 			gl.texParameteri(this.target, gl.TEXTURE_WRAP_S, paramThreeToGL(gl, texture.wrapS));
@@ -1085,7 +1085,7 @@ export class Renderer {
 
 				this.shaders.set(material, shader);
 			}
-
+            
 			shader = this.shaders.get(material);
 
 			//if(material.needsUpdate){
@@ -1104,8 +1104,15 @@ export class Renderer {
 					`#define num_clipspheres ${numClipSpheres}`,
 					`#define num_clippolygons ${numClipPolygons}`,
 				];
-
-
+                
+                //add:-----------
+                if(material.usePanoMap){
+                    defines.push("#define usePanoMap");
+                } 
+                //---------------
+                
+                
+                
 				if(octree.pcoGeometry.root.isLoaded()){
 					let attributes = octree.pcoGeometry.root.geometry.attributes;
 
@@ -1149,7 +1156,7 @@ export class Renderer {
 
 				material.needsUpdate = false;
 			}
-
+             
 			for (let uniformName of Object.keys(material.uniforms)) {
 				let uniform = material.uniforms[uniformName];
 
@@ -1160,7 +1167,11 @@ export class Renderer {
 					if (!texture) {
 						continue;
 					}
-
+                    //add 
+                    if(uniformName == 'pano0Map' || uniformName == 'pano1Map' ){ //属于cubeTex,另外设置 
+                        continue
+                    } 
+                    
 					if (!this.textures.has(texture)) {
 						let webglTexture = new WebGLTexture(gl, texture);
 
@@ -1335,84 +1346,35 @@ export class Renderer {
 
 
             //=============add===========
-            shader.setUniform1i("usePanoMap", material.uniforms.usePanoMap.value);
-            shader.setUniform1f("progress", material.uniforms.progress.value);
-            shader.setUniform1f("easeInOutRatio", material.uniforms.easeInOutRatio.value);
-            shader.setUniform3f("pano0Position", material.uniforms.pano0Position.value.toArray());
-            shader.setUniform3f("pano1Position", material.uniforms.pano1Position.value.toArray()); 
-            shader.setUniform('pano0Matrix',  material.uniforms.pano0Matrix.value);
-            shader.setUniform('pano1Matrix',  material.uniforms.pano1Matrix.value);
             
             
-            if(material.uniforms.usePanoMap.value == 1){//为什么pointsize失效
-                let pano0Map = this.textures.get(material.uniforms.pano0Map.value);
+            
+            if(material.usePanoMap){//为什么pointsize失效 
+                shader.setUniform1f("progress", material.uniforms.progress.value);
+                shader.setUniform1f("easeInOutRatio", material.uniforms.easeInOutRatio.value);
+                shader.setUniform3f("pano0Position", material.uniforms.pano0Position.value.toArray());
+                shader.setUniform3f("pano1Position", material.uniforms.pano1Position.value.toArray()); 
+                shader.setUniform('pano0Matrix',  material.uniforms.pano0Matrix.value);
+                shader.setUniform('pano1Matrix',  material.uniforms.pano1Matrix.value);
+                
+                let pano0Map = material.uniforms.pano0Map.value
                 if(pano0Map){
-                    shader.setUniform1i("pano0Map", currentTextureBindingPoint);
-                    gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
-                    gl.bindTexture(pano0Map.target, pano0Map.id);
-                    currentTextureBindingPoint++;
+                    this.threeRenderer._textures.safeSetTextureCube( pano0Map, ++currentTextureBindingPoint );
+                          
+                    shader.setUniform1i('pano0Map', currentTextureBindingPoint);
                 }
-                let pano1Map = this.textures.get(material.uniforms.pano1Map.value);
+                let pano1Map = material.uniforms.pano1Map.value
                 if(pano1Map){
-                    shader.setUniform1i("pano1Map", currentTextureBindingPoint);
-                    gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
-                    gl.bindTexture(pano1Map.target, pano1Map.id);
-                    currentTextureBindingPoint++;
+                    this.threeRenderer._textures.safeSetTextureCube( pano1Map, ++currentTextureBindingPoint );
+                         
+                    shader.setUniform1i('pano1Map', currentTextureBindingPoint);
                 }
-            }
-            /* if(material.uniforms.pano0Map.value){
-                //shader.setUniformTexture('pano0Map',material.uniforms.pano0Map.value)
-                let pano0Map = this.textures.get(material.uniforms.pano0Map.value);
-                shader.setUniform1i("pano0Map", currentTextureBindingPoint);                
-                gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
-                gl.bindTexture(gl.TEXTURE_2D, pano0Map.id);
-                currentTextureBindingPoint++;
-            }  */
-            /* if(material.uniforms.pano1Map.value){
-                //shader.setUniformTexture('pano1Map',currentTextureBindingPoint)
-                let pano1Map = this.textures.get(material.uniforms.pano1Map.value);
-                shader.setUniform1i("pano1Map", currentTextureBindingPoint);                  
-                gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
-                gl.bindTexture(gl.TEXTURE_2D, pano1Map.id);
-                currentTextureBindingPoint++; 
-                //this.setUniformTexture('pano1Map',)
-            }    */
-           /*  let classificationTexture = this.textures.get(material.classificationTexture);
-			shader.setUniform1i("classificationLUT", currentTextureBindingPoint);
-			gl.activeTexture(gl.TEXTURE0 + currentTextureBindingPoint);
-			gl.bindTexture(classificationTexture.target, classificationTexture.id);
-			currentTextureBindingPoint++;  */
-			  
-			/* pano0Map: {
-				type: "t",
-				value: null
-			},
-			pano0Position: {
-				type: "v3",
-				value: new THREE.Vector3
-			},
-			pano0Matrix: {
-				type: "m4",
-				value: new THREE.Matrix4
-			},
-			pano1Map: {
-				type: "t",
-				value: null
-			},
-			pano1Position: {
-				type: "v3",
-				value: new THREE.Vector3
-			},
-			pano1Matrix: {
-				type: "m4",
-				value: new THREE.Matrix4
-            },    
-            
- */
-
-
-
-            //===========
+                //注: three.js我添加了个 _textures,   safeSetTextureCube里主要就是activeTexture和bindTexture
+             
+            }   
+                
+          
+            //==========================
 
 
 

+ 2 - 2
src/Potree_update_visibility.js

@@ -75,7 +75,7 @@ export function updateVisibilityStructures(pointclouds, camera, renderer) {
 		let camObjPos = new THREE.Vector3().setFromMatrixPosition(camMatrixObject);
 		camObjPositions.push(camObjPos);
 
-		if (pointcloud.visible && pointcloud.root !== null) {
+		if ( pointcloud.isVisible &&  pointcloud.root !== null) {//改 visible -> isVisible
 			priorityQueue.push({pointcloud: i, node: pointcloud.root, weight: Number.MAX_VALUE});
 		}
 
@@ -132,7 +132,7 @@ export function updateVisibility(pointclouds, camera, renderer){
 	let pointcloudTransformVersion = Potree._pointcloudTransformVersion;
 	for(let pointcloud of pointclouds){
 
-		if(!pointcloud.visible){
+		if(!pointcloud.isVisible){//改 visible -> isVisible
 			continue;
 		}
 

+ 9 - 5
src/TextSprite.js

@@ -6,9 +6,13 @@
 
 import * as THREE from "../libs/three.js/build/three.module.js";
 
+
+
+//可能还是要用html写,因为要加按钮和图片
+
 export class TextSprite extends THREE.Object3D{
 	
-	constructor(text){
+	constructor(text, options={}){
 		super();
 
 		let texture = new THREE.Texture();
@@ -28,10 +32,10 @@ export class TextSprite extends THREE.Object3D{
 
 		this.borderThickness = 4;
 		this.fontface = 'Arial';
-		this.fontsize = 28;
-		this.borderColor = { r: 0, g: 0, b: 0, a: 1.0 };
-		this.backgroundColor = { r: 255, g: 255, b: 255, a: 1.0 };
-		this.textColor = {r: 255, g: 255, b: 255, a: 1.0};
+		this.fontsize = options.fontsize ||  28;
+		this.borderColor = options.borderColor || { r: 0, g: 0, b: 0, a: 1.0 };
+		this.backgroundColor = options.backgroundColor || { r: 255, g: 255, b: 255, a: 1.0 };
+		this.textColor = options.textColor || {r: 255, g: 255, b: 255, a: 1.0};
 		this.text = '';
 
 		this.setText(text);

+ 121 - 5
src/defines.js

@@ -1,6 +1,6 @@
-
+import * as THREE from "../libs/three.js/build/three.module.js";
 import {Enum} from "./Enum.js";
-
+import math from "./utils/math";
 
 export const CameraMode = {
 	ORTHOGRAPHIC: 0,
@@ -26,11 +26,17 @@ export const ElevationGradientRepeat = {
 	MIRRORED_REPEAT: 2,
 };
 
-export const MOUSE = {
-	LEFT: 0b0001,
+export const MOUSE = {// MouseEvent.buttons
+    //buttons,设置按下了鼠标哪些键,是一个3个比特位的二进制值,默认为0。1表示按下主键(通常是左键),2表示按下次要键(通常是右键),4表示按下辅助键(通常是中间的键)。
+	NONE:0,//add
+    
+    LEFT: 0b0001,
 	RIGHT: 0b0010,
 	MIDDLE: 0b0100
 };
+/*  如果访问的是button, 用THREE.MOUSE来判断:
+    button,设置按下了哪一个鼠标按键,默认为0。-1表示没有按键,0表示按下主键(通常是左键),1表示按下辅助键(通常是中间的键),2表示按下次要键(通常是右键)
+ */
 
 export const PointSizeType = {
 	FIXED: 0,
@@ -53,4 +59,114 @@ export const LengthUnits = {
 	METER: {code: 'm', unitspermeter: 1.0},
 	FEET: {code: 'ft', unitspermeter: 3.28084},
 	INCH: {code: '\u2033', unitspermeter: 39.3701}
-};
+};
+
+
+
+/////////// add //////////////////////////////////
+
+ 
+
+var GLCubeFaces = {
+    GL_TEXTURE_CUBE_MAP_POSITIVE_X: 0,
+    GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1,
+    GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2,
+    GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 3,
+    GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 4,
+    GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 5
+};
+
+
+var PanoSizeClass = {
+    BASE: 1,
+    STANDARD: 2,
+    HIGH: 3,
+    ULTRAHIGH: 4
+};
+
+var PanoRendererEvents = {
+    PanoRenderComplete: "panorama.render.complete",
+    TileRenderFailure: "panorama.tile.render.failed",
+    TileRenderSuccess: "panorama.tile.render.success",
+    TileUploadAttempted: "panorama.tile.upload.attempted",
+    UploadAttemptedForAllTiles: "panorama.upload.attempted.all.tiles",
+    ZoomLevelRenderStarted: "panorama.zoom.render.started"
+};
+
+var SceneRendererEvents = {
+    ContextCreated: "scene-renderer-context-created",
+    AfterRender: "after-render",
+    MemoryUsageUpdated: "scene-renderer-memory-usage-updated"
+};
+
+
+var TileDownloaderEvents = {
+    TileDownloadSuccess: "tiledownloader.download.success",
+    TileDownloadFailure: "tiledownloader.download.failure",
+    PanoDownloadComplete: "tiledownloader.pano.download.complete"
+};
+
+var Vectors = {
+    UP: new THREE.Vector3(0,1,0),
+    DOWN: new THREE.Vector3(0,-1,0),
+    LEFT: new THREE.Vector3(-1,0,0),
+    RIGHT: new THREE.Vector3(1,0,0),
+    FORWARD: new THREE.Vector3(0,0,-1),
+    BACK: new THREE.Vector3(0,0,1)
+};
+var Vectors2 = {}
+for(var i in Vectors){
+    Vectors2[i] = math.convertVector.YupToZup(Vectors[i])  
+}
+
+
+
+var DownloadStatus = Object.freeze({
+    None: 0,
+    Queued: 1,
+    ForceQueued: 2,
+    Downloading: 3,
+    Downloaded: 4,
+    DownloadFailed: 5
+});
+var ModelManagerEvents = {
+    ModelAdded: "model-added",
+    ActiveModelChanged: "active-model-changed"
+};
+
+var PanoramaEvents = {
+
+    Enter: 'panorama.enter',
+    Exit: 'panorama.exit',
+
+    LoadComplete: "panorama.load.complete",
+    LoadFailed: "panorama.load.failed",
+    TileLoaded: "panorama.tile.loaded",
+    VideoRendered: "panorama.video.rendered"
+};
+ 
+
+
+
+
+export {GLCubeFaces,PanoSizeClass,PanoRendererEvents,SceneRendererEvents,
+TileDownloaderEvents,Vectors,Vectors2,DownloadStatus,ModelManagerEvents, PanoramaEvents,
+ 
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 14 - 10
src/materials/PointCloudMaterial.js

@@ -152,7 +152,7 @@ export class PointCloudMaterial extends THREE.RawShaderMaterial {
 			backfaceCulling: { type: "b", value: false },
             
             ////////////////add
-            usePanoMap:{ type: "i", value: 0 }, 
+            //usePanoMap:{ type: "i", value: 0 }, 
 			progress: {
 				type: "f",
 				value: 0
@@ -1064,7 +1064,7 @@ export class PointCloudMaterial extends THREE.RawShaderMaterial {
 		}
 	}
 
-	static generateGradientTexture (gradient) {
+	static generateGradientTexture (gradient) { 
 		let size = 64;
 
 		// create canvas
@@ -1124,26 +1124,30 @@ export class PointCloudMaterial extends THREE.RawShaderMaterial {
 	};
 
     ////////////////////////add
-    setProjectedPanos(pano0, pano1, flag, easeInOutRatio){
-        this.uniforms.usePanoMap.value = 1
- 		flag && (this.uniforms.progress.value = 0);
+    setProjectedPanos(pano0, pano1, progressValue, easeInOutRatio){
+        
+        //this.uniforms.usePanoMap.value = 1
+        this.usePanoMap = true
+        
+ 		progressValue!=void 0 && (this.uniforms.progress.value = progressValue);
 		//pano0.ensureSkyboxReadyForRender();
-		this.uniforms.pano0Map.value = pano0.texture
+		this.uniforms.pano0Map.value = pano0.getSkyboxTexture()
 		this.uniforms.pano0Position.value.copy(pano0.position)
 		this.uniforms.pano0Matrix.value.copy(pano0.panoMatrix/* pano0.mesh.matrixWorld */ );
 		//pano1.ensureSkyboxReadyForRender();
  
-        this.uniforms.easeInOutRatio.value = 0//easeInOutRatio || 0;
+        this.uniforms.easeInOutRatio.value =  easeInOutRatio || 0;
 		
-		this.uniforms.pano1Map.value = pano1.texture;
+		this.uniforms.pano1Map.value = pano1.getSkyboxTexture()
 		this.uniforms.pano1Position.value.copy(pano1.position)
 		this.uniforms.pano1Matrix.value.copy(pano1.panoMatrix /* pano1.mesh.matrixWorld */ );
-          
+           
         //this.updateShaderSource()
         //this.needsUpdate = true;
  	}
     stopProjectedPanos(){
-        this.uniforms.usePanoMap.value = 0
+        //this.uniforms.usePanoMap.value = 0
+        this.usePanoMap = false
     } 
 
 	// copyFrom(from){

+ 3 - 3
src/materials/shaders/pointcloud.fs

@@ -12,9 +12,9 @@ precision highp int;
 
 
 //------------
-uniform int usePanoMap;
-uniform sampler2D pano0Map;
-uniform sampler2D pano1Map; 
+//uniform int usePanoMap;
+/*uniform sampler2D pano0Map;
+uniform sampler2D pano1Map; */
 uniform float progress;
 
 //varying vec3 vWorldPosition0;

+ 38 - 13
src/materials/shaders/pointcloud.vs

@@ -16,11 +16,23 @@ uniform vec3 pano1Position;
 uniform mat4 pano1Matrix;
 
 uniform int usePanoMap;
-uniform sampler2D pano0Map;
-uniform sampler2D pano1Map; 
-uniform float progress;
+/*uniform sampler2D pano0Map;
+uniform sampler2D pano1Map;  
+uniform samplerCube pano0Map;   //随便设置一个samplerCube去使用都会让点云消失
+uniform samplerCube pano1Map;*/
+
+
+
+#if defined(usePanoMap) 
+    uniform samplerCube pano0Map;   //随便设置一个samplerCube去使用都会让点云消失
+    uniform samplerCube pano1Map;
+#endif 
+
 
 
+uniform float progress;
+ 
+
 //--------------
 
 
@@ -901,6 +913,14 @@ vec2 getSamplerCoord( vec3 direction )
     return vec2(tx,ty);
 }  
 
+vec3 transformAxis( vec3 direction ) //navvis->4dkk
+{
+    float y = direction.y;
+    direction.y = direction.z;
+    direction.z = -y;
+    return  direction;
+}
+
 void main() {
 	vec4 mvPosition = modelViewMatrix * vec4(position, 1.0 );
 	vViewPosition = mvPosition.xyz;
@@ -912,24 +932,28 @@ void main() {
      
     // COLOR
 	 
-    if(usePanoMap == 1){ 
+    #if defined(usePanoMap)
         vec4 worldPosition = modelMatrix * vec4(position, 1.0);
          
         vec3 positionLocalToPanoCenter0 = worldPosition.xyz - pano0Position;
         vec3 vWorldPosition0 = (vec4(positionLocalToPanoCenter0, 1.0) * pano0Matrix).xyz; 
         vWorldPosition0.x *= -1.0;
-         
+        vWorldPosition0 = transformAxis(vWorldPosition0);
+        
         vec3 positionLocalToPanoCenter1 = worldPosition.xyz - pano1Position;
         vec3 vWorldPosition1 = (vec4(positionLocalToPanoCenter1, 1.0) * pano1Matrix).xyz; 
         vWorldPosition1.x *= -1.0;
+        vWorldPosition1 = transformAxis(vWorldPosition1);
          
-        vec2 samplerCoord0 = getSamplerCoord(vWorldPosition0.xyz);
-        vec2 samplerCoord1 = getSamplerCoord(vWorldPosition1.xyz);
-
-       
+        /*vec2 samplerCoord0 = getSamplerCoord(vWorldPosition0.xyz);
+        vec2 samplerCoord1 = getSamplerCoord(vWorldPosition1.xyz); 
         vec4 colorFromPano0 = texture2D(pano0Map,samplerCoord0);
-        vec4 colorFromPano1 = texture2D(pano1Map,samplerCoord1);
+        vec4 colorFromPano1 = texture2D(pano1Map,samplerCoord1);*/
         
+        //pano0Map;
+        vec4 colorFromPano0=textureCube(pano0Map,vWorldPosition0.xyz);
+        vec4 colorFromPano1=textureCube(pano1Map,vWorldPosition1.xyz);
+
         vColor = mix(colorFromPano0,colorFromPano1,progress).xyz; 
 
         //-----
@@ -947,10 +971,11 @@ void main() {
         }
 
 
-    }else{
+    #else
+     
         vColor = getColor();
-    }
-
+    
+    #endif
    
    
     //-------------------        

Разлика између датотеке није приказан због своје велике величине
+ 644 - 280
src/modules/Images360/Images360.js


+ 35 - 28
src/modules/Images360/ModelTextureMaterial.js

@@ -55,22 +55,32 @@ let shader = {
             varying vec3 vWorldPosition0;
             varying vec3 vWorldPosition1;
             
+            vec3 transformAxis( vec3 direction ) //navvis->4dkk
+            {
+                float y = direction.y;
+                direction.y = direction.z;
+                direction.z = -y;
+                return  direction;
+            }  
+            
+            
+            
             void main() {
             
                 vUv = uv;
                 vec4 worldPosition = modelMatrix * vec4(position, 1.0);
                 
-               
+                
             
                 vec3 positionLocalToPanoCenter0 = worldPosition.xyz - pano0Position;
                 vWorldPosition0 = (vec4(positionLocalToPanoCenter0, 1.0) * pano0Matrix).xyz;
                 vWorldPosition0.x *= -1.0;
-                 
+                vWorldPosition0 = transformAxis(vWorldPosition0);
                 
                 vec3 positionLocalToPanoCenter1 = worldPosition.xyz - pano1Position;
                 vWorldPosition1 = (vec4(positionLocalToPanoCenter1, 1.0) * pano1Matrix).xyz;
                 vWorldPosition1.x *= -1.0;
-              
+                vWorldPosition1 = transformAxis(vWorldPosition1);
                 
                 gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
             
@@ -81,9 +91,7 @@ let shader = {
 
             #define PI 3.141592653 
             
-            
-            
-            uniform sampler2D map;
+             
             uniform float modelAlpha;
             uniform float opacity;
             uniform float progress;
@@ -96,23 +104,18 @@ let shader = {
             
           
        
-            uniform sampler2D pano0Map;
-            uniform sampler2D pano1Map;      
+            /* uniform sampler2D pano0Map;
+            uniform sampler2D pano1Map;    */   
+            uniform samplerCube pano0Map;
+            uniform samplerCube pano1Map;
           
             
             varying vec2 vUv;
             varying vec3 vWorldPosition0;
             varying vec3 vWorldPosition1;
 
-            /* vec2 getSamplerCoord( vec3 direction ) 
-            {
-                direction = normalize(direction);
-                float tx=atan(direction.x,direction.z)/(PI*2.0)+0.5;
-                float ty=acos(direction.y)/PI;
-
-                return vec2(tx,ty);
-            } */ 
-             vec2 getSamplerCoord( vec3 direction ) 
+          
+            vec2 getSamplerCoord( vec3 direction ) 
             {
                 direction = normalize(direction);
                 float tx=atan(direction.x,-direction.y)/(PI*2.0)+0.5;
@@ -123,15 +126,18 @@ let shader = {
             void main()
             {
                 
-                vec2 samplerCoord0 = getSamplerCoord(vWorldPosition0.xyz);
-                vec2 samplerCoord1 = getSamplerCoord(vWorldPosition1.xyz);
+                /* vec2 samplerCoord0 = getSamplerCoord(vWorldPosition0.xyz);
+                vec2 samplerCoord1 = getSamplerCoord(vWorldPosition1.xyz);  
+                vec4 colorFromPano0=texture2D(pano0Map,samplerCoord0);
+                vec4 colorFromPano1=texture2D(pano1Map,samplerCoord1); */
+                
+                vec4 colorFromPano0=textureCube(pano0Map,vWorldPosition0.xyz);
+                vec4 colorFromPano1=textureCube(pano1Map,vWorldPosition1.xyz);
 
-                vec4 color;
                 
-               
-                vec4 colorFromPano0=texture2D(pano0Map,samplerCoord0);
-                vec4 colorFromPano1=texture2D(pano1Map,samplerCoord1);
-               
+
+
+
 
                 gl_FragColor=mix(colorFromPano0,colorFromPano1,progress);
               
@@ -180,17 +186,18 @@ export default class ModelTextureMaterial extends THREE.RawShaderMaterial {
      更新全景图的材质uniforms 
      
 	 */
-	setProjectedPanos(pano0, pano1, flag ){
- 		flag && (this.uniforms.progress.value = 0);
+	setProjectedPanos(pano0, pano1, progressValue ){
+        
+ 		progressValue!=void 0 && (this.uniforms.progress.value = progressValue);
 		//pano0.ensureSkyboxReadyForRender();
-		this.uniforms.pano0Map.value = pano0.texture
+		this.uniforms.pano0Map.value = pano0.getSkyboxTexture();//pano0.texture
 		this.uniforms.pano0Position.value.copy(pano0.position)
 		this.uniforms.pano0Matrix.value.copy(pano0.panoMatrix/* pano0.mesh.matrixWorld */ );
 		//pano1.ensureSkyboxReadyForRender();
  
         
 		
-		this.uniforms.pano1Map.value = pano1.texture;
+		this.uniforms.pano1Map.value = pano1.getSkyboxTexture()//pano1.texture;
 		this.uniforms.pano1Position.value.copy(pano1.position)
 		this.uniforms.pano1Matrix.value.copy(pano1.panoMatrix /* pano1.mesh.matrixWorld */ );
         

+ 279 - 23
src/modules/Images360/Panorama2.js

@@ -1,11 +1,16 @@
 import * as THREE from "../../../libs/three.js/build/three.module.js";
+import {transitions, esing, lerp} from '../../utils/transitions.js'
+import TileUtils from './tile/TileUtils'
+import { PanoRendererEvents, PanoramaEvents, PanoSizeClass} from '../../defines'
+import math from '../../utils/math'
+import { EventDispatcher } from "../../EventDispatcher.js";
 
 
 var texLoader = new THREE.TextureLoader()
 
 
 
-let standardMarkerMat = new THREE.MeshBasicMaterial({side: THREE.DoubleSide , map:texLoader.load('../resources/textures/marker.png') ,transparent:true})
+let standardMarkerMat = new THREE.MeshBasicMaterial({opacity:0.5, side: THREE.DoubleSide , map:texLoader.load('../resources/textures/marker.png') ,transparent:true})
  
 let planeGeo = new THREE.PlaneBufferGeometry(0.1,0.1);
 
@@ -16,10 +21,13 @@ let sg = new THREE.SphereGeometry(0.1, 8, 8);
 
 let sm = new THREE.MeshBasicMaterial({side: THREE.BackSide});
 
+
+
+var rot90 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1),  Math.PI/2 ); //使用的是刚好适合全景图的,给cube贴图需要转90°
 //var rot90 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1,0,0),  -Math.PI/2 ); //4dkk->navvis
-var rot901 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,1,0), -Math.PI/2 ); //整张球幕图要旋转下
+//var rot901 = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,1,0), -Math.PI/2 ); //整张球幕图要旋转下
 //rot90 = new THREE.Quaternion().multiplyQuaternions(  rot901, rot90)   
- 
+var old = null;
 /* 
 转成四维看看的axis:
 var a = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), THREE.Math.degToRad(-90))  因为四维的要绕y转90
@@ -30,9 +38,10 @@ var a = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), THREE.
  */
 
 //暂时直接用4dkkconsole输出的数据 
-class Panorama2{
+class Panorama2 extends EventDispatcher{
 
-	constructor(o, transform){//file, time, longitude, latitude, altitude, course, pitch, roll
+	constructor(o, transform, images360){//file, time, longitude, latitude, altitude, course, pitch, roll
+        super()
         this.id = o.id;
         this.position = new THREE.Vector3().fromArray(o.dataset_location) 
         //this.position.set(this.position.x, -this.position.z, this.position.y) //4dkk的坐标绕x旋转90°
@@ -51,7 +60,7 @@ class Panorama2{
         this.pointcloud = viewer.scene.pointclouds.find(e=>e.dataset_id == o.dataset_id) || viewer.scene.pointclouds[0]
         this.pointcloud.panos.push(this)
         
-        
+        //全景图和Cube的水平采样起始坐标相差90度 
         
 
         /* if(from4dkk){
@@ -64,28 +73,46 @@ class Panorama2{
         }else{ */
             var qua = o.dataset_orientation 
             qua = [qua[1], qua[2], qua[3], qua[0]]
-            this.quaternion   = new THREE.Quaternion().fromArray(qua)
-            //this.oriQuaternion = this.quaternion.clone()
+            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度
          //}
 
-        /* var qua = o.dataset_orientation 
-        //qua = [qua[1], qua[2], qua[3], qua[0]] 
-        //qua = [qua[0], -qua[2], qua[1], qua[3]] 
-
-
-        //var qua =  [0,0,0,1]
-        var quaternion = new THREE.Quaternion().fromArray(qua)
-            quaternion = new THREE.Quaternion().multiplyQuaternions(quaternion,  rot901);//整张球幕图要旋转下  因为在4dkk里转过,还原。如果是tiles的不用
-        this.quaternion = new THREE.Quaternion(quaternion.x, -quaternion.z, quaternion.y, quaternion.w) //转化坐标
-
- */
+      
         //let xy = this.transform.forward([this.longitude, this.latitude]);  
         this.file = `https://4dkk.4dage.com/images/images${Potree.settings.number}/pan/high/${this.id}.jpg`
         this.build()
         this.transformByPointcloud()
+        
+        
+        
+        {//tile
+            this.minimumTiledPanoLoaded = !1;
+            this.highestPartialTileRenderOpCompleted = 0;
+            this.highestFullTileRenderOpCompleted = 0;
+            this.shouldRedrawOnBaseLoaded = !1;
+            this.resolutionPromise = {}
+            this.tiledPanoRenderTarget = null;
+            this.zoomed = !1;
+            
+            
+            this.images360 = images360
+           
+            images360.panoRenderer.on(PanoRendererEvents.TileRenderSuccess, this.onTileRendered.bind(this));
+            images360.panoRenderer.on(PanoRendererEvents.PanoRenderComplete, this.onPanoRendered.bind(this));
+            images360.panoRenderer.on(PanoRendererEvents.TileRenderFailure, this.onTileRenderFail.bind(this));
+            images360.panoRenderer.on(PanoRendererEvents.UploadAttemptedForAllTiles, this.onUploadAttemptedForAllTiles.bind(this));
+            
+        }
 	}
     
-    
+
+
+
+
+
+
+
     transformByPointcloud(){
         /* pointcloud.orientationUser = 0  
                     pointcloud.translateUser = new THREE.Vector3; */
@@ -127,16 +154,245 @@ class Panorama2{
         this.mesh = mesh;
          
          
-        let marker = new THREE.Mesh(planeGeo, standardMarkerMat)
+        let marker = new THREE.Mesh(planeGeo, standardMarkerMat.clone())
             
             marker.position.copy(this.floorPosition); 
             //marker.position.z += 0.1;
             marker.up.set(0,0,1)
             marker.lookAt(this.position) 
             marker.scale.set(2,2,2) 
-            
-        this.marker = marker    
+             
+        this.marker = marker 
+    }
+    
+    
+    hoverOn() { 
+        //console.log("hoverOn  " + this.id  )
+        transitions.start(lerp.property(this.marker.material, "opacity", 1), 250)  
+		
+    }
+
+ 
+
+
+    hoverOff(){
+        //console.log("hoverOff  " + this.id  )
+        transitions.start(lerp.property(this.marker.material, "opacity", 0.5), 250) 
+
+    }
+    
+    enter(){ 
+        this.setZoomed(!1),
+        this.dispatchEvent({type:PanoramaEvents.Enter, oldPano:old, newPano:this  }  ),
+        old = this 
+        //this.model.setHighMap(this)//add
+        
+        //console.log("enter pano "+ this.id)
+    } 
+
+    exit(){
+        /* if(this.tiled)
+        { */
+            this.clearWaitDeferreds();
+            this.minimumTiledPanoLoaded = !1;
+            this.tiledPanoRenderTarget = null;
+            this.setZoomed(!1);
+            this.images360.panoRenderer.deactivateTiledPano(this);
+            this.highestPartialTileRenderOpCompleted = 0;
+            this.highestFullTileRenderOpCompleted = 0;
+        /*}
+         else
+        {
+            this.solidSkybox.dispose();
+            this.solidSkybox.loaded = !1;
+            this.solidSkybox.version = 0;
+        } */
+        
+        //console.log("exit pano "+ this.id)
+        
+        this.emit(PanoramaEvents.Exit, this); 
     }
+
+    
+    getSkyboxTexture(){
+        /* if(this.tiled)
+        { */
+            if(this.minimumTiledPanoLoaded)
+            {
+                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;
+                }
+            }
+            else
+            {
+                return null;
+            }
+        /* }
+        else
+        { 
+            return this.solidSkybox;
+        }*/
+    }
+    
+    setZoomed(e){
+        this.zoomed = e;
+        //this.updateSkyboxForZoomLevel();
+        //e ? this.model.showHighMap() : this.model.hideHighMap() //add
+    }
+    
+    isLoaded(e){
+        //if (this.tiled) {
+            if (e && "string" == typeof e)
+                console.error("Wrong panoSize given to Panorama.isLoaded(); a tiled pano uses PanoSizeClass");
+            return !!this.minimumTiledPanoLoaded && (!e || this.highestPartialTileRenderOpCompleted >= e)
+        //}
+        /* if (e && "number" == typeof e)
+            throw new BasicException("Wrong panoSize given to Panorama.isLoaded(); a non-tiled pano uses high/low.");
+        return !!this.solidSkybox.high || e in this.solidSkybox */
+    }
+
+    getWaitDeferred(size){//获取不同size的tile贴图的promiss 
+        var t = this.resolutionPromise[this.id];
+        t || (t = {}, this.resolutionPromise[this.id] = t);
+        var i = t[size];
+        return i || (i = {
+            deferred: $.Deferred(),
+            active: !1
+        },
+        t[size] = i),
+        i
+    }
+    
+    clearWaitDeferreds(){
+        var e = this.resolutionPromise[this.id];
+        e || (e = {},
+        this.resolutionPromise[this.id] = e);
+        for (var t in e)
+            if (e.hasOwnProperty(t)) {
+                var i = e[t];
+                i.active = !1,
+                i.deferred = $.Deferred()
+            }
+    }
+    resetWaitDeferred(e){
+        var t = this.getWaitDeferred(e);
+        t.active = !1;
+        t.deferred = $.Deferred();
+    }
+    onTileRendered(e, t, i, n){
+        e === this.id && this.dispatchEvent({type:PanoramaEvents.TileLoaded,  size:t, index:i, count:n});
+    }
+
+    onPanoRendered(e, t, i, n) {
+        if(e === this.id)
+        {
+            this.minimumTiledPanoLoaded = !0;
+            //this.updateSkyboxForZoomLevel();//更新贴图 setProjected
+            t > this.highestPartialTileRenderOpCompleted && (this.highestPartialTileRenderOpCompleted = t);//应该是更新最高获取到的Partial size
+            !n && t > this.highestFullTileRenderOpCompleted && (this.highestFullTileRenderOpCompleted = t); //应该是更新最高获取到的Full size
+            //this.emit("load", t);
+            //this.model.emit("load", this);
+            this.dispatchEvent({type:PanoramaEvents.LoadComplete, size:t, count:i});
+        }
+    }
+ 
+    onTileRenderFail(e, t, i) {
+        e === this.id && this.dispatchEvent({type:PanoramaEvents.LoadFailed, t});
+    }
+    onUploadAttemptedForAllTiles(e, t, i) {
+        if (e === this.id) {
+            var n = this.images360.qualityManager.getPanoSize(PanoSizeClass.BASE);
+            if(t === n && this.shouldRedrawOnBaseLoaded)
+            {
+                this.shouldRedrawOnBaseLoaded = !1;
+                this.panoRenderer.resetRenderStatus(this.id, !0, !1);
+                this.panoRenderer.renderPanoTiles(this.id, null, !0, !0);
+            }
+        }
+    }
+
+    
+    
+    
+    
+    
+    
+    
+    
+    
 };
 
+
+
+
+Panorama2.prototype.loadTiledPano = function() {
+    var downloads = []  , t = [];
+    
+    return function(size, dir, fov, o, a, download) {
+        null !== o && void 0 !== o || (o = !0),
+        null !== a && void 0 !== a || (a = !0);
+        var l = this.getWaitDeferred(size)
+          , c = l.deferred
+          , h = null
+          , u = null;
+        fov && ("number" == typeof fov ? h = fov : (h = fov.hFov, u = fov.vFov))  
+        if (!this.isLoaded(size)) {
+            if (!l.active) {
+                l.active = !0 
+                if (fov) {
+                    var d = TileUtils.matchingTilesInDirection(this, size, dir, h, u);
+                    downloads[this.id + ":" + size] = {
+                        tileCount: 0,
+                        targetTileCount: d
+                    } 
+                    //console.log("Loading partial pano: " + this.id + " with " + d + " tiles")
+                }
+                if(!t[this.id]) {
+                    t[this.id] = !0 
+                    
+                    this.addEventListener(PanoramaEvents.LoadComplete, function(ev/* e, t */) {//本次任务全部加载完毕 
+                        var i = this.getWaitDeferred(ev.size).deferred;//"pending"为还未完成
+                        i && "pending" === i.state() && this.highestPartialTileRenderOpCompleted >= ev.size && (i.resolve(ev.size, ev.count),
+                        this.resetWaitDeferred(ev.size))//恢复active为false
+                    }.bind(this)) 
+                    
+                    this.addEventListener(PanoramaEvents.LoadFailed, function(ev) {
+                        var t = this.getWaitDeferred(e).deferred;
+                        t && "pending" === t.state() && this.highestPartialTileRenderOpCompleted >= ev.t && (t.reject(ev.t),
+                        this.resetWaitDeferred(ev.t))//恢复active为false
+                    }.bind(this)) 
+                    
+                    this.addEventListener(PanoramaEvents.TileLoaded, function(ev/* t, i, n */) {//每张加载完时
+                        var r = this.getWaitDeferred(ev.size).deferred;
+                        if (r && "pending" === r.state()) {
+                            r.notify(ev.size, ev.index, ev.count);
+                            var o = downloads[this.id + ":" + ev.size];
+                            if(o){//如果有规定下载哪些tile,只需要下载这些tile则LoadComplete
+                                o.tileCount++ 
+                                if(o.tileCount === o.targetTileCount){//达到下载目标数
+                                    this.onPanoRendered(this.id, ev.size, ev.count, !0);
+                                    r.resolve(ev.size, ev.count);
+                                    this.resetWaitDeferred(ev.size)
+                                }
+                            }
+                        }
+                    }.bind(this))
+                }
+            }
+            this.images360.tileDownloader.clearForceQueue(),
+            this.images360.tileDownloader.forceQueueTilesForPano(this, size, dir, h, u, download),
+            this.tiledPanoRenderTarget = this.images360.panoRenderer.activateTiledPano(this, this.images360.qualityManager.getMaxNavPanoSize(), o),
+            this.images360.panoRenderer.renderPanoTiles(this.id, dir, a)
+        }
+        return c.promise()
+    }
+}()
+
 export default Panorama2

+ 66 - 54
src/navigation/FirstPersonControls.js

@@ -61,13 +61,13 @@ export class FirstPersonControls extends EventDispatcher {
 
 		this.tweens = [];
 
-
+        this.enableChangePos = true
         
 
 		let drag = (e) => {
-			if (e.drag.object !== null) {
+			/* if (e.drag.object !== null) {
 				return;
-			}
+			} */
 
 			if (e.drag.startHandled === undefined) {
 				e.drag.startHandled = true;
@@ -100,20 +100,23 @@ export class FirstPersonControls extends EventDispatcher {
                   , o = Math.atan2(e1.y, i)
                   , a = Math.atan2(t.y, n);
                    
-                this.pitchDelta =  o - a  //上下旋转
+                this.pitchDelta +=  o - a  //上下旋转
                 e1.y = 0,
-                t.y = 0;
-                var s = Math.acos(e1.dot(t) / e1.length() / t.length());
-                isNaN(s) || (this.yawDelta = s ,//左右旋转
-                e.drag.pointerDragStart.x > e.drag.pointer.x && (this.yawDelta *= -1)),
-                e.drag.pointerDragStart.copy(e.drag.pointer)
+                t.y = 0; 
                 
-                //console.log(this.pitchDelta)
+                var s = Math.acos(e1.dot(t) / e1.length() / t.length());
                 
+                if(!isNaN(s)){
+                    var yawDelta = s    //左右旋转 
+                    e.drag.pointerDragStart.x > e.drag.pointer.x && (yawDelta *= -1) 
+                    this.yawDelta += yawDelta
+                } 
+                e.drag.pointerDragStart.copy(e.drag.pointer)
+                 
                 camera.matrixWorld = _matrixWorld ;
               
 			} else if (mode == 'pan') {//平移 
-             
+                if(!this.enableChangePos)return
                 if(camera.type == "OrthographicCamera"){
                     let moveVec = new THREE.Vector3; 
                     let viewport = e.drag.dragViewport;
@@ -187,7 +190,7 @@ export class FirstPersonControls extends EventDispatcher {
 
 		let scroll = (e) => { 
             //优化下,当高度在和建筑物差不多时speed恒定, 离开建筑物后才开始加大。
-           
+            if(!this.enableChangePos)return
             this.setCurrentView({viewport : e.hoverViewport})
             let camera = e.hoverViewport ? e.hoverViewport.camera : this.scene.getActiveCamera()
             let speed = this.viewer.getMoveSpeed() 
@@ -205,7 +208,7 @@ export class FirstPersonControls extends EventDispatcher {
             }else{
                 var direction = this.currentView.direction.clone();
             
-                var vec = direction.multiplyScalar(speed * 20)
+                var vec = direction.multiplyScalar(speed * 10)
                 if (e.delta < 0) {
                     this.translationWorldDelta.copy(vec.negate())
                 } else if (e.delta > 0) {
@@ -217,7 +220,7 @@ export class FirstPersonControls extends EventDispatcher {
 		};
 
 		let dblclick = (e) => {
-            if(viewer.navigateMode == 'free') this.zoomToLocation(e.mouse);
+            if(Potree.settings.displayMode == 'showPointCloud'/* !viewer.images360.isAtPano() */) this.zoomToLocation(e.mouse);
 		};
 
 		this.addEventListener('drag', drag);
@@ -226,7 +229,12 @@ export class FirstPersonControls extends EventDispatcher {
 		this.addEventListener('dblclick', dblclick);
         
         viewer.addEventListener('startDragging', this.setCurrentView.bind(this))
-        
+        viewer.addEventListener('enableChangePos', (e)=>{
+            this.enableChangePos = e.canLeavePano 
+        })
+
+
+       
 	}
 
 
@@ -317,6 +325,9 @@ export class FirstPersonControls extends EventDispatcher {
 	}
 
 	update (delta) {
+        
+ 
+        
 		let view = this.currentView//this.scene.view;
 
 		{ // cancel move animations on user input
@@ -361,44 +372,45 @@ export class FirstPersonControls extends EventDispatcher {
             }
             
         
+            if(this.enableChangePos){
+                if(this.lockElevation){
+                    let dir = view.direction;
+                    dir.z = 0;
+                    dir.normalize();
+
+                    if (moveForward && moveBackward) {
+                        this.translationWorldDelta.set(0, 0, 0);
+                    } else if (moveForward) {
+                        this.translationWorldDelta.copy(dir.multiplyScalar(this.viewer.getMoveSpeed()));
+                    } else if (moveBackward) {
+                        this.translationWorldDelta.copy(dir.multiplyScalar(-this.viewer.getMoveSpeed()));
+                    }
+                }else{
+                    if (moveForward && moveBackward) {
+                        this.translationDelta.y = 0;
+                    } else if (moveForward) {
+                        this.translationDelta.y = this.viewer.getMoveSpeed();
+                    } else if (moveBackward) {
+                        this.translationDelta.y = -this.viewer.getMoveSpeed();
+                    }
+                }
 
-			if(this.lockElevation){
-				let dir = view.direction;
-				dir.z = 0;
-				dir.normalize();
-
-				if (moveForward && moveBackward) {
-					this.translationWorldDelta.set(0, 0, 0);
-				} else if (moveForward) {
-					this.translationWorldDelta.copy(dir.multiplyScalar(this.viewer.getMoveSpeed()));
-				} else if (moveBackward) {
-					this.translationWorldDelta.copy(dir.multiplyScalar(-this.viewer.getMoveSpeed()));
-				}
-			}else{
-				if (moveForward && moveBackward) {
-					this.translationDelta.y = 0;
-				} else if (moveForward) {
-					this.translationDelta.y = this.viewer.getMoveSpeed();
-				} else if (moveBackward) {
-					this.translationDelta.y = -this.viewer.getMoveSpeed();
-				}
-			}
-
-			if (moveLeft && moveRight) {
-				this.translationDelta.x = 0;
-			} else if (moveLeft) {
-				this.translationDelta.x = -this.viewer.getMoveSpeed();
-			} else if (moveRight) {
-				this.translationDelta.x = this.viewer.getMoveSpeed();
-			}
+                if (moveLeft && moveRight) {
+                    this.translationDelta.x = 0;
+                } else if (moveLeft) {
+                    this.translationDelta.x = -this.viewer.getMoveSpeed();
+                } else if (moveRight) {
+                    this.translationDelta.x = this.viewer.getMoveSpeed();
+                }
 
-			if (moveUp && moveDown) {
-				this.translationWorldDelta.z = 0;
-			} else if (moveUp) {
-				this.translationWorldDelta.z = this.viewer.getMoveSpeed();
-			} else if (moveDown) {
-				this.translationWorldDelta.z = -this.viewer.getMoveSpeed();
-			}
+                if (moveUp && moveDown) {
+                    this.translationWorldDelta.z = 0;
+                } else if (moveUp) {
+                    this.translationWorldDelta.z = this.viewer.getMoveSpeed();
+                } else if (moveDown) {
+                    this.translationWorldDelta.z = -this.viewer.getMoveSpeed();
+                }
+            } 
 		}
 
 		{ // apply rotation
@@ -415,9 +427,9 @@ export class FirstPersonControls extends EventDispatcher {
             this.yawDelta = 0
             this.pitchDelta = 0 
 		}
-    if(this.translationWorldDelta.length()>0) {
-       // console.log('translationDelta')
-    }
+        if(this.translationWorldDelta.length()>0) {
+           // console.log('translationDelta')
+        }
 
 		{ // apply translation
 			view.translate(

+ 44 - 28
src/navigation/InputHandler.js

@@ -7,6 +7,7 @@
 import * as THREE from "../../libs/three.js/build/three.module.js";
 import {KeyCodes} from "../KeyCodes.js";
 import {Utils} from "../utils.js";
+import {MOUSE} from "../defines.js"; 
 import {EventDispatcher} from "../EventDispatcher.js";
 import Magnifier from "../utils/Magnifier.js";
 import Reticule from "./Reticule.js";
@@ -52,8 +53,8 @@ export class InputHandler extends EventDispatcher {
         //this.viewer.scene.sceneOverlay.add(this.magnifier) 
         this.viewer.overlay.add(this.magnifier) //不和sceneOverlay放一处,因为透明冲突
         this.reticule = new Reticule(this)
-        this.viewer.overlay.add(this.reticule) 
-        
+        this.viewer.scene.sceneOverlay.add(this.reticule) 
+        this.mouseDownMouse;
         
         
         
@@ -117,6 +118,9 @@ export class InputHandler extends EventDispatcher {
 				changedTouches: e.changedTouches
 			});
 		}
+        
+        //add
+        this.mouseDownMouse = this.mouse.clone()
 	}
 
 	onTouchEnd (e) {
@@ -155,7 +159,7 @@ export class InputHandler extends EventDispatcher {
 			this.mouse.set(x, y);
 
 			if (this.drag) {
-				this.drag.mouse = 1;
+				this.drag.mouse = 1; //why??非左键也非右键的意思?
 
 				this.drag.mouseDelta.x = x - this.drag.end.x;
 				this.drag.mouseDelta.y = y - this.drag.end.y;
@@ -210,7 +214,7 @@ export class InputHandler extends EventDispatcher {
 		this.dispatchEvent({
 			type: 'keydown',
 			keyCode: e.keyCode,
-			event: e
+			event: e                                            
 		});
 
 		// for(let l of this.getSortedListeners()){
@@ -319,7 +323,7 @@ export class InputHandler extends EventDispatcher {
         //add
         this.drag.pointerDragStart = this.pointer.clone()
         this.drag.intersectStart = this.intersectPoint;
-        
+        this.mouseDownMouse = this.mouse.clone()
         
 		if (this.scene) {
 			this.viewStart = this.scene.view.clone();
@@ -327,13 +331,16 @@ export class InputHandler extends EventDispatcher {
 	}
 
 	onMouseUp (e) {
+        if(!this.drag){// 在canvas外mousedown
+            return 
+        }
 		if (this.logMessages) console.log(this.constructor.name + ': onMouseUp');
 
 		e.preventDefault();
-
+        
+        let pressDistance = this.mouseDownMouse.distanceTo(this.mouse);
 		let noMovement = this.getNormalizedDrag().length() === 0;
-
-		
+        
 		let consumed = false;
 		let consume = () => { return consumed = true; };
 		if (this.hoveredElements.length === 0) {
@@ -342,7 +349,9 @@ export class InputHandler extends EventDispatcher {
 					type: 'mouseup',
 					viewer: this.viewer,
 					mouse: this.mouse,
-					consume: consume
+					consume: consume,
+                    drag :this.drag,
+                    pressDistance 
 				});
 
 				if(consumed){
@@ -363,12 +372,14 @@ export class InputHandler extends EventDispatcher {
 		}
 
 		if (this.drag) {
-			if (this.drag.object) {
+            //只有左键才能拖拽物体:
+			if (this.drag.object/*  && e.button == THREE.MOUSE.LEFT */) {//add LEFT
 				if (this.logMessages) console.log(`${this.constructor.name}: drop ${this.drag.object.name}`);
 				this.drag.object.dispatchEvent({
 					type: 'drop',
-					drag: this.drag,
-					viewer: this.viewer
+					drag: this.drag, 
+					viewer: this.viewer,
+                    pressDistance
 
 				});
 			} else {
@@ -376,7 +387,8 @@ export class InputHandler extends EventDispatcher {
 					inputListener.dispatchEvent({
 						type: 'drop',
 						drag: this.drag,
-						viewer: this.viewer
+						viewer: this.viewer,
+                        pressDistance
 					});
 				}
 			}
@@ -391,11 +403,7 @@ export class InputHandler extends EventDispatcher {
 					consume: consume,
 				});
 			}
-            var endDragFun = this.drag.endDragFun
-			this.drag = null;
-            //console.log('mouseup this.drag = null;')
-            
-            endDragFun && endDragFun(e)//add
+            this.drag = null;
             
 		}
 
@@ -513,16 +521,16 @@ export class InputHandler extends EventDispatcher {
             {pickClipped: true});
 
 
-		if (this.drag) {
-			this.drag.mouse = e.buttons;
+		if (this.drag) {//有按下鼠标拖拽(不一定拖拽了物体)
+			this.drag.mouse = e.buttons; 
 
 			this.drag.mouseDelta.x = this.mouse.x - this.drag.end.x;
 			this.drag.mouseDelta.y = this.mouse.y - this.drag.end.y;
 
 			this.drag.end.set(this.mouse.x, this.mouse.y);
             
-
-			if (this.drag.object) {
+            //如果按下右键或中建,就暂停拖拽:
+			if (this.drag.object && (e.buttons == MOUSE.LEFT || e.buttons == MOUSE.NONE)) {//add LEFT
 				if (this.logMessages) console.log(this.constructor.name + ': drag: ' + this.drag.object.name);
 				this.drag.object.dispatchEvent({
 					type: 'drag',
@@ -598,7 +606,7 @@ export class InputHandler extends EventDispatcher {
             }
             
             
-            this.reticule.updatePosition(this.intersectPoint, defaultCamera.position)   
+            
 
             
             if (intersectPoint) { 
@@ -620,17 +628,19 @@ export class InputHandler extends EventDispatcher {
                         type : "coordinateChange", pos
                     })
                 }
+                
+                //viewer.images360.updateClosestPano(intersectPoint)
+                
             }
             
             
-            
-
+             
             
             
             
 		}
         
-        
+        this.reticule.updatePosition(intersectPoint, defaultCamera.position)   
         //add 放大镜
         
         
@@ -649,6 +659,7 @@ export class InputHandler extends EventDispatcher {
 		 for (let inputListener of this.getSortedListeners()) {
 		 	inputListener.dispatchEvent({
 		 		type: 'mousemove',
+                intersectPoint,
 		 		object: null
 		 	});
 		 }
@@ -852,11 +863,11 @@ export class InputHandler extends EventDispatcher {
 		}
 		
 		let camera = this.scene.getActiveCamera();
-		 let ray = Utils.mouseToRay(this.pointer, camera, this.domElement.clientWidth, this.domElement.clientHeight);
+        let ray = Utils.mouseToRay(this.pointer, camera, this.domElement.clientWidth, this.domElement.clientHeight);
 		
 		let raycaster = new THREE.Raycaster();
 		raycaster.ray.set(ray.origin, ray.direction);  
-        
+        raycaster.camera = camera //add
         
         /* let {origin,direction}  = this.getMouseDirection()
         let raycaster = new THREE.Raycaster();
@@ -866,6 +877,11 @@ export class InputHandler extends EventDispatcher {
 		raycaster.params.Line.threshold = 0.2;
 
 		let intersections = raycaster.intersectObjects(interactables.filter(o => o.visible), false);
+        
+        
+        //add for测量线,在检测到sphere时优先选中sphere而非线
+        intersections = intersections.sort(function(a,b){return b.object.renderOrder-a.object.renderOrder}) // 降序
+ 
 
 		return intersections;
 	}

+ 20 - 8
src/navigation/Reticule.js

@@ -4,16 +4,20 @@ import {transitions, esing, lerp} from '../utils/transitions.js'
 
 
 
-let texLoader = new THREE.TextureLoader() 
+let texLoader = new THREE.TextureLoader()
+let defaultOpacity =  0.7
 //鼠标指示小圆片 
 export default class Reticule extends THREE.Mesh{
     constructor(inputHandler){
-         
-        super(new THREE.PlaneBufferGeometry(0.3,0.3,1,1),new THREE.MeshBasicMaterial({
+        var defaultTex = texLoader.load(Potree.config.urls.localTextures+'whiteCircle.png'/* reticule-256x256.png'  */)  
+        var crosshairTex = texLoader.load(Potree.config.urls.localTextures+'reticule_cross_hair.png') 
+        
+        super(new THREE.PlaneBufferGeometry(0.15,0.15,1,1),new THREE.MeshBasicMaterial({
             side: THREE.DoubleSide , 
-            map: texLoader.load('../resources/textures/reticule-256x256.png'),
+            map: defaultTex,
             transparent:true,
             depthTest: !1,
+            opacity: defaultOpacity,
             //depthWrite: !1,
         }))
         
@@ -37,7 +41,7 @@ export default class Reticule extends THREE.Mesh{
         
         
         //this.layers.set(0/* RenderLayers.RETICULE */);
-        //this.renderOrder = RenderOrder.reticule;
+        this.renderOrder = 0
        
         this.direction = new THREE.Vector3;
         this.hidden = !0;
@@ -45,8 +49,16 @@ export default class Reticule extends THREE.Mesh{
 
 
         inputHandler.addInputListener(this);
-        this.addEventListener('mousemove',this.move.bind(this)) 
-
+        this.addEventListener('mousemove',this.move.bind(this))
+        
+        this.addEventListener('measureMovePoint',()=>{
+            this.material.map = crosshairTex
+        }) 
+        this.addEventListener('endMeasureMove',()=>{
+            this.material.map = defaultTex 
+        }) 
+         
+    
     }
 
     move(){
@@ -63,7 +75,7 @@ export default class Reticule extends THREE.Mesh{
     show(){
         //console.log("show Reticule")
         this.hidden = !1,
-        this.material.opacity <= 0 && transitions.start(lerp.property(this.material, "opacity", 1), 300)
+        this.material.opacity <= 0 && transitions.start(lerp.property(this.material, "opacity", defaultOpacity), 300)
     }
 
     //鼠标静止一段时间它就会消失

+ 98 - 5
src/settings.js

@@ -1,5 +1,5 @@
 //xzw add  
-
+import browser from './utils/browser'
 
 const config = {//配置参数   不可修改
     displayMode:{ 
@@ -30,8 +30,8 @@ const config = {//配置参数   不可修改
                 pointUsePanoTex: true //是否使用全景贴图
             },
             canLeavePano: false    
-		},
-
+		}, 
+        
 		showBoth:{
             atPano:{
                 showPoint : true,
@@ -44,17 +44,110 @@ const config = {//配置参数   不可修改
                 pointUsePanoTex: true  
             },
             canLeavePano: true   //是否能离开pano位置   离开后自动变为showPointCloud
-		}
+		},
+        //test:
+        pointUsePanoTex:{ //---静止时调点云
+            atPano:{
+                showPoint : true,
+                showSkybox: false,
+                pointUsePanoTex : true  
+			},
+            transition:{
+                showPoint: true,
+                showSkybox: true,
+                pointUsePanoTex: true //是否使用全景贴图
+            },
+            canLeavePano: false    
+		},
 
 	},
     
+     
     transitionsTime:{
         panoToPano: 1000,
         flyIn:1000,
         flyOut:1000,
     }
+    ,
+    
+    measure:{
+        lineColor:"#00c7b2",
+        guideLineColor:"#FFFFFF",
+        lineWidth: 4,
+        labelOpacity:0.7,
+        textColor: "#FFFFFF"
+        
+    },
+    material:{//初始化
+        pointSize:0.4,//1.6,
+        minSize: 0.1,
+        pointSizeType: 'ADAPTIVE'// 
+        //ADAPTIVE : 字会失真扭曲
+        //'ATTENUATED' 往旁边看有缝隙、点在浮动
+        //navvis的shader在哪里 为什么不会抖动
+    }
+    ,
+    
+    
+    urls:{
+        localTextures:'../resources/textures/',
+        
+        
+    },
+    
+    tiling: {
+        panoPreRenderRepeatDelay: 2500,
+        panoPreRenderDelay: 500,
+        preRenderTourPanos: browser.valueFromHash("tileprerender", 0),
+        tilingFlagNames: ["usetiles", "tiles"],
+        maxNavPanoQuality: browser.valueFromHash("maxtileq", null),
+        maxZoomPanoQuality: browser.valueFromHash("maxztileq", null),
+        overlayStyle: browser.valueFromHash("tileoverlay", 0),
+        uploadIntervalDelay: browser.valueFromHash("tileupdelay", 10),
+        initialIntervalDelay: browser.valueFromHash("itiledelay", 0),
+        maxNonBaseUploadsPerFrame: browser.valueFromHash("maxnbtpf", 2),
+        maxBaseUploadsPerFrame: browser.valueFromHash("maxbtpf", 6),
+        customCompression: browser.valueFromHash("tilecustcomp", 0),
+        mobileHighQualityOverride: !1,
+        allowUltraHighResolution: !0
+    },
+    navigation: {
+        panoScores: !1,
+        mouseDirection: !0,
+        filterStrictness: .75,
+        angleFactor: -30,
+        directionFactor: 10,
+        distanceFactor: -1,
+        optionalityFactor: 3
+    },
     
     
+    signedUrlDefaultExpireTime: 24e4,
+    signedUrlCheckInterval: 1e4,
+    signedUrlRefreshBuffer: 15e3,
+    dollhouseFOV: 70,
+    dollhouseNear: 1,
+    dollhouseFar: 5e3,
+    insideFOV: 70,
+    insideFOVMax: 120,
+    insideNear: .1,
+    insideFar: 5e3,
+    insideLookSpeed: .12,
+    insideLookLimitUp: 40,
+    insideLookLimitDown: -90,//-40,
+    orthoNear: 1,
+    orthoFar: 5e3,
+    orthoBase: 10,
+    narrowLandscapeHeight: 290,
+    reallyNarrowLandscapeHeight: 250,
+    visionTilingStartDate: new Date("8/26/2016"),
+    visionTilingStartVersion: "1.1.407.13667",
+    windowHeightHighQualityThreshold: 900,
+    tourStepDelayDefault: 3500,
+    tourStepDelaySlideShow: 5e3,
+    workshopApsect: 9 / 16,
+    highQualityMaxZoom: 2,
+    ultraHighQualityMaxZoom: 3
 }
 /* 显示模式:
 
@@ -66,8 +159,8 @@ const config = {//配置参数   不可修改
 
 var settings = {//设置   可修改
     number: '', //场景序号
+    displayMode:''
     
-    displayMode : '',//'showPointCloud'
     
 }
 

+ 20 - 1
src/utils.js

@@ -571,7 +571,26 @@ export class Utils {
 		return ray;
 	}
     
-    
+    static getPos2d(point, camera, dom){//获取一个三维坐标对应屏幕中的二维坐标
+		 
+		var pos = point.clone().project(camera)	//比之前hotspot的计算方式写得简单  project用于3转2(求法同shader); unproject用于2转3 :new r.Vector3(e.x, e.y, -1).unproject(this.camera);
+		
+		var x,y;
+		x = (pos.x + 1) / 2 * dom.clientWidth;
+		y = (1 - (pos.y + 1) / 2) * dom.clientHeight; 
+  
+		var inSight = x <= dom.clientWidth &&  x >= 0    //是否在屏幕中   
+					&& y <= dom.clientHeight &&  y >= 0 
+	 
+	
+		return {
+			pos: new THREE.Vector2(x,y),  // 屏幕像素坐标
+			vector:  pos,   //(范围 -1 ~ 1)
+			trueSide : pos.z<1, //trueSide为false时,即使在屏幕范围内可见,也是反方向的另一个不可以被渲染的点   参见Tag.update
+			inSight : inSight	//在屏幕范围内可见
+		};
+	} 
+
     
 	static projectedRadius(radius, camera, distance, screenWidth, screenHeight){
 		if(camera instanceof THREE.OrthographicCamera){

+ 101 - 0
src/utils/Common.js

@@ -13,13 +13,114 @@ var Common = {
         })
     } 
     ,
+    
+    find : function(list, request, rank) {
+        var i = Common.filterAll(list, request);
+        return 0 === i.length ? null : (rank && rank.forEach(function(e) {
+            i = Common.stableSort(i, e)
+        }),
+        i[0])
+    }
+    
+    ,
     filterAll: function(e, t) {
         return e.filter(function (e) {
             return t.every(function (t) {
                 return t(e)
             })
         })
+    },
+    
+    
+    stableSort: function(e, t) {
+        return e.map(function(e, t) {
+            return {
+                value: e,
+                index: t
+            }
+        }).sort(function(e, i) { 
+            var n = t(e.value, i.value);
+            return 0 !== n ? n : e.index - i.index  //似乎就是加多了这一步:如果结果为0,按照原顺序
+        }).map(function(e) {
+            return e.value
+        })
+    },
+    CloneObject : function(copyObj, result, isSimpleCopy, extraReplace) {
+        //isSimpleCopy只复制最外层
+        //复制json		result的可能:普通数字或字符串、普通数组、复杂对象
+        if(!copyObj)return copyObj //0 null undefined ''
+        result = result || {};
+        if (copyObj instanceof Array) {
+            /*  if (copyObj[0]instanceof Object) {
+                //不支持含有 [[Object]] 这样二级数组里面还是复杂数据的,普通和复杂的数据混合可能也不支持
+                console.error("不支持含有 [[Object]] 这样二级数组里面还是复杂数据的...")
+            }  
+            
+            return copyObj.slice(0);*/ //如果是数组,直接复制返回(排除数组内是object 
+            return copyObj.map(e=>{
+                if(e instanceof Object){
+                    return CloneObject(e)
+                }else return e 
+            })
+           
+        }else{
+            if(copyObj.clone instanceof Function ){ //解决一部分
+                return copyObj.clone()
+            }
+        }
+        for (var key in copyObj) {
+            if (copyObj[key] instanceof Object && !isSimpleCopy)
+                result[key] = CloneObject(copyObj[key]);
+            else
+                result[key] = copyObj[key];
+            //如果是函数类同基本数据,即复制引用
+        }
+        return result;
+    }
+    ,
+    ifSame : function(object1, object2){
+        if(object1 == object2  )return true // 0 != undefined  , 0 == ''
+        else if(!object1 || !object2) return false
+        else if(object1.constructor != object2.constructor){
+            return false
+        }else if(object1 instanceof Array ) {
+            if(object1.length != object2.length)return false;
+            var _object2 = object2.slice(0);
+            
+            for(let i=0;i<object1.length;i++){ 
+                var u = _object2.find(e=>ifSame(object1[i], e));
+                if(u == void 0 && !_object2.includes(u) && !object1.includes(u))return false;
+                else{
+                    let index = _object2.indexOf(u);
+                    _object2.splice(index,1);
+                }
+            }
+            
+            return true
+        }else if(object1.equals instanceof Function ){//复杂数据仅支持这种,其他的可能卡住?
+            
+            return object1.equals(object2)
+              
+        }else if(typeof object1 == 'number' ||  typeof object1 == 'string'){
+            if(isNaN(object1) && isNaN(object2))return true
+            else return object1 == object2
+            
+        }else if(typeof object1 == "object"){
+            var keys1 = Object.keys(object1)
+            var keys2 = Object.keys(object2)
+            if(!ifSame(keys1,keys2))return false;
+            
+            for(let i in object1){
+                var same = ifSame(object1[i], object2[i]);
+                if(!same)return false
+            }
+            return true
+        }else{
+            console.log('isSame出现例外')
+        } 
+        
     }
 
+
 }    
 export default Common 

+ 1 - 1
src/utils/CursorDeal.js

@@ -6,7 +6,7 @@
 var CursorDeal = {
     priorityEvent : [//在前面的优先级高
         {"movePointcloud":'move'},
-    
+        {"measure_isIntersectSelf":'not-allowed'},
     ], 
     list:[], //当前存在的cursor状态
     currentCursorIndex:null,

+ 274 - 26
src/utils/DrawUtil.js

@@ -1,39 +1,287 @@
 
-
+ 
 import * as THREE from "../../libs/three.js/build/three.module.js";
+import math from './math';
+import {Line2} from "../../libs/three.js/lines/Line2.js";
+import {LineGeometry} from "../../libs/three.js/lines/LineGeometry.js";
+import {LineMaterial} from "../../libs/three.js/lines/LineMaterial.js";
+//画线等函数--by 许钟文
 
 
 
+var defaultColor = new THREE.Color(1,1,1);//config.applicationName == "zhiHouse" ? Colors.zhiBlue : Colors.lightGreen;
 
-var DrawUtil = {
-    getShapeGeo : 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 ) 
-        } 
-     
-        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
-        return geometry; 
-        
-    }  
-
+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"]({
+			linewidth: o.width || 1,
+			//windows无效。 似乎mac/ios上粗细有效 ? 
+			color: o.color || defaultColor,
+			transparent: o.dontAlwaysSeen ? false : true,
+			depthTest: o.dontAlwaysSeen ? true : false,
+            dashSize : o.dashSize || 0.1,
+            gapSize: o.gapSize || 0.1
+		})
+        
+		var line = new THREE.Line(e, mat);
+		line.renderOrder = o.renderOrder || 4
+        o.deshed && line.computeLineDistances()
+		//同tagStem;   //如果不加高,可能会部分被model遮住
+		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;
+		}
+		line.geometry.attributes.position.needsUpdate = true;
+		line.geometry.computeBoundingSphere();
+	}  
+	,
+     /* 
+     
+        为line创建用于检测鼠标的透明mesh,实际是个1-2段圆台。
+        由于近大远小的原因,假设没有透视畸变、创建的是等粗的圆柱的话, 所看到的线上每个位置的粗细应该和距离成反比。所以将圆柱改为根据距离线性渐变其截面半径的圆台,在最近点(相机到线的垂足)最细。如果最近点在线段上,则分成两段圆台,否则一段。
+      */
+	createBoldLine:function(points, o){ 
+		o = o || {}
+		var cylinder = o && o.cylinder;  
+		var CD = points[1].clone().sub(points[0]);
+		
+		var rotate = function(){//根据端点旋转好模型
+			cylinder.lastVector = CD;//记录本次的端点向量 
+			var AB = new THREE.Vector3(0,-1,0) 
+			var axisVec = AB.clone().cross(CD).normalize(); //得到垂直于它们的向量,也就是旋转轴
+			var rotationAngle = AB.angleTo(CD);
+			cylinder.quaternion.setFromAxisAngle( axisVec, rotationAngle ) 
+ 		} 
+		if(o && o.type == "init"){
+			cylinder = new THREE.Mesh()
+			cylinder.material = o.mat 
+			if(CD.length() == 0)return cylinder;
+			rotate()
+		}
+		
+		if(CD.length() == 0)return cylinder;
+		if(o.type != "update"){
+			var CDcenter = points[0].clone().add(points[1]).multiplyScalar(.5);
+			cylinder.position.copy(CDcenter);
+			
+			if(!cylinder.lastVector || o.type == "moveAndRotate")rotate()
+ 			else if(cylinder.lastVector &&  CD.angleTo(cylinder.lastVector)>0) rotate()//线方向改了or线反向了 重新旋转一下模型
+ 			if(config.isEdit && !objects.mainDesign.editing )return cylinder;//节省初始加载时间?
+		}
+ 
+		
+		//为了保证线段任何地方的可检测点击范围看起来一样大,更新圆台的结构(但是在镜头边缘会比中心看起来大)
+		var height = points[0].distanceTo(points[1]);
+		var standPos = o && o.standPos || objects.player.position;
+		var k = config.isMobile ? 20 : 40;
+		var dis1 = points[0].distanceTo(standPos);
+		var dis2 = points[1].distanceTo(standPos); 
+	 
+		var foot = math.getFootPoint(standPos, points[0], points[1]);//垂足
+		
+        if(o.constantBold || objects.player.mode != "panorama"){
+            var width = 0.1//0.08;
+            var pts = [new THREE.Vector2(width ,height/2),new THREE.Vector2(width ,-height/2)]  
+        }else if(foot.clone().sub(points[0]).dot( foot.clone().sub(points[1])   ) > 0){//foot不在线段上
+			var pts = [new THREE.Vector2(dis1 / k,height/2),new THREE.Vector2(dis2 / k,-height/2)]
+		}else{//在线段上的话,要在垂足这加一个节点,因它距离站位最近,而两端较远
+			var dis3 = foot.distanceTo(standPos); 
+			var len = foot.distanceTo(points[0])
+			var pts = [new THREE.Vector2(dis1 / k,height/2),  new THREE.Vector2(dis3 / k,height/2-len),  new THREE.Vector2(dis2 / k,-height/2)]
+		} 
+		cylinder.geometry && cylinder.geometry.dispose();//若不删除会占用内存
+ 		cylinder.geometry = new THREE.LatheBufferGeometry( pts, 4/* Math.min(dis1,dis2)<10?4:3 */ )  
+		cylinder.renderOrder = 2;
+		
+		return cylinder;
+	},  
+	updateBoldLine:function(cylinder, points, type, standPos, constantBold){  
+		this.createBoldLine(points,{type:type,  cylinder : cylinder, standPos:standPos, constantBold}) //type:move:平移 会改长短  , type:update根据距离和角度更新  不改长短
+	},	 
+	 
+	createFatLineMat : function(o){ 
+		var mat = new LineMaterial( { 
+			color: o.color || 0xffffff,
+			linewidth: o.width || 5, // in pixels
+			//vertexColors: THREE.VertexColors,//THREE.VertexColors,
+			resolution:  new THREE.Vector2(viewer.renderer.domElement.width,viewer.renderer.domElement.height ),// to be set by renderer, eventually
+			 
+			transparent:true, //o.dontAlwaysSeen ? false : true,
+			/* depthTest:   false,//  o.alwaysShow ? false : true,//o.dontAlwaysSeen ? true : false
+            depthWrite:false, */
+            dashSize : o.dashSize || 0.1,
+            gapSize: o.gapSize || 0.1,
+           /*  transparent:o.dontAlwaysSeen ? false : true,
+			depthTest:o.dontAlwaysSeen ? true : false
+             */
+            /* polygonOffset : true,//是否开启多边形偏移	for not cover the lineMesh
+            polygonOffsetFactor : -o.width*2.5 || -5 ,//多边形偏移因子
+            polygonOffsetUnits : -4.0,//多边形偏移单位 */  
+             
+		} ); 
+        
+        if(o.dashed)(mat.defines.USE_DASH = "") 
+        
+        var opa = 0
+        Object.defineProperty( mat, "opacity", {
+            get: function () {
+                return opa;
+            },
+            set: function(o){
+                mat.uniforms.opacity.value = opa = o; 
+            }
+        })
+        mat.opacity = o.opacity != void 0 ? o.opacity : 1;
+        
+		return 	mat;			
+	},
+    
+    /* 
+        创建可以改变粗细的线。 
+     */
+	createFatLine : function(posArr, o){  
+		var geometry = new LineGeometry();
+		geometry.setPositions( posArr );
+		geometry.setColors( o.color || [1,1,1]);
 
+		var matLine = o.material || this.createFatLineMat(o);
+		var line = new Line2( geometry, matLine );
+		//line.computeLineDistances();
+        
+        if(line.material.defines.USE_DASH != void 0){
+            //line.geometry.verticesNeedUpdate = true;
+            //line.geometry.computeBoundingSphere();
+            line.computeLineDistances(); 
+        }
+        
+		line.scale.set( 1, 1, 1 );
+		line.renderOrder = 2;
+		return line;
 
+	},
+	moveFatLine: function(line, posArr){
+		var geometry = line.geometry;
+		geometry.setPositions( posArr );  
+        
+        
+        if(line.material.defines.USE_DASH != void 0){
+            //line.geometry.verticesNeedUpdate = true;
+            //line.geometry.computeBoundingSphere();
+            line.computeLineDistances(); 
+        }
+        
+        
+        
+	}
 }
 
- 
+var MeshDraw = { 
+    
+    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 matrix = new THREE.Matrix4();//将竖直的面变为水平
+		matrix.set(//z = y 
+			1, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 1, 0, 0,
+			0, 0, 0, 1 
+		)
+		geometry.applyMatrix(matrix) */
+		//geometry.computeVertexNormals();//对于光照需要的是点法线
+        
+        
+        
+		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])
+			, i = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1])
+			, 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)) 
+		return function(){
+			return g
+		}	 
+	}(), 
+	getPlaneGeo : function(A,B,C,D){
+		var geo = this.getUnPosPlaneGeo().clone();
+		var pos = new Float32Array([
+			A.x, A.y, A.z, 
+			B.x, B.y, B.z, 
+			C.x, C.y, C.z, 
+			D.x, D.y, D.z  
+		])
+		geo.addAttribute("position", new THREE.BufferAttribute(pos, 3))  
+		geo.computeVertexNormals()
+		geo.computeBoundingSphere() //for raycaster
+		return geo;
+	}, 
+	drawPlane : function(A,B,C,D, material){   
+		var wall = new THREE.Mesh(this.getPlaneGeo(A,B,C,D), material); 
+		return wall;
+	  
+	}, 
+	movePlane: function(mesh, A,B,C,D){
+		var pos = new Float32Array([
+			A.x, A.y, A.z, 
+			B.x, B.y, B.z, 
+			C.x, C.y, C.z, 
+			D.x, D.y, D.z  
+		])
+		mesh.geometry.addAttribute("position", new THREE.BufferAttribute(pos, 3)) 
+		mesh.geometry.computeBoundingSphere()//for checkIntersect
+	}  
+    
+    
+    
+} 
 
-export default DrawUtil
+export {LineDraw, MeshDraw} ;

+ 5 - 4
src/utils/Magnifier.js

@@ -45,20 +45,21 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
             side: THREE.DoubleSide , 
             map: this.renderTarget.texture ,
             transparent:true,
-            //depthTest: !1,
+            depthTest: !1,
             //depthWrite: !1,
         }))
         this.overlayMesh = new THREE.Mesh(circleGeo, new THREE.MeshBasicMaterial({
             side: THREE.DoubleSide , 
-            map:texLoader.load('../resources/textures/crosshair.png') ,
+            map:texLoader.load(Potree.config.urls.localTextures+'crosshair.png') ,
             transparent:true,
             depthTest: !1,
             //depthWrite: !1,
         }))
         this.add(this.mesh)
         this.add(this.overlayMesh)
+        this.position.set(-1000,-1000,-100000)//令它看不见
         this.mesh.renderOrder = 10;
-        this.overlayMesh.renderOrder = 10;
+        this.overlayMesh.renderOrder = 11;
         this.aimPos
 
         inputHandler.addInputListener(this)
@@ -138,7 +139,7 @@ export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
          
 
         this.aimPos =  aimPos
-
+ 
         if(!this.dontRender){
             this.waitRender = true
         }

Разлика између датотеке није приказан због своје велике величине
+ 1130 - 643
src/utils/Measure.js


+ 156 - 169
src/utils/MeasuringTool.js

@@ -1,17 +1,18 @@
 
 import * as THREE from "../../libs/three.js/build/three.module.js";
 import {Measure} from "./Measure.js";
-import {Utils} from "../utils.js";
-import {CameraMode} from "../defines.js";
+import {Utils} from "../utils.js"; 
+import math from "./math.js";
+import {CameraMode,MOUSE} from "../defines.js";
 import { EventDispatcher } from "../EventDispatcher.js";
-
+ 
 function updateAzimuth(viewer, measure){
-
+    if(!measure.showAzimuth)return
 	const azimuth = measure.azimuth;
 
 	const isOkay = measure.points.length === 2;
 
-	azimuth.node.visible = isOkay && measure.showAzimuth;
+	azimuth.node.visible = isOkay  
 
 	if(!azimuth.node.visible){
 		return;
@@ -134,26 +135,30 @@ export class MeasuringTool extends EventDispatcher{
 		});
 
 		this.showLabels = true;
-		this.scene = new THREE.Scene();
+        this.scene = new THREE.Scene();
 		this.scene.name = 'scene_measurement';
-		this.light = new THREE.PointLight(0xffffff, 1.0);
-		this.scene.add(this.light);
-
+		//this.light = new THREE.PointLight(0xffffff, 1.0);
+		//this.scene.add(this.light);  
 		this.viewer.inputHandler.registerInteractiveScene(this.scene);
-
-		this.onRemove = (e) => { this.scene.remove(e.measurement);};
+        //this.scene = viewer.overlay//
+        
+        
+		this.onRemove = (e) => { e.measurement.dispose()/* this.scene.remove(e.measurement); */};
 		this.onAdd = e => {this.scene.add(e.measurement);};
 
 		for(let measurement of viewer.scene.measurements){
 			this.onAdd({measurement: measurement});
 		}
-
-		viewer.addEventListener("update", this.update.bind(this));
+		viewer.addEventListener("camera_changed", this.update.bind(this));
+		//viewer.addEventListener("update", this.update.bind(this));
 		viewer.addEventListener("render.pass.perspective_overlay", this.render.bind(this));
 		viewer.addEventListener("scene_changed", this.onSceneChange.bind(this));
 
 		viewer.scene.addEventListener('measurement_added', this.onAdd);
 		viewer.scene.addEventListener('measurement_removed', this.onRemove);
+        
+        viewer.addEventListener('resize',this.setSize.bind(this))
+        
 	}
 
 	onSceneChange(e){
@@ -167,14 +172,11 @@ export class MeasuringTool extends EventDispatcher{
 	}
 
 	startInsertion (args = {}) {
+        
+        
 		let domElement = this.viewer.renderer.domElement;
 
-		let measure = new Measure();
-
-		this.dispatchEvent({
-			type: 'start_inserting_measurement',
-			measure: measure
-		});
+		
 
 		const pick = (defaul, alternative) => {
 			if(defaul != null){
@@ -184,56 +186,91 @@ export class MeasuringTool extends EventDispatcher{
 			}
 		};
 
-		measure.showDistances = (args.showDistances === null) ? true : args.showDistances;
+		args.showDistances = (args.showDistances === null) ? true : args.showDistances;
+
+		args.showArea = pick(args.showArea, false);
+		args.showAngles = pick(args.showAngles, false);
+		args.showCoordinates = pick(args.showCoordinates, false);
+		args.showHeight = pick(args.showHeight, false);
+		args.showCircle = pick(args.showCircle, false);
+		args.showAzimuth = pick(args.showAzimuth, false);
+		args.showEdges = pick(args.showEdges, true);
+		args.closed = pick(args.closed, false);
+		args.maxMarkers = pick(args.maxMarkers, Infinity);
+        args.direction = args.direction//add
+		args.type = args.type    /*  || 'Measurement'; */
+        args.showGuideLine = pick(args.showGuideLine, false);  
+        args.isRect = pick(args.isRect, false);
+        
 
-		measure.showArea = pick(args.showArea, false);
-		measure.showAngles = pick(args.showAngles, false);
-		measure.showCoordinates = pick(args.showCoordinates, false);
-		measure.showHeight = pick(args.showHeight, false);
-		measure.showCircle = pick(args.showCircle, false);
-		measure.showAzimuth = pick(args.showAzimuth, false);
-		measure.showEdges = pick(args.showEdges, true);
-		measure.closed = pick(args.closed, false);
-		measure.maxMarkers = pick(args.maxMarkers, Infinity);
 
-		measure.name = args.name || 'Measurement';
 
-		this.scene.add(measure);
+        let measure = new Measure(args);
+        /* if(this.editingMeasure){
+            this.editingMeasure.dispatchEvent({type:"endEdit"}) 
+        }
+        this.editingMeasure = measure */
+        
+        
+		this.dispatchEvent({
+			type: 'start_inserting_measurement',
+			measure: measure
+		});
 
-		let cancel = {
-			//removeLastMarker: measure.maxMarkers > 3,
-			callback: null
-		};
+    
+		this.scene.add(measure);
+         
+		 
 
 		let endDragFun = (e) => {
-			if (e.button === THREE.MOUSE.LEFT) {
+           
+			if (e.drag.mouse == MOUSE.LEFT) {
 				if (measure.points.length >= measure.maxMarkers) {
-                    cancel.callback();
+                    end({complete:true});
 				}else{
-                    this.viewer.inputHandler.startDragging(measure.addMarker(measure.points[measure.points.length - 1].position.clone()),
-                        {endDragFun} 
-                    );    
+                    var marker = measure.addMarker(measure.points[measure.points.length - 1].position.clone())
+                    if(args.isRect && measure.spheres.length == 3){
+                        measure.addMarker(measure.points[0].position.clone())
+                    }
+                    setTimeout(()=>{//等 drag=null之后
+                        this.viewer.inputHandler.startDragging(marker,
+                            {endDragFun} 
+                        ); 
+                    },1)    
                 } 
 				 
-			} else if (e.button === THREE.MOUSE.RIGHT) {
-				cancel.callback();
+			} else if (e.drag.mouse === MOUSE.RIGHT) {
+				if(e.pressDistance < 2 )end();//非拖拽的话
+                else setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag
+                    this.viewer.inputHandler.startDragging(e.drag.object,
+                        {endDragFun} 
+                    ); 
+                },1) 
 			}
 		};
 
-		cancel.callback = e => {
-            if(args.minMarkers != void 0  && measure.spheres.length<args.minMarkers){
-                this.viewer.scene.removeMeasurement(measure)
-            }else if (measure.spheres.length > 3) {
+		let end = (o={}) => {
+            if(args.minMarkers != void 0){
+                if(!o.complete && measure.spheres.length<=args.minMarkers){
+                    this.viewer.scene.removeMeasurement(measure)
+                } 
+            }
+            if (!o.complete && measure.spheres.length > 3) {
 				measure.removeMarker(measure.points.length - 1);
 			}
+            
+            //this.editingMeasure = null
 			//domElement.removeEventListener('mouseup', insertionCallback, false);
-			//this.viewer.removeEventListener('cancel_insertions', cancel.callback);
+			this.viewer.removeEventListener('cancel_insertions', end);
 		};
 
-		if (measure.maxMarkers > 1) {
-			//this.viewer.addEventListener('cancel_insertions', cancel.callback);
+        //measure.addEventListener("endEdit", end)
+
+
+		//if (measure.maxMarkers > 1) {
+			this.viewer.addEventListener('cancel_insertions', end);
 			//domElement.addEventListener('mouseup', insertionCallback, false);
-		}
+		//}
 
 		/* measure.addMarker(new THREE.Vector3(0, 0, 0));
 		this.viewer.inputHandler.startDragging(
@@ -245,13 +282,37 @@ export class MeasuringTool extends EventDispatcher{
             endDragFun 
         });
          
-            
+        
 
 		this.viewer.scene.addMeasurement(measure);
-
+        
 		return measure;
 	}
 	
+    
+    updateLabelZIndex(group){//[{labels:[]},{}] 顺序按照z-index低到高
+        
+        group.forEach((e,i)=>{
+            e.base = group[i-1] ? group[i-1].base + group[i-1].labels.length : 0
+         
+            var labels = e.labels.sort((a,b)=>{
+                return b.pos2d.z - a.pos2d.z
+            }) 
+            labels.forEach((label,index)=>{
+                $(label.elem).css('z-index', e.base+index) 
+            }) 
+        }) 
+        
+    }
+    
+    setSize(e){ 
+        if(Measure.lineMats){
+            for(var m in Measure.lineMats){
+                Measure.lineMats[m].resolution.set(e.canvasWidth, e.canvasHeight);
+            }  
+        } 
+    }
+    
 	update(){
 		let camera = this.viewer.scene.getActiveCamera();
 		let domElement = this.renderer.domElement;
@@ -261,159 +322,83 @@ export class MeasuringTool extends EventDispatcher{
 		let clientWidth = renderAreaSize.width;
 		let clientHeight = renderAreaSize.height;
 
-		this.light.position.copy(camera.position);
+		//this.light.position.copy(camera.position);
 
 		// make size independant of distance
+        let mainLabels = [], subLabels = [];
+        
+        
 		for (let measure of measurements) {
 			measure.lengthUnit = this.viewer.lengthUnit;
 			measure.lengthUnitDisplay = this.viewer.lengthUnitDisplay;
-			measure.update();
+			//measure.update();
 
 			updateAzimuth(this.viewer, measure);
 
 			// spheres
-			for(let sphere of measure.spheres){
-				let distance = camera.position.distanceTo(sphere.getWorldPosition(new THREE.Vector3()));
-				let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
-				let scale = (15 / pr);
-				sphere.scale.set(scale, scale, scale);
-			}
+            
+            for(let sphere of measure.spheres){
+                measure.updateSphereSize(sphere)
+            }
+			
 
 			// labels
 			let labels = measure.edgeLabels.concat(measure.angleLabels);
-			for(let label of labels){
-				let distance = camera.position.distanceTo(label.getWorldPosition(new THREE.Vector3()));
-				let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
-				let scale = (70 / pr);
-
-				if(Potree.debug.scale){
-					scale = (Potree.debug.scale / pr);
-				}
-
-				label.scale.set(scale, scale, scale);
+			for(let label of labels){ 
+                label.update()
+                if(label.elem.hasClass('sub')){
+                    subLabels.push(label)
+                }else{
+                    mainLabels.push(label)
+                }
 			}
 
 			// coordinate labels
-			for (let j = 0; j < measure.coordinateLabels.length; j++) {
-				let label = measure.coordinateLabels[j];
-				let sphere = measure.spheres[j];
-
-				let distance = camera.position.distanceTo(sphere.getWorldPosition(new THREE.Vector3()));
-
-				let screenPos = sphere.getWorldPosition(new THREE.Vector3()).clone().project(camera);
-				screenPos.x = Math.round((screenPos.x + 1) * clientWidth / 2);
-				screenPos.y = Math.round((-screenPos.y + 1) * clientHeight / 2);
-				screenPos.z = 0;
-				screenPos.y -= 30;
-
-				let labelPos = new THREE.Vector3( 
-					(screenPos.x / clientWidth) * 2 - 1, 
-					-(screenPos.y / clientHeight) * 2 + 1, 
-					0.5 );
-				labelPos.unproject(camera);
-				if(this.viewer.scene.cameraMode == CameraMode.PERSPECTIVE) {
-					let direction = labelPos.sub(camera.position).normalize();
-					labelPos = new THREE.Vector3().addVectors(
-						camera.position, direction.multiplyScalar(distance));
-
-				}
-				label.position.copy(labelPos);
-				let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
-				let scale = (70 / pr);
-				label.scale.set(scale, scale, scale);
+			for (let j = 0; j < measure.coordinateLabels.length; j++) { 
+				let label = measure.coordinateLabels[j]; 
+                label.update() 
+                mainLabels.push(label)
+			} 
+ 
+
+			if(measure.showArea){ // area label
+				let label = measure.areaLabel; 
+                label.update()
+                mainLabels.push(label)
 			}
 
-			// height label
-			if (measure.showHeight) {
-				let label = measure.heightLabel;
-
-				{
-					let distance = label.position.distanceTo(camera.position);
-					let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
-					let scale = (70 / pr);
-					label.scale.set(scale, scale, scale);
-				}
-
-				{ // height edge
-					let edge = measure.heightEdge;
-
-					let sorted = measure.points.slice().sort((a, b) => a.position.z - b.position.z);
-					let lowPoint = sorted[0].position.clone();
-					let highPoint = sorted[sorted.length - 1].position.clone();
-					let min = lowPoint.z;
-					let max = highPoint.z;
-
-					let start = new THREE.Vector3(highPoint.x, highPoint.y, min);
-					let end = new THREE.Vector3(highPoint.x, highPoint.y, max);
-
-					let lowScreen = lowPoint.clone().project(camera);
-					let startScreen = start.clone().project(camera);
-					let endScreen = end.clone().project(camera);
-
-					let toPixelCoordinates = v => {
-						let r = v.clone().addScalar(1).divideScalar(2);
-						r.x = r.x * clientWidth;
-						r.y = r.y * clientHeight;
-						r.z = 0;
-
-						return r;
-					};
-
-					let lowEL = toPixelCoordinates(lowScreen);
-					let startEL = toPixelCoordinates(startScreen);
-					let endEL = toPixelCoordinates(endScreen);
-
-					let lToS = lowEL.distanceTo(startEL);
-					let sToE = startEL.distanceTo(endEL);
-
-					edge.geometry.lineDistances = [0, lToS, lToS, lToS + sToE];
-					edge.geometry.lineDistancesNeedUpdate = true;
-
-					edge.material.dashSize = 10;
-					edge.material.gapSize = 10;
-				}
-			}
-
-			{ // area label
-				let label = measure.areaLabel;
-				let distance = label.position.distanceTo(camera.position);
-				let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
-
-				let scale = (70 / pr);
-				label.scale.set(scale, scale, scale);
-			}
-
-			{ // radius label
+			/* if(measure.showCircle){ // radius label
 				let label = measure.circleRadiusLabel;
 				let distance = label.position.distanceTo(camera.position);
 				let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
 
 				let scale = (70 / pr);
 				label.scale.set(scale, scale, scale);
-			}
+			} */
 
 			{ // edges
-				const materials = [
+				/* const materials = [
 					measure.circleRadiusLine.material,
 					...measure.edges.map( (e) => e.material),
-					measure.heightEdge.material,
+					//measure.heightEdge.material,
+                    measure.guideLine.material,
 					measure.circleLine.material,
-				];
+				]; 
 
 				for(const material of materials){
 					material.resolution.set(clientWidth, clientHeight);
-				}
+				}*/
+                
+                
+                
+                
 			}
 
 			if(!this.showLabels){
 
 				const labels = [
-					...measure.sphereLabels, 
-					...measure.edgeLabels, 
-					...measure.angleLabels, 
-					...measure.coordinateLabels,
-					measure.heightLabel,
-					measure.areaLabel,
+					...measure.sphereLabels,  
+					...measure.angleLabels,  
 					measure.circleRadiusLabel,
 				];
 
@@ -422,6 +407,8 @@ export class MeasuringTool extends EventDispatcher{
 				}
 			}
 		}
+        this.updateLabelZIndex([{labels:subLabels},{labels:mainLabels}])
+        
 	}
 
 	render(o={}){

+ 57 - 42
src/utils/math.js

@@ -2,7 +2,26 @@
 import * as THREE from "../../libs/three.js/build/three.module.js";
 
 var math = {
+    convertVector : {
+        ZupToYup: function(e){//navvis -> 4dkk
+            return new THREE.Vector3(e.x,e.z,-e.y)
+        },
+        YupToZup: function(e){//4dkk -> navvis
+            return new THREE.Vector3(e.x,-e.z,e.y)
+        },
+        
+        
+    },
+    
 	 
+    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)))
+    },
+    invertVisionQuaternion : function(e) {//反转给算法部
+        var a = e.clone().multiply((new THREE.Quaternion).setFromAxisAngle(new THREE.Vector3(0,1,0), THREE.Math.degToRad(-90)))
+        return new THREE.Quaternion(a.x,-a.z,a.y,a.w)
+    },
+    //------------
     
     getVec2Angle : function(dir1,dir2){ 
         return Math.acos( THREE.Math.clamp(this.getVec2Cos(dir1,dir2), -1,1) )  
@@ -146,6 +165,7 @@ var math = {
 			p1.y += mainDesign.meshGroup.position.y;
 			p2.y += mainDesign.meshGroup.position.y;
 		} */
+        if(p1.equals(p2))return p1.clone()
 		var op1 = oldPos.clone().sub(p1); 
 		var p1p2 = p1.clone().sub(p2)
 		var p1p2Len = p1p2.length()
@@ -286,12 +306,17 @@ var math = {
 		  }
 		}  
     },
-
-	getNormal : function(line2d){//获取二维法向量 方向向内
-		var x,y;//要求的向量
+     
+	getNormal2d : function(o={} ){//获取二维法向量 方向向内
+		var x,y, x1,y1; 
 		//line2d的向量
-		var x1 = line2d.points[1].x - line2d.points[0].x;
-		var y1 = line2d.points[1].y - line2d.points[0].y;
+        if(o.vec){
+            x1 = o.vec.x;  y1 = o.vec.y
+        }else{
+            x1 = o.p1.x - o.p2.x;
+            y1 = o.p1.y - o.p2.y;
+        }
+		
 		//假设法向量的x或y固定为1或-1
 		if(y1 != 0){
 			x = 1;
@@ -314,31 +339,7 @@ var math = {
 		} 
 		return new THREE.Vector2(x, y).normalize();
  	},
-    /* getLineIntersect : function(o){ //https://www.cnblogs.com/DHUtoBUAA/p/8057056.html //求二维直线交点(不是线段!)
-        var lines = [{A:null,B:null,C:null },{A:null,B:null,C:null }];
-         
-        lines.forEach((line, index)=>{
-            var p1 = o[index].p1;
-            var p2 = o[index].vec ? new THREE.Vector2().copy(p1).add(o[index].vec) : o[index].p2;
-            line.A = p2.y - p1.y;
-            line.B = p1.x - p2.x;
-            line.C = p2.x * p1.y - p2.y * p1.x;
-            
-        })
-         
-        var D = lines[0].A * lines[1].B - lines[1].A * lines[0].B;//A1 * B2 - A2 * B1 
-        //当D = -1的时候表示两条直线垂直,当D = 0的时候表示两条直线平行或共线
-        if(D == 0){
-            return null;
-        }else{
-            var x = (lines[0].B * lines[1].C - lines[1].B * lines[0].C) / D;
-            var y = (lines[0].C * lines[1].A - lines[1].C * lines[0].A) / D;
-            return new THREE.Vector2(x,y)
-            
-        }
-    
-    }  
-    ,*/
+     
     getQuaBetween2Vector:function(oriVec, newVec, upVec){ //获取从oriVec旋转到newVec可以应用的quaternion
         var angle = oriVec.angleTo(newVec);
         var axis = oriVec.clone().cross( newVec).normalize();//两个up之间
@@ -347,7 +348,18 @@ var math = {
         }
         return new THREE.Quaternion().setFromAxisAngle( axis, angle );
     }
+    /* ,
+    getQuaBetween2Vector2 : function(oriVec, newVec   ){//not camera
+        var _ = (new THREE.Matrix4).lookAt( oriVec, new THREE.Vector3, new THREE.Vector3(0,1,0))
+        var aimQua = (new THREE.Quaternion).setFromRotationMatrix(_)
+        var _2 = (new THREE.Matrix4).lookAt( newVec, new THREE.Vector3, new THREE.Vector3(0,1,0))
+        var aimQua2 = (new THREE.Quaternion).setFromRotationMatrix(_2)
+        
+        return aimQua2.multiply(aimQua.clone().inverse()) 
+        
+    } */
     
+        
     ,
     
     getScaleForConstantSize : function(){ //获得规定二维大小的mesh的scale值。可以避免因camera的projection造成的mesh视觉大小改变。  来源:tag.updateDisc
@@ -361,9 +373,9 @@ var math = {
                 //maxSize : mesh要表现的最大像素宽度;   nearBound: 最近距离,若比nearBound近,则使用maxSize
             }
             i.copy(op.position).project(op.camera),  //tag中心在屏幕上的二维坐标
-            o.set($('#player').width() / 2, $('#player').height() / 2, 1).multiply(i), //转化成px   -w/2 到 w/2的范围
+            o.set(op.dom.clientWidth / 2, op.dom.clientHeight / 2, 1).multiply(i), //转化成px   -w/2 到 w/2的范围
             l.set(w / 2, 0, 0).add(o),  //加上tag宽度的一半
-            c.set(2 / $('#player').width(), 2 / $('#player').height(), 1).multiply(l), //再转回  -1 到 1的范围
+            c.set(2 / op.dom.clientWidth, 2 / op.dom.clientHeight, 1).multiply(l), //再转回  -1 到 1的范围
             h.copy(c).unproject(op.camera);//再转成三维坐标,求得tag边缘的位置
             var g = h.distanceTo(op.position)//就能得到tag的三维半径
         
@@ -483,16 +495,19 @@ var math = {
          return dir;
     },
     getDirByLonLat : function(lon,lat){
-            var dir = new THREE.Vector3
-            var phi = THREE.Math.degToRad(90 - lat);
-            var theta = THREE.Math.degToRad(lon);
-            dir.x = Math.sin(phi) * Math.cos(theta);
-            dir.y = Math.cos(phi);
-            dir.z = Math.sin(phi) * Math.sin(theta);   
-            return dir
-        }
-        
-    //0,0 => (1,0,0)     270=>(0,0,-1)
+        var dir = new THREE.Vector3
+        var phi = THREE.Math.degToRad(90 - lat);
+        var theta = THREE.Math.degToRad(lon);
+        dir.x = Math.sin(phi) * Math.cos(theta);
+        dir.y = Math.cos(phi);
+        dir.z = Math.sin(phi) * Math.sin(theta);   
+        return dir
+    } //0,0 => (1,0,0)     270=>(0,0,-1)
+    ,    
+    projectPointAtPlane:function(o={}){//获取一个点在一个面上的投影 {facePoints:[a,b,c], point:}
+        var plane = new THREE.Plane().setFromCoplanarPoints(...o.facePoints)
+        return plane.projectPoint(o.point, new THREE.Vector3() )
+    }
     
 };
 

+ 2 - 2
src/viewer/Axis.js

@@ -1,7 +1,7 @@
 
 
 import * as THREE from "../../libs/three.js/build/three.module.js"; 
-import DrawUtil from '../utils/DrawUtil'
+import {MeshDraw} from '../utils/DrawUtil'
  
 /*  
 
@@ -25,7 +25,7 @@ export default class Axis extends THREE.Object3D {// 坐标轴
         this.scale.set(2,2,2)
     }
     getGeometry(){
-        var geometry = DrawUtil.getShapeGeo([new THREE.Vector2(2,0), new THREE.Vector2(1,-2), new THREE.Vector2(1,-1), new THREE.Vector2(0,-1),
+        var geometry = MeshDraw.getShapeGeo([new THREE.Vector2(2,0), new THREE.Vector2(1,-2), new THREE.Vector2(1,-1), new THREE.Vector2(0,-1),
             new THREE.Vector2(0,1), new THREE.Vector2(1,1), new THREE.Vector2(1,2)])
         this.geometry = geometry
         

+ 17 - 18
src/viewer/EDLRenderer.js

@@ -17,6 +17,9 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 		this.gl = viewer.renderer.getContext();
 
 		this.shadowMap = new PointCloudSM(this.viewer.pRenderer);
+        
+        viewer.addEventListener('resize',this.resize.bind(this))
+         
 	}
 
 	initEDL(){
@@ -45,17 +48,15 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 		});
 	};
 
-	resize(width, height){
-		if(this.screenshot){
+	resize(e){
+        //width, height
+		/* if(this.screenshot){
 			width = this.screenshot.target.width;
 			height = this.screenshot.target.height;
-		}
+		} */
 
-		this.rtEDL.setSize(width , height);
-		this.rtRegular.setSize(width , height);
-        
-        
-        
+		this.rtEDL.setSize(e.canvasWidth, e.canvasHeight);
+		this.rtRegular.setSize(e.canvasWidth, e.canvasHeight);
         
 	}
 
@@ -212,7 +213,7 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 
 		viewer.dispatchEvent({type: "render.pass.begin",viewer: viewer});
 	
-		params.target || this.resize(width, height);//因为resize WebGLRenderTarget会清屏,所以一般不要resize。  但为何navvis不会?
+		//params.target || this.resize(width, height);//因为resize WebGLRenderTarget会清屏,所以一般不要resize。  但为何navvis不会?
                                                     //所以最好为放大镜准备一个rtEDL
 		const visiblePointClouds = viewer.scene.pointclouds.filter(pc => pc.visible);
 
@@ -370,13 +371,15 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
             
         }
         
-		viewer.dispatchEvent({type: "render.pass.scene", viewer: viewer});
         
         
+        viewer.dispatchEvent({type: "render.pass.scene", viewer: viewer});
         
         
-        viewer.renderer.render(viewer.scene.sceneOverlay, camera);// add   透明贴图层
-
+        
+        if(!params.target){
+            viewer.renderer.render(viewer.scene.sceneOverlay, camera);// add   透明贴图层  reticule marker 不能遮住测量线
+        }
 
 
 		viewer.renderer.clearDepth();
@@ -386,14 +389,10 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
        
          
         
-        if(!params.target){
-            
-            
-            viewer.renderer.render(viewer.overlay, camera);//从 viewer.renderDefault搬过来,为了reticule不遮住测量线
-            
+        if(!params.target){ 
             //测量线
             viewer.dispatchEvent({type: "render.pass.perspective_overlay", viewer: viewer, camera});
-
+            viewer.renderer.render(viewer.overlay, camera); //magnifier 遮住测量线
             
         } 
         

+ 25 - 11
src/viewer/HQSplatRenderer.js

@@ -10,6 +10,9 @@ import {Utils} from "../utils.js";
 
 export class HQSplatRenderer{
 	
+    
+  //rtAttribute  估计需要给magnifer复制一份 
+    
 	constructor(viewer){
 		this.viewer = viewer;
 
@@ -22,6 +25,8 @@ export class HQSplatRenderer{
 		this.gl = viewer.renderer.getContext();
 
 		this.initialized = false;
+        
+        viewer.addEventListener('resize',this.resize.bind(this))
 	}
 
 	init(){
@@ -58,9 +63,9 @@ export class HQSplatRenderer{
 		this.initialized = true;
 	};
 
-	resize(width, height){
-		this.rtDepth.setSize(width, height);
-		this.rtAttribute.setSize(width, height);
+	resize(e/* width, height */){
+		this.rtDepth.setSize(e.canvasWidth, e.canvasHeight);
+		this.rtAttribute.setSize(e.canvasWidth, e.canvasHeight);
 	}
 
 	clearTargets(params){
@@ -115,11 +120,11 @@ export class HQSplatRenderer{
 		const camera = params.camera ? params.camera : viewer.scene.getActiveCamera(); 
 		const {width, height} = params.width ? params : this.viewer.renderer.getSize(new THREE.Vector2());
 
-
+        viewer.renderer.setRenderTarget(params.target||null);
 
 		viewer.dispatchEvent({type: "render.pass.begin",viewer: viewer});
 
-		params.target || this.resize(width, height);
+		//params.target || this.resize(width, height);
 
 		const visiblePointClouds = viewer.scene.pointclouds.filter(pc => pc.visible);
 		const originalMaterials = new Map();
@@ -179,7 +184,7 @@ export class HQSplatRenderer{
 				pointcloud.material = depthMaterial;
 			}
 			
-			viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, this.rtDepth, {
+			viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, (params.rtEDL || this.rtDepth), {
 				clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
 			});
 		}
@@ -248,7 +253,7 @@ export class HQSplatRenderer{
 			
 			let gl = this.gl;
 
-			viewer.renderer.setRenderTarget(null);
+			//viewer.renderer.setRenderTarget(null);
 			viewer.pRenderer.render(viewer.scene.scenePointCloud, camera, this.rtAttribute, {
 				clipSpheres: viewer.scene.volumes.filter(v => (v instanceof SphereVolume)),
 				//material: this.attributeMaterial,
@@ -262,7 +267,13 @@ export class HQSplatRenderer{
 			pointcloud.material = material;
 		}
 
-		viewer.renderer.setRenderTarget(null);
+
+        
+
+		
+        
+         
+        
 		if(viewer.background === "skybox"){
 			viewer.renderer.setClearColor(0x000000, 0);
 			viewer.renderer.clear();
@@ -290,6 +301,9 @@ export class HQSplatRenderer{
 			viewer.renderer.clear();
 		}
 
+
+          
+
 		{ // NORMALIZATION PASS
 			let normalizationMaterial = this.useEDL ? this.normalizationEDLMaterial : this.normalizationMaterial;
 
@@ -298,7 +312,7 @@ export class HQSplatRenderer{
 				normalizationMaterial.uniforms.radius.value = viewer.edlRadius;
 				normalizationMaterial.uniforms.screenWidth.value = width;
 				normalizationMaterial.uniforms.screenHeight.value = height;
-				normalizationMaterial.uniforms.uEDLMap.value = this.rtDepth.texture;
+				normalizationMaterial.uniforms.uEDLMap.value = (params.rtEDL || this.rtDepth).texture;
 			}
 
 			normalizationMaterial.uniforms.uWeightMap.value = this.rtAttribute.texture;
@@ -318,10 +332,10 @@ export class HQSplatRenderer{
 
 		viewer.transformationTool.update();
         if(!params.target){
-            viewer.renderer.render(viewer.overlay, camera);//从 viewer.renderDefault搬过来,为了reticule不遮住测量线
             
             //测量线
             viewer.dispatchEvent({type: "render.pass.perspective_overlay",viewer: viewer, camera});
+            viewer.renderer.render(viewer.overlay, camera);//从 viewer.renderDefault搬过来,为了reticule不遮住测量线
         }
 		viewer.renderer.render(viewer.controls.sceneControls, camera);
 		viewer.renderer.render(viewer.clippingTool.sceneVolume, camera);
@@ -334,7 +348,7 @@ export class HQSplatRenderer{
 		viewer.renderer.setViewport(0, 0, width, height);
 		
 		viewer.dispatchEvent({type: "render.pass.end",viewer: viewer});
-
+        viewer.renderer.setRenderTarget(null) 
 	}
 
 }

+ 13 - 9
src/viewer/LoadProject.js

@@ -88,10 +88,11 @@ function loadMeasurement(viewer, data){
 	if(duplicate){
 		return;
 	}
+    
 
-	const measure = new Measure();
+	const measure = new Measure(data);
 
-	measure.uuid = data.uuid;
+	/* measure.uuid = data.uuid;
 	measure.name = data.name;
 	measure.showDistances = data.showDistances;
 	measure.showCoordinates = data.showCoordinates;
@@ -101,16 +102,19 @@ function loadMeasurement(viewer, data){
 	measure.showHeight = data.showHeight;
 	measure.showCircle = data.showCircle;
 	measure.showAzimuth = data.showAzimuth;
-	measure.showEdges = data.showEdges;
+	measure.showEdges = data.showEdges; */
 	// color
 
 	for(const point of data.points){
 		const pos = new THREE.Vector3(...point);
 		measure.addMarker(pos);
+        
 	}
-
+    measure.dragChange(new THREE.Vector3(...data.points[data.points.length-1]), data.points.length-1); 
+    //measure.update()
 	viewer.scene.addMeasurement(measure);
-
+    measure.setSelected(false )
+    if(measure.guideLine)measure.guideLine.visible = false
 }
 
 function loadVolume(viewer, data){
@@ -325,11 +329,11 @@ export async function loadProject(viewer, data){
 
 	loadView(viewer, data.view);
 
-	const pointcloudPromises = [];
+	/* const pointcloudPromises = [];
 	for(const pointcloud of data.pointclouds){
 		const promise = loadPointCloud(viewer, pointcloud);
 		pointcloudPromises.push(promise);
-	}
+	} */
 
 	for(const measure of data.measurements){
 		loadMeasurement(viewer, measure);
@@ -360,7 +364,7 @@ export async function loadProject(viewer, data){
 	// need to load at least one point cloud that defines the scene projection,
 	// before we can load stuff in other projections such as geopackages
 	//await Promise.any(pointcloudPromises); // (not yet supported)
-	Utils.waitAny(pointcloudPromises).then( () => {
+	/* Utils.waitAny(pointcloudPromises).then( () => {
 		if(data.geopackages){
 			for(const geopackage of data.geopackages){
 				loadGeopackage(viewer, geopackage);
@@ -368,5 +372,5 @@ export async function loadProject(viewer, data){
 		}
 	});
 
-	await Promise.all(pointcloudPromises);
+	await Promise.all(pointcloudPromises); */
 }

+ 2 - 5
src/viewer/PotreeRenderer.js

@@ -127,14 +127,11 @@ export class PotreeRenderer {
 		viewer.transformationTool.update();
         
         
-        if(!params.target){
-            
-            
-            viewer.renderer.render(viewer.overlay, camera);//从 viewer.renderDefault搬过来,为了reticule不遮住测量线
+        if(!params.target){ 
             
             //测量线
             viewer.dispatchEvent({type: "render.pass.perspective_overlay", viewer: viewer, camera});
-
+            viewer.renderer.render(viewer.overlay, camera);//从 viewer.renderDefault搬过来,为了reticule不遮住测量线
             
         } 
         

+ 1 - 1
src/viewer/PropertyPanels/AreaPanel.js

@@ -41,6 +41,6 @@ export class AreaPanel extends MeasurePanel{
 		elCoordiantesContainer.append(this.createCoordinatesTable(this.measurement.points.map(p => p.position)));
 
 		let elArea = this.elContent.find(`#measurement_area`);
-		elArea.html(this.measurement.getArea().toFixed(3));
+		elArea.html(this.measurement.area.toFixed(3));
 	}
 };

+ 2 - 2
src/viewer/PropertyPanels/PropertiesPanel.js

@@ -249,7 +249,7 @@ export class PropertiesPanel{
 			sldPointSize.slider({
 				value: material.size,
 				min: 0,
-				max: 3,
+				max: 30,//3,
 				step: 0.01,
 				slide: function (event, ui) { material.size = ui.value; }
 			});
@@ -270,7 +270,7 @@ export class PropertiesPanel{
 			sldMinPointSize.slider({
 				value: material.size,
 				min: 0,
-				max: 3,
+				max: 30,//3,
 				step: 0.01,
 				slide: function (event, ui) { material.minSize = ui.value; }
 			});

+ 15 - 2
src/viewer/SaveProject.js

@@ -102,9 +102,16 @@ function createCameraAnimationData(animation){
 
 function createMeasurementData(measurement){
 
-	const data = {
+	/* const data = {
 		uuid: measurement.uuid,
 		name: measurement.name,
+        measureType:measurement.measureType, //add
+        direction:measurement.direction,//add
+        minMarkers:measurement.minMarkers,//add
+        maxMarkers: measurement.maxMarkers,//add
+        isRect: measurement.isRect,//add
+        faceDirection: measurement.faceDirection,//add
+        
 		points: measurement.points.map(p => p.position.toArray()),
 		showDistances: measurement.showDistances,
 		showCoordinates: measurement.showCoordinates,
@@ -116,8 +123,14 @@ function createMeasurementData(measurement){
 		showAzimuth: measurement.showAzimuth,
 		showEdges: measurement.showEdges,
 		color: measurement.color.toArray(),
+	}; */
+    const data = {
+		uuid: measurement.uuid,
+		name: measurement.name,
+        measureType:measurement.measureType, //add 
+		points: measurement.points.map(p => p.position.toArray()),
+		 
 	};
-
 	return data;
 }
 

+ 3 - 2
src/viewer/View.js

@@ -6,8 +6,8 @@ export class View{
 	constructor () {
 		this.position = new THREE.Vector3(0, 0, 0);
 
-		this.yaw = Math.PI / 4;
-		this._pitch = -Math.PI / 4;
+		this.yaw = Math.PI / 4; // =  4dkk lon + 90  
+		this._pitch = -Math.PI / 4; //上下旋转 = 4dkk lat
 		this.radius = 1;
 
 		this.maxPitch = Math.PI / 2;
@@ -221,6 +221,7 @@ export class View{
 		if(duration === 0){
 			this.position.copy(endPosition);
 			endTarget && this.lookAt(endTarget);
+            callback && callback()
 		}else{
 
             transitions.start(lerp.vector(this.position, endPosition, (pos, progress)=>{

+ 3 - 3
src/viewer/map.js

@@ -552,7 +552,7 @@ export class MapView{
 		return this.sourcesLabelLayer;
 	}
 
-	setSceneProjection (sceneProjection) {
+	setSceneProjection (sceneProjection) { 
 		this.sceneProjection = sceneProjection;
 		this.toMap = proj4(this.sceneProjection, this.mapProjection);
 		this.toScene = proj4(this.mapProjection, this.sceneProjection);
@@ -660,10 +660,10 @@ export class MapView{
 		/* if (!pointcloud.projection) {
 			return;
 		}
- */
+        */
 		if (!this.sceneProjection) {
 			try {
-				this.setSceneProjection(proj4.defs("NAVVIS:TMERC")/* pointcloud.projection */);
+				this.setSceneProjection(proj4.defs("NAVVIS:TMERC") || pointcloud.projection);
 			}catch (e) {
 				console.log('Failed projection:', e);
 

+ 69 - 3
src/viewer/potree.css

@@ -187,10 +187,10 @@
 	background-color: var(--bg-dark-color);
 }
 
-a:hover, a:visited, a:link, a:active{
+/* a:hover, a:visited, a:link, a:active{
 	color: 				#ccccff;
 	text-decoration: 	none;
-}
+} */
 
 .annotation{
 	position:		absolute;
@@ -801,4 +801,70 @@ body{
 #alignment button{
 	padding:0 2px;
     cursor:pointer;
-}
+}
+
+#potree_labels{
+    position:absolute;
+    left:0;
+    right:0;
+    top:0;
+    bottom:0;
+    height:100%;
+    width:100%;
+    z-index: 2;
+    pointer-events:none;
+}
+
+
+#potree_labels>div{
+    display: block;
+    position: absolute;
+    line-height: 22px;
+    -webkit-transform: translate(-50%,-50%);
+    transform: translate(-50%,-50%);
+    text-align: center;
+    white-space: nowrap;
+    font-size: 12px;
+    font-style: normal;
+    pointer-events: auto;
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+    background: #02c1add4;
+    /* border: 1px solid hsla(0,0%,100%,.4); */
+    color:#fff;
+    border-radius: 3px;
+    text-shadow: 0 1px 1px #878787;
+    padding:3px 10px;
+    cursor:default;
+    user-select:none;
+}
+#potree_labels>div.unvisible{
+    display:none; 
+}
+
+#potree_labels >div.measure_pointPos{
+    -webkit-transform: translate(-50%,calc(-100% - 15px));
+    transform: translate(-50%,calc(-100% - 15px));
+}
+
+#potree_labels >div.sub{
+    background:#fff; color:#111; 
+    padding:2px 7px; font-size: 10px;
+}
+
+#potree_labels >div.measure_area{
+    
+}
+#potree_labels >div.highLight{
+    background:#02e4ccf2;
+    
+}
+#potree_labels >div.measure_length{
+    
+}
+ 
+
+.hide{
+    display:none !important; 
+}
+ 

+ 91 - 11
src/viewer/sidebar.js

@@ -136,7 +136,7 @@ export class Sidebar{
 					closed: true,
 					maxMarkers: 3,
                     minMarkers:3,
-					name: 'Angle'});
+					measureType: 'Angle'});
 
 				let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
 				let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
@@ -155,11 +155,12 @@ export class Sidebar{
 					showDistances: false,
 					showAngles: false,
 					showCoordinates: true,
+                    showEdges:false,
 					showArea: false,
 					closed: true,
 					maxMarkers: 1,
                     minMarkers:1,
-					name: 'Point'});
+					measureType: 'Point'});
 
 				let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
 				let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
@@ -179,7 +180,9 @@ export class Sidebar{
 					showArea: false,
 					closed: false,
                     minMarkers:2,
-					name: 'Distance'});
+                    maxMarkers: 2,
+					measureType: 'Distance'
+                });
 
 				let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
 				let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
@@ -195,13 +198,16 @@ export class Sidebar{
 			() => {
 				$('#menu_measurements').next().slideDown();
 				let measurement = this.measuringTool.startInsertion({
-					showDistances: false,
+					showDistances: true,//false,
 					showHeight: true,
 					showArea: false,
 					closed: false,
 					maxMarkers: 2,
-                    minMarkers:2,
-					name: 'Height'});
+                    minMarkers:2, 
+                    direction: new THREE.Vector3(0,0,1),//add
+                    //showGuideLine: true: true
+                    measureType: 'Height',
+                });
 
 				let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
 				let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
@@ -225,7 +231,8 @@ export class Sidebar{
 					closed: false,
 					maxMarkers: 3,
                     minMarkers:3,
-					name: 'Circle'});
+					measureType: 'Circle'
+                });
 
 				let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
 				let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
@@ -250,7 +257,7 @@ export class Sidebar{
 					closed: false,
 					maxMarkers: 2,
                     minMarkers:2,
-					name: 'Azimuth'});
+					measureType: 'Azimuth'});
 
 				let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
 				let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
@@ -270,7 +277,53 @@ export class Sidebar{
 					showArea: true,
 					closed: true,
                     minMarkers:3,
-					name: 'Area'});
+                    //showGuideLine: true: true,
+					measureType: 'Area'});
+
+				let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
+				let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
+				$.jstree.reference(jsonNode.id).deselect_all();
+				$.jstree.reference(jsonNode.id).select_node(jsonNode.id);
+			}
+		));
+        // rect area freedom direction
+        elToolbar.append(this.createToolIcon(
+			Potree.resourcePath + '/icons/area.svg',
+			'[title]tt.area_freedom_rect',
+			() => {
+				$('#menu_measurements').next().slideDown();
+				let measurement = this.measuringTool.startInsertion({
+					showDistances: true,
+					showArea: true,
+					closed: true,
+                    minMarkers:4,
+                    maxMarkers:4,
+                    //showGuideLine: true: true,
+                    isRect:true,
+					measureType: 'Rect Area'});
+
+				let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
+				let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
+				$.jstree.reference(jsonNode.id).deselect_all();
+				$.jstree.reference(jsonNode.id).select_node(jsonNode.id);
+			}
+		));
+        // rect area horizontal
+		elToolbar.append(this.createToolIcon(
+			Potree.resourcePath + '/icons/area.svg',
+			'[title]tt.area_horizontal_rect',
+			() => {
+				$('#menu_measurements').next().slideDown();
+				let measurement = this.measuringTool.startInsertion({
+					showDistances: true,
+					showArea: true,
+					closed: true,
+                    minMarkers:4,
+                    maxMarkers:4,
+                    //showGuideLine: true: true,
+                    isRect:true,
+                    faceDirection:"horizontal", 
+					measureType: 'Hor Rect Area'});
 
 				let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
 				let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
@@ -279,6 +332,33 @@ export class Sidebar{
 			}
 		));
 
+        // rect area vertical
+        elToolbar.append(this.createToolIcon(
+			Potree.resourcePath + '/icons/area.svg',
+			'[title]tt.area_vertical_rect',
+			() => {
+				$('#menu_measurements').next().slideDown();
+				let measurement = this.measuringTool.startInsertion({
+					showDistances: true,
+					showArea: true,
+					closed: true,
+                    minMarkers:4,
+                    maxMarkers:4,
+                    //showGuideLine: true: true,
+                    isRect:true,
+                    faceDirection:"vertical",
+					measureType: 'Ver Rect Area'});
+
+				let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements");
+				let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid);
+				$.jstree.reference(jsonNode.id).deselect_all();
+				$.jstree.reference(jsonNode.id).select_node(jsonNode.id);
+			}
+		));       
+                
+                
+                
+
 		// VOLUME
 		elToolbar.append(this.createToolIcon(
 			Potree.resourcePath + '/icons/volume.svg',
@@ -335,7 +415,7 @@ export class Sidebar{
 				$.jstree.reference(jsonNode.id).deselect_all();
 				$.jstree.reference(jsonNode.id).select_node(jsonNode.id);
 			}
-		));
+		)); 
 
 		// REMOVE ALL
 		elToolbar.append(this.createToolIcon(
@@ -393,7 +473,7 @@ export class Sidebar{
 					let url = window.URL.createObjectURL(new Blob([geoJson], {type: 'data:application/octet-stream'}));
 					elDownloadJSON.attr('href', url);
 				}else{
-					this.viewer.postError("no measurements to export");
+					this.viewer.postError("nothing to export");
 					event.preventDefault();
 				}
 			});

+ 80 - 22
src/viewer/viewer.js

@@ -36,6 +36,13 @@ import {transitions, esing, lerp} from '../utils/transitions.js'
 import JSON5 from "../../libs/json5-2.1.3/json5.mjs";
 import CursorDeal from '../utils/CursorDeal'
 
+
+
+
+var W, H, pixelRatio;
+
+ 
+
 export class Viewer extends EventDispatcher{
 	
 	constructor(domElement, args = {}){
@@ -121,6 +128,14 @@ export class Viewer extends EventDispatcher{
 
 				$(domElement).append(potreeMap);
 			}
+            
+            //add
+            {
+                $(domElement).append($("<div id='potree_labels'></div>"))
+            }
+             
+            
+            
 		}
         
 
@@ -188,10 +203,7 @@ export class Viewer extends EventDispatcher{
 
 		this.initThree();
 
-console.log('11111')
-
-
-
+  
 		if(args.noDragAndDrop){
 			
 		}else{
@@ -1423,7 +1435,7 @@ console.log('11111')
 			alpha: true,
 			depth: true,
 			stencil: false,
-			antialias: false,
+			antialias: true,
 			//premultipliedAlpha: _premultipliedAlpha,
 			preserveDrawingBuffer: true,
 			powerPreference: "high-performance",
@@ -1447,9 +1459,11 @@ console.log('11111')
 			alpha: true, 
 			premultipliedAlpha: false,
 			canvas: canvas,
-			context: context});
-		this.renderer.sortObjects = false;
-		this.renderer.setSize(width, height);
+			context: context,
+            
+        });     
+		this.renderer.sortObjects = true; //原先false 打开了renderOrder才奏效
+		//this.renderer.setSize(width, height);
 		this.renderer.autoClear = false;
 		this.renderArea.appendChild(this.renderer.domElement);
 		this.renderer.domElement.tabIndex = '2222';
@@ -1825,24 +1839,24 @@ console.log('11111')
 				this._previousCamera.rotation.copy(this.scene.getActiveCamera().rotation);
 			}
 
-			if(!this._previousCamera.matrixWorld.equals(camera.matrixWorld)){
+			if(!this._previousCamera.matrixWorld.equals(camera.matrixWorld) || 
+                !this._previousCamera.projectionMatrix.equals(camera.projectionMatrix)
+            ){
 				this.dispatchEvent({
 					type: "camera_changed",
 					previous: this._previousCamera,
 					camera: camera
 				});
-			}else if(!this._previousCamera.projectionMatrix.equals(camera.projectionMatrix)){
-				this.dispatchEvent({
-					type: "camera_changed",
-					previous: this._previousCamera,
-					camera: camera
-				});
-			}
+			} 
 
 			this._previousCamera = this.scene.getActiveCamera().clone();
 			this._previousCamera.rotation.copy(this.scene.getActiveCamera().rotation);
 
 		}
+        
+        {//判断是否改变canvas大小
+            this.updateScreenSize()
+        }
 
 		{ // update clip boxes
 			let boxes = [];
@@ -1901,7 +1915,8 @@ console.log('11111')
 
 		TWEEN.update(timestamp);
         transitions.update(delta);
-
+        
+             
 
 		this.dispatchEvent({
 			type: 'update',
@@ -1918,6 +1933,53 @@ console.log('11111')
 
 	}
 
+
+
+    updateScreenSize(o={}) { //add 
+          
+        var render = false, ratio, w, h;
+        //记录应当render的大小
+        if (!o.resize && o.width != void 0 && o.height != void 0) {
+            w = o.width
+            h = o.height
+            render = true
+            ratio = 1
+        }else {
+            w = this.renderArea.clientWidth;
+            h = this.renderArea.clientHeight
+            if(o.resize){
+                W = this.renderWidth, H = this.renderHeight 
+            }
+           
+            if(w !== W || h !== H || this.forceUpdateSize || pixelRatio != window.devicePixelRatio){
+                W = w 
+                H = h 
+                render = true 
+                pixelRatio = window.devicePixelRatio  //如果player放在小窗口了,也要监测devicePixelRatio,因为缩放时client宽高不会改变
+                //config.isMobile ? (ratio = Math.min(window.devicePixelRatio, 2)) : (ratio = window.devicePixelRatio)
+                ratio = window.devicePixelRatio
+            }    
+        }
+        if (render) {
+            this.setSize(w, h, ratio);
+            this.forceUpdateSize = !1  
+        } 
+    } 
+    
+    
+    setSize(width, height, devicePixelRatio){//add
+        
+        this.renderer.setSize(width, height, null, devicePixelRatio); //改  为了防止给canvas设置宽高
+        //this.composer.setSize(width, height);
+         
+        this.dispatchEvent({
+            type: 'resize',
+            clientWidth:width, clientHeight:height, devicePixelRatio,
+            canvasWidth:this.renderer.domElement.width,
+            canvasHeight:this.renderer.domElement.height,
+        });
+    }
+
 	getPRenderer(){
 		if(this.useHQ){
 			if (!this.hqRenderer) {
@@ -2120,7 +2182,7 @@ console.log('11111')
             const height = params.height || this.scaleFactor * this.renderArea.clientHeight;
          
 
-            this.renderer.setSize(width, height);
+            //this.renderer.setSize(width, height);
         
         
             if(this.viewports){
@@ -2411,10 +2473,6 @@ console.log('11111')
     
     
     
-    
-    
-    
-    
 };