浏览代码

增加skybox。改进outline

xzw 2 年之前
父节点
当前提交
cac00a245d

+ 2 - 2
gulpfile.js

@@ -79,8 +79,8 @@ let shaders = [
 	"src/materials/shaders/copyCubeMap.fs",
 	"src/materials/shaders/basicTextured.vs",
 	"src/materials/shaders/basicTextured.fs", 
-    
-    
+    "src/materials/shaders/skybox.vs", 
+    "src/materials/shaders/skybox.fs", 
 ];
 
 

+ 190 - 196
src/custom/materials/postprocessing/OutlinePass.js

@@ -19,7 +19,7 @@ let OutlinePass = function ( selectedObjects ) {
 	this.edgeStrength =  50;
 	this.downSampleRatio = 1//2;  // 抗锯齿  值越低renderTarget size越大,抗锯齿越强,线条可越细(或许可以把模糊化去掉?)
 	this.pulsePeriod = 0;
-
+    this.showHiddenPart = false //是否判断被遮住的部分,以设置hiddenEdgeColor。一般不需要
 	Pass.call( this );
 
 	this.resolution =  new THREE.Vector2( 256, 256 ); 
@@ -29,8 +29,7 @@ let OutlinePass = function ( selectedObjects ) {
 	var resx = Math.round( this.resolution.x / this.downSampleRatio );
 	var resy = Math.round( this.resolution.y / this.downSampleRatio );
 
-	//this.maskBufferMaterial = new THREE.MeshBasicMaterial( { color: 0xffffff } );
-	//this.maskBufferMaterial.side = THREE.DoubleSide;
+	 
 	this.renderTargetMaskBuffer = new THREE.WebGLRenderTarget( this.resolution.x, this.resolution.y, pars );
 	this.renderTargetMaskBuffer.texture.name = "OutlinePass.mask";
 	this.renderTargetMaskBuffer.texture.generateMipmaps = false;
@@ -42,22 +41,13 @@ let OutlinePass = function ( selectedObjects ) {
 
 	this.prepareMaskMaterial = this.getPrepareMaskMaterial();
 	this.prepareMaskMaterial.side = THREE.DoubleSide;
-	//this.replaceDepthToViewZ(  viewer.mainViewport.camera  /*  camera */ );
+	 
 
 	this.renderTargetDepthBuffer = new THREE.WebGLRenderTarget( this.resolution.x, this.resolution.y, pars );
 	this.renderTargetDepthBuffer.texture.name = "OutlinePass.depth";
 	this.renderTargetDepthBuffer.texture.generateMipmaps = false;
 
-	/* this.renderTargetMaskDownSampleBuffer = new THREE.WebGLRenderTarget( resx, resy, pars );
-	this.renderTargetMaskDownSampleBuffer.texture.name = "OutlinePass.depthDownSample";
-	this.renderTargetMaskDownSampleBuffer.texture.generateMipmaps = false;
-
-	this.renderTargetBlurBuffer1 = new THREE.WebGLRenderTarget( resx, resy, pars );
-	this.renderTargetBlurBuffer1.texture.name = "OutlinePass.blur1";
-	this.renderTargetBlurBuffer1.texture.generateMipmaps = false;
-	this.renderTargetBlurBuffer2 = new THREE.WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars );
-	this.renderTargetBlurBuffer2.texture.name = "OutlinePass.blur2";
-	this.renderTargetBlurBuffer2.texture.generateMipmaps = false; */
+	 
 
 	this.edgeDetectionMaterial = this.getEdgeDetectionMaterial(this.edgeStrength);
      
@@ -65,20 +55,7 @@ let OutlinePass = function ( selectedObjects ) {
 	this.renderTargetEdgeBuffer1 = new THREE.WebGLRenderTarget( resx, resy, pars );
 	this.renderTargetEdgeBuffer1.texture.name = "OutlinePass.edge1";
 	this.renderTargetEdgeBuffer1.texture.generateMipmaps = false;
-	/* this.renderTargetEdgeBuffer2 = new THREE.WebGLRenderTarget( Math.round( resx / 2 ), Math.round( resy / 2 ), pars );
-	this.renderTargetEdgeBuffer2.texture.name = "OutlinePass.edge2";
-	this.renderTargetEdgeBuffer2.texture.generateMipmaps = false; 
-
-	var MAX_EDGE_THICKNESS = 4;
-	var MAX_EDGE_GLOW = 4;
-
-	this.separableBlurMaterial1 = this.getSeperableBlurMaterial( MAX_EDGE_THICKNESS );
-	this.separableBlurMaterial1.uniforms[ "texSize" ].value = new THREE.Vector2( resx, resy );
-	this.separableBlurMaterial1.uniforms[ "kernelRadius" ].value = 1;
-	this.separableBlurMaterial2 = this.getSeperableBlurMaterial( MAX_EDGE_GLOW );
-	this.separableBlurMaterial2.uniforms[ "texSize" ].value = new THREE.Vector2( Math.round( resx / 2 ), Math.round( resy / 2 ) );
-	this.separableBlurMaterial2.uniforms[ "kernelRadius" ].value = MAX_EDGE_GLOW;
-    */
+	 
 	// Overlay material
 	this.overlayMaterial = this.getOverlayMaterial();
 
@@ -96,12 +73,7 @@ let OutlinePass = function ( selectedObjects ) {
 		transparent: true
 	} );
 
-    
-
-
-
-
-
+     
 
 
 	this.enabled = true;
@@ -116,9 +88,7 @@ let OutlinePass = function ( selectedObjects ) {
 	this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
 	this.quad.frustumCulled = false; // Avoid getting clipped
 	this.scene.add( this.quad );
-
-	/* this.tempPulseColor1 = new THREE.Color();
-	this.tempPulseColor2 = new THREE.Color(); */
+ 
 	this.textureMatrix = new THREE.Matrix4();
 
 	
@@ -136,7 +106,7 @@ OutlinePass.prototype = Object.assign( Object.create(  Pass.prototype ), {
         this.renderTargetDepthBuffer.dispose(); 
 	},
     
-    replaceDepthToViewZ( camera ) { 
+    replaceDepthToViewZ( camera ) {  
 		var type = camera.isPerspectiveCamera ? 'perspective' : 'orthographic';
         if(type == this.lastCameraType )return
         this.lastCameraType = type
@@ -276,21 +246,13 @@ OutlinePass.prototype = Object.assign( Object.create(  Pass.prototype ), {
             
             let render2 = (target, dontRenderRtEDL=true)=>{
                 if(renderFun){
-                    renderFun({target  , dontRenderRtEDL})
+                    renderFun({target  , dontRenderRtEDL  })
                 }else{
                     renderer.setRenderTarget(target)
                     renderer.clear()
                     scenes.forEach(scene=>renderer.render( scene, camera)) 
                 }
             }
-            viewports.forEach(e=>{ 
-                e.oldBeforeRender = e.beforeRender
-                e.beforeRender = ()=>{ 
-                    e.oldBeforeRender && e.oldBeforeRender()
-                    this.replaceDepthToViewZ( e.camera );
-                }
-            })
-            
 	   
 			this.oldClearColor.copy( renderer.getClearColor(new THREE.Color) );
 			this.oldClearAlpha = renderer.getClearAlpha();
@@ -299,83 +261,108 @@ OutlinePass.prototype = Object.assign( Object.create(  Pass.prototype ), {
 			renderer.autoClear = false;
 
 			if ( maskActive ) renderer.context.disable( renderer.context.STENCIL_TEST );
+            renderer.setClearColor( 0xffffff, 1 );
 
-			renderer.setClearColor( 0xffffff, 1 );
+			let oldBG = viewer.background, oldBgOpacity = viewer.backgroundOpacity
+            viewer.background = new THREE.Color(1,1,1)
+            viewer.backgroundOpacity = 1;
 
-			// Make selected objects invisible
-			this.changeVisibilityOfSelectedObjects( false );
-            
-            scenes.forEach(scene=>{
-                scene.currentBackground = scene.background;
-                scene.background = null;
-                // 1. Draw Non Selected objects in the depth buffer
-                scene.overrideMaterial = this.depthMaterial;    
-            }) 
             
-			
-			
-            render2(this.renderTargetDepthBuffer)
-            //renderer.setRenderTarget(this.renderTargetDepthBuffer)
-            //renderer.clear()
-			//renderer.render( scene, camera/* , this.renderTargetDepthBuffer, true  */);
-            
-			// Make selected objects visible
-			this.changeVisibilityOfSelectedObjects( true );
-
-    
-            viewports.forEach(e=>{
-                e.beforeRender = ()=>{ 
-                    e.oldBeforeRender && e.oldBeforeRender()
-                    // Update Texture Matrix for Depth compare
-                    this.updateTextureMatrix(e.camera);
-                    this.prepareMaskMaterial.uniforms[ "cameraNearFar" ].value = new THREE.Vector2( e.camera.near, e.camera.far );
-                }
-            })
-
-
-			
+            if(this.showHiddenPart){ //几乎不会使用
+                viewports.forEach(e=>{ 
+                    e.oldBeforeRender = e.beforeRender
+                    e.beforeRender = ()=>{ 
+                        e.oldBeforeRender && e.oldBeforeRender()
+                        this.replaceDepthToViewZ( e.camera );
+                    }
+                }) 
+                // Make selected objects invisible
+                this.changeVisibilityOfSelectedObjects( false );
+                
+                scenes.forEach(scene=>{
+                    scene.currentBackground = scene.background;
+                    scene.background = null;
+                    // 1. Draw Non Selected objects in the depth buffer
+                    scene.overrideMaterial = this.depthMaterial;    
+                }) 
+                 
+                render2(this.renderTargetDepthBuffer)
+                  
+                // Make selected objects visible
+                this.changeVisibilityOfSelectedObjects( true );
 
-			// Make non selected objects invisible, and draw only the selected objects, by comparing the depth buffer of non selected objects
-			this.changeVisibilityOfNonSelectedObjects( false , scenes);
-			
-            
-            scenes.forEach(scene=>{ 
-                scene.overrideMaterial = this.prepareMaskMaterial; 
-            })
-            
-            
-			this.prepareMaskMaterial.uniforms[ "depthTexture" ].value = this.renderTargetDepthBuffer.texture;
-			this.prepareMaskMaterial.uniforms[ "textureMatrix" ].value = this.textureMatrix;
-			 
-            //renderer.setRenderTarget(this.renderTargetMaskBuffer)
-            //renderer.clear()
-            //renderer.render( scene, camera/* , this.renderTargetMaskBuffer, true */ );
+        
+                viewports.forEach(e=>{
+                    e.beforeRender = ()=>{ 
+                        e.oldBeforeRender && e.oldBeforeRender()
+                        // Update Texture Matrix for Depth compare
+                        this.updateTextureMatrix(e.camera);
+                        this.prepareMaskMaterial.uniforms[ "cameraNearFar" ].value = new THREE.Vector2( e.camera.near, e.camera.far );
+                    }
+                })
+                
+            }else{
+                //不渲染背景 
+                scenes.forEach(scene=>{
+                    scene.currentBackground = scene.background;
+                    scene.background = null; 
+                })
+            }
             
-            viewer.scene.pointclouds.forEach(e=>{  //先将点云透明度变为1,因为点云透明度莫名其妙会影响其r值
-                e.material._oldOpa = e.material.opacity
-                e.material.opacity = 1
-            })
+            let colorType, colors = new Map() , opas = new Map()
+            {//绘制选中部分
+                // Make non selected objects invisible, and draw only the selected objects, by comparing the depth buffer of non selected objects
+                this.changeVisibilityOfNonSelectedObjects( false , scenes);
+                 
+                scenes.forEach(scene=>{ 
+                    scene.overrideMaterial = this.prepareMaskMaterial; 
+                })
+                
+                if(this.showHiddenPart){ 
+                    this.prepareMaskMaterial.uniforms[ "depthTexture" ].value = this.renderTargetDepthBuffer.texture;
+                    this.prepareMaskMaterial.uniforms[ "textureMatrix" ].value = this.textureMatrix;
+                }
+                  
+                //因为点云不受prepareMaskMaterial作用,所以手动将他们变为黑色不透明 
+                viewer.scene.pointclouds.forEach(e=>{  //先将点云透明度变为1,因为点云透明度莫名其妙会影响其r值//
+                    colorType = e.material.activeAttributeName
+                    e.material.activeAttributeName = 'color'
+                    
+                    colors.set(e, e.material.color)
+                    e.material.color = '#000000';
+                    
+                    opas.set(e, e.material.opacity)
+                    e.material.opacity = 1 
+                })
+            }
             
             render2(this.renderTargetMaskBuffer)
             
-            viewer.scene.pointclouds.forEach(e=>{//恢复
-                e.material.opacity = e.material._oldOpa
-                delete e.material._oldOpa
-            })
-            
-            viewports.forEach((e)=>{e.beforeRender = e.oldBeforeRender})  
-            
-			this.changeVisibilityOfNonSelectedObjects( true , scenes);
             
-            
-            scenes.forEach(scene=>{ 
-                scene.overrideMaterial = null;
-                scene.background = scene.currentBackground 
-            })
-			
+            {//恢复 
+                viewer.scene.pointclouds.forEach(e=>{
+                    e.material.activeAttributeName = colorType 
+                    e.material.color = colors.get(e) 
+                    e.material.opacity = opas.get(e) 
+                })
+                
+                if(this.showHiddenPart){
+                    viewports.forEach((e)=>{e.beforeRender = e.oldBeforeRender})
+                }
+                
+                scenes.forEach(scene=>{ 
+                    scene.overrideMaterial = null;
+                    scene.background = scene.currentBackground 
+                }) 
+                viewer.background = oldBG
+                viewer.backgroundOpacity = oldBgOpacity
+                
+                this.changeVisibilityOfNonSelectedObjects( true , scenes);
+                
+            }
 
-			 
 
+            //检测边缘并绘制
 			// 3. Apply Edge Detection Pass
 			this.quad.material = this.edgeDetectionMaterial;
 			this.edgeDetectionMaterial.uniforms[ "maskTexture" ].value = this.renderTargetMaskBuffer.texture;//this.renderTargetMaskDownSampleBuffer.texture;
@@ -387,14 +374,15 @@ OutlinePass.prototype = Object.assign( Object.create(  Pass.prototype ), {
 			this.edgeDetectionMaterial.uniforms[ "hiddenEdgeColor" ].value = this.hiddenEdgeColor //this.tempPulseColor2;
 			
             
+             
             
-            let buffer = readBuffer
+            let buffer
             if ( this.renderToScreen ) {
                 this.quad.material.transparent = true
                 
                 buffer = null 
                 renderer.setClearColor( this.oldClearColor, this.oldClearAlpha );  
-                render2(null,false)
+                render2(null,false) //普通绘制原场景
                 
                 //绘制到全屏
                 let renderSize = renderer.getSize(new THREE.Vector2()); //是client大小
@@ -402,98 +390,71 @@ OutlinePass.prototype = Object.assign( Object.create(  Pass.prototype ), {
                 renderer.setScissorTest( false );
                   
             }else{
+                buffer = readBuffer
                 renderer.setClearColor( 0x000000, 0 );
                 renderer.clear()
             } 
-            
-         
-            renderer.setRenderTarget(buffer/* this.renderTargetEdgeBuffer1 */)
-            
-            renderer.render( this.scene,  this.camera/* , this.renderTargetEdgeBuffer1, true  */);
+             
+            renderer.setRenderTarget( buffer ) 
+            renderer.render( this.scene,  this.camera );    //将边缘覆盖上去
            
-
-            //这次删掉
-			/* // Blend it additively over the input texture
-			this.quad.material = this.overlayMaterial;
-			//this.overlayMaterial.uniforms[ "maskTexture" ].value = this.renderTargetMaskBuffer.texture;
-			this.overlayMaterial.uniforms[ "edgeTexture1" ].value = this.renderTargetEdgeBuffer1.texture;
-			//this.overlayMaterial.uniforms[ "edgeTexture2" ].value = this.renderTargetEdgeBuffer2.texture;
-			//this.overlayMaterial.uniforms[ "patternTexture" ].value = this.patternTexture;
-			this.overlayMaterial.uniforms[ "edgeStrength" ].value = this.edgeStrength;
-			//this.overlayMaterial.uniforms[ "edgeGlow" ].value = this.edgeGlow;
-			//this.overlayMaterial.uniforms[ "usePatternTexture" ].value = this.usePatternTexture;
            
-
-			if ( maskActive ) renderer.context.enable( renderer.context.STENCIL_TEST ); 
-			//renderer.render( this.scene,  camera, readBuffer, false );
-            
-            //改:清空readBuffer, 仅绘制出outline的部分 
-            
-            renderer.setClearColor( 0x000000, 0 );
-            renderer.setRenderTarget(readBuffer)
-            renderer.clear()
-            renderer.render(  this.scene,  this.camera );
-            */
+           
+ 
             renderer.setRenderTarget(oldTarget) 
 			renderer.setClearColor( this.oldClearColor, this.oldClearAlpha );
 			renderer.autoClear = oldAutoClear;
             return true
 		} 
-
-		/* if ( this.renderToScreen ) {
-
-			this.quad.material = this.materialCopy;
-			this.copyUniforms[ "tDiffuse" ].value = readBuffer.texture;
-			renderer.render(  this.scene ,  this.camera );
-
-		} */
+ 
 
 	},
 
 	getPrepareMaskMaterial: function () {
-
-		return new THREE.ShaderMaterial( {
-
-			uniforms: {
-				"depthTexture": { value: null },
-				"cameraNearFar": { value: new THREE.Vector2( 0.5, 0.5 ) },
-				"textureMatrix": { value: new THREE.Matrix4() }
-			},
-
-			vertexShader: [
-				'varying vec4 projTexCoord;',
-				'varying vec4 vPosition;',
-				'uniform mat4 textureMatrix;',
-
-				'void main() {',
-
-				'	vPosition = modelViewMatrix * vec4( position, 1.0 );',
-				'	vec4 worldPosition = modelMatrix * vec4( position, 1.0 );',
-				'	projTexCoord = textureMatrix * worldPosition;',
-				'	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
-
-				'}'
-			].join( '\n' ),
-
-			fragmentShader: [
-				'#include <packing>',
-				'varying vec4 vPosition;',
-				'varying vec4 projTexCoord;',
-				'uniform sampler2D depthTexture;',
-				'uniform vec2 cameraNearFar;',
-
-				'void main() {',
-
-				'	float depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));',
-				'	float viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y );',
-				'	float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;',   
-				'	gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);',
-
-				'}'
-			].join( '\n' )
-            //scene.overrideMaterial
-            //为什么画出来红色通道不为0,且depthTest似乎会改变红色通道的值
-		} );
+        if(this.showHiddenPart){
+            return new THREE.ShaderMaterial( {
+
+                uniforms: {
+                    "depthTexture": { value: null },
+                    "cameraNearFar": { value: new THREE.Vector2( 0.5, 0.5 ) },
+                    "textureMatrix": { value: new THREE.Matrix4() }
+                },
+
+                vertexShader: [
+                    'varying vec4 projTexCoord;',
+                    'varying vec4 vPosition;',
+                    'uniform mat4 textureMatrix;',
+
+                    'void main() {',
+
+                    '	vPosition = modelViewMatrix * vec4( position, 1.0 );',
+                    '	vec4 worldPosition = modelMatrix * vec4( position, 1.0 );',
+                    '	projTexCoord = textureMatrix * worldPosition;',
+                    '	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
+
+                    '}'
+                ].join( '\n' ),
+
+                fragmentShader: [
+                    '#include <packing>',
+                    'varying vec4 vPosition;',
+                    'varying vec4 projTexCoord;',
+                    'uniform sampler2D depthTexture;',
+                    'uniform vec2 cameraNearFar;',
+
+                    'void main() {',
+
+                    '	float depth = unpackRGBAToDepth(texture2DProj( depthTexture, projTexCoord ));',
+                    '	float viewZ = - DEPTH_TO_VIEW_Z( depth, cameraNearFar.x, cameraNearFar.y );',
+                    '	float depthTest = (-vPosition.z > viewZ) ? 1.0 : 0.0;',   //决定是否为hiddenPart
+                    '	gl_FragColor = vec4(0.0, depthTest, 1.0, 1.0);',
+
+                    '}'
+                ].join( '\n' ) 
+            } );//没有绘制部分的颜色是clearColor,255
+        }else{
+            return new THREE.MeshBasicMaterial({color:'#000000'}) //不检测深度,不判断遮挡
+        }
 
 	},
 
@@ -560,7 +521,7 @@ OutlinePass.prototype = Object.assign( Object.create(  Pass.prototype ), {
 					float d = length( vec2(diff1, diff2) ) * edgeStrength;
 					float a1 = min(c1.g, c2.g);
 					float a2 = min(c3.g, c4.g);
-					float visibilityFactor = min(a1, a2);
+					float visibilityFactor = min(a1, a2); //检测深度值,是否被遮挡
 					vec3 edgeColor = 1.0 - visibilityFactor > 0.001 ? visibleEdgeColor : hiddenEdgeColor;
 					//gl_FragColor = vec4(0.0,1.0,0.0,1.0); 
                     gl_FragColor = vec4(edgeColor, 1.0) * vec4(d); 
@@ -624,7 +585,7 @@ OutlinePass.prototype = Object.assign( Object.create(  Pass.prototype ), {
 
 	},
 
-	getOverlayMaterial: function () {
+	getOverlayMaterial: function () {//对边缘线进一步处理,已被废弃
 
 		return new THREE.ShaderMaterial( {
 
@@ -688,4 +649,37 @@ OutlinePass.prototype = Object.assign( Object.create(  Pass.prototype ), {
 OutlinePass.BlurDirectionX = new THREE.Vector2( 1.0, 0.0 );
 OutlinePass.BlurDirectionY = new THREE.Vector2( 0.0, 1.0 );
 
-export default OutlinePass
+export default OutlinePass
+
+
+
+
+
+
+/* 
+
+
+渲染步骤:(没有showHiddenPart时)
+
+仅绘制选中部分,材质为普通的单色材质,颜色是黑色不透明。未绘制部分的clearColor是白色不透明。
+(详见prepareMaskMaterial,输出的r要为0) 
+     
+
+
+然后在上面绘制的图中,根据r的差值,得到边缘线。
+
+
+正常绘制场景之后,将上面的边缘线覆盖于其上。
+
+
+
+(如果showHiddenPart,最开始还要先隐藏选中部分,这是为了得到非选中部分的深度值,然后再绘制选中部分时去比较选中和非选中部分之间的深度差异。以判断是否被遮挡。)
+
+
+
+
+
+
+
+
+ */

+ 1 - 1
src/custom/modules/clipModel/Clip.js

@@ -308,7 +308,7 @@ var Clip = {
     
     
     getTransformationMatrix:function(pointcloud, invMatrix) {//剪裁矩阵
-        var invMatrix = invMatrix || new THREE.Matrix4().getInverse(this.box.matrixWorld) 
+        var invMatrix = invMatrix || this.box.matrixWorld.clone().invert()
         return (new THREE.Matrix4).multiplyMatrices(invMatrix, pointcloud.transformMatrix).transpose()
     },
 

+ 43 - 30
src/custom/modules/mergeModel/MergeEditor.js

@@ -44,7 +44,7 @@ const viewportProps = [{
     viewContainsPoints:[new THREE.Vector3(0,0,0)],
     margin:{x:300, y:250} ,
 } ]
- 
+let cylinderSkyGeo, oldSkyGeo
  
  
 let MergeEditor = {
@@ -76,7 +76,7 @@ let MergeEditor = {
             //见笔记:透明物体的材质设置
         }
         
-        
+        let oriEdgeStrength = viewer.outlinePass.edgeStrength 
         {
             
             this.transformControls = new TransformControls(viewer.mainViewport.camera, viewer.renderArea,{
@@ -96,7 +96,8 @@ let MergeEditor = {
             this.transformControls.setSize(1.5)
             viewer.scene.scene.add(this.transformControls2) 
             viewer.setObjectLayers(this.transformControls2, 'layer2' )  
-            
+             
+             
             let mouseDown = (e)=>{
                  
                 viewer.outlinePass.edgeStrength = 0//暂时消失线
@@ -104,8 +105,8 @@ let MergeEditor = {
             }
             let mouseUp = (e)=>{
                  
-                this.updateEdgeStrength()
-                 
+                //this.updateEdgeStrength()
+                viewer.outlinePass.edgeStrength = oriEdgeStrength
             }
             this.transformControls.addEventListener('mouseDown',mouseDown)
             this.transformControls2.addEventListener('mouseDown',mouseDown)
@@ -265,12 +266,18 @@ let MergeEditor = {
                 dragInfo = null
                 this.clearTranCursor()
                   
-                this.updateEdgeStrength()
-                  
+                //this.updateEdgeStrength()
+                viewer.outlinePass.edgeStrength = oriEdgeStrength  
                 
             })
         
         }
+        
+        
+        /* viewer.addEventListener('background_changed',()=>{
+          
+        }) */
+        
     },
     
     
@@ -294,23 +301,25 @@ let MergeEditor = {
             pointDensity: Potree.settings.pointDensity,
         }
         Potree.settings.pointDensity = 'fourViewports' //强制降低点云质量
-        /* viewer.scene.pointclouds.forEach(e=>{
-            e.material.activeAttributeName = "color"
-            e.material.useFilterByNormal = true  
-        }) */ 
-        //取消outline,改点云颜色为和outline一样的颜色
-        /* if(this.selected && this.selected.isPointcloud){ 
-            this.showModelOutline(this.selected, false) 
-            this.selected.material.activeAttributeName = "color"
-            this.selected.material.color = viewer.outlinePass.visibleEdgeColor 
-        } */
-        
+         
         
         viewer.setControls(viewer.fpControls)  
-        viewer.viewports.find(e=>e.name == 'right').rotateSide = true 
-        viewer.viewports.find(e=>e.name == 'top').alignment = true
-       
          
+        let rightViewport = viewer.viewports.find(e=>e.name == 'right')
+        let topViewport = viewer.viewports.find(e=>e.name == 'top')
+        topViewport.alignment = true
+        rightViewport.rotateSide = true  
+        rightViewport.skyboxFixPos = true
+        rightViewport.skyboxMinZoom = 10
+        rightViewport.skyboxRenderFun = ()=>{// 使cube的一面永远正向镜头。 因侧视图的camera是ortho类型,需要平视mesh才不会拉伸
+            viewer.skybox.scene.children[0].rotation.copy(rightViewport.camera.rotation)
+        }
+        topViewport.skyboxRenderFun = ()=>{
+            viewer.skybox.scene.children[0].rotation.set(0,0,0)
+        }
+         
+        
+        
         viewer.viewports[1].layersAdd('layer2') 
         viewer.viewports[0].layersAdd('layer1') 
         viewer.setObjectLayers(this.transformControls, 'layer1' ) 
@@ -328,8 +337,11 @@ let MergeEditor = {
         viewer.compass.changeViewport(viewer.viewports[1])
         viewer.compass.setDomPos()
         
+        
+        //this.changeSkyboxGeo(true)
     },
     
+    
     leaveSplit(){
         this.split = false
         this.SplitScreen.unSplit()    
@@ -350,7 +362,7 @@ let MergeEditor = {
         viewer.compass.setDomPos()
         this.secondCompass.setDisplay(false)
         
-         
+        
     },
     
     rotateSideCamera(angle){
@@ -361,6 +373,9 @@ let MergeEditor = {
         this.transformState = state  
         this.clearTranCursor()       
     },
+    
+  
+    
     //---------------------------
     
     /* writeToHistory(content){ 
@@ -420,10 +435,8 @@ let MergeEditor = {
               
            
             this.showModelOutline(model)
-            
-            
-            
-            this.updateEdgeStrength()
+             
+            //this.updateEdgeStrength()
             
             //console.log('selectModel', model)
             
@@ -470,14 +483,14 @@ let MergeEditor = {
         }
     },
     
-    updateEdgeStrength(){
-        if(!this.selected)return
-        if(this.selected.isPointcloud){
+    /*updateEdgeStrength(){
+        if(!this.selected)return 
+         if(this.selected.isPointcloud){
             viewer.outlinePass.edgeStrength = edgeStrengths.pointcloud// / this.selected.material.opacity  
         }else{
             viewer.outlinePass.edgeStrength = edgeStrengths.glb
         }  
-    },
+    },*/ 
     focusOn(objects, duration = 400, fitBound=true, dontLookUp){  
         if(!(objects instanceof Array)){
             objects = [objects]

+ 24 - 22
src/custom/modules/panos/Images360.js

@@ -283,11 +283,12 @@ export class Images360 extends THREE.EventDispatcher{
                             viewer.mainViewport.view.addEventListener('flyingDone', f) //once
                             return
                         }
-                        if(this.isAtPano() ){//this.currentPano
-                            if(this.flying)config2 = config.transition 
-                            else config2 = config.atPano 
-                        }else{
+                         
+                        
+                        if(this.isAtPano() && !this.latestToPano){ 
                             config2 = config.atPano 
+                        }else{
+                            config2 = config.transition  
                             if(mode == 'showPanos'){//自动飞入一个pano
                                 //要改成飞进最近的。。。 
                                 if(this.panos.length == 0)return
@@ -300,6 +301,7 @@ export class Images360 extends THREE.EventDispatcher{
                                         } 
                                     },e.makeIt ? 1 : 50) 
                                 }
+                                this.addEventListener('flyToPanoDone',wait)   //等待飞行完毕。flyToPano的callback可能不执行所以换这个。但也可能被cancel
                                 this.flyToPano({
                                     pano: this.findNearestPano(),   
                                     //dealDoneWhenCancel:true,
@@ -311,7 +313,6 @@ export class Images360 extends THREE.EventDispatcher{
                                         },1)  
                                     } */
                                 }) 
-                                this.addEventListener('flyToPanoDone',wait)   //等待飞行完毕。flyToPano的callback可能不执行所以换这个。但也可能被cancel
                                 
                                 return;
                             }else{
@@ -456,7 +457,7 @@ export class Images360 extends THREE.EventDispatcher{
                 },
                 set: function(e) {
                     if(e != currentPano){
-                        
+                        console.log('set currentPano ', e.id)
                         currentPano && currentPano.exit()
                         e && e.enter()
                         currentPano = e
@@ -680,13 +681,14 @@ export class Images360 extends THREE.EventDispatcher{
         if(!toPano.pano.enabled)return done(false,true);
         
         
+        if(this.latestToPano && this.latestToPano != toPano){//还在飞
+            return done(false)
+        }
+        
         if(this.currentPano == toPano.pano && this.isAtPano() && !toPano.target && !toPano.quaternion  ){
             this.dispatchEvent({type:'flyToPano', toPano})
             return done(true);
         }
-        if(this.latestToPano && this.latestToPano != toPano){//还在飞
-            return done(false)
-        }
         
         let target = toPano.target 
         let easeName = toPano.easeName || 'easeInOutQuad' // 'easeInOutSine'//'easeOutSine' 
@@ -700,7 +702,7 @@ export class Images360 extends THREE.EventDispatcher{
         let maxTime = this.isAtPano() ? T.panoToPanoMax : T.flyIn 
         var duration = toPano.duration == void 0 ? (T.flyMinTime+Math.min(T.flytimeDistanceMultiplier * this.position.distanceTo(pano.position), maxTime)) : toPano.duration 
         toPano.duration = duration
-        //console.warn("flyto "+pano.id + ' duration: ' + duration )     
+         
         
         this.nextPano = pano 
         this.latestToPano = toPano
@@ -1796,12 +1798,12 @@ export class Images360 extends THREE.EventDispatcher{
                     start+=1 //不包含start和end
                     for(let m=start;m<end;m++){ 
                         dirs2[m].disB = dirs2[end].dis * 0.8
-                        //console.log('changeDis', m, dirs2[m].disB) 
+                        console.log('changeDis', m, dirs2[m].disB) 
                     }
                 }
                 let start = -1 
                 for(let i=0;i<count1;i++){//遍历时将左边dis比之小很多且宽度较小的改大 
-                    //console.log(i, dirs2[i].dis) 
+                    console.log(i, dirs2[i].dis) 
                     let j = i-1
                     let ratios = 0
                     while(j>start && dirs2[i].dis / dirs2[j].dis > maxRatio1){
@@ -1810,7 +1812,7 @@ export class Images360 extends THREE.EventDispatcher{
                     }  
                     let count = i-j-1
                     ratios /= count
-                    if(count > 0 && computeWidth(j,i)< minWidth * ratios / maxRatio2  ){
+                    if(count > 0 && computeWidth(j,i)< minWidth * ratios / maxRatio2  ){ //怎么感觉好像改成了视觉宽度小于某个值即可,那直接用count好了?
                         changeDis(j,i)  
                         start = i  //在此之前的修改过,之后不用再判断
                     }
@@ -1894,18 +1896,17 @@ export class Images360 extends THREE.EventDispatcher{
                                 }
                             }) 
                         })
-                         
-                        
-                        sideCount[index0] = disToSides.length //记录侧边个数
-                        
+                          
                         if(disToSides.length){
                             //disToSides.sort((a,b)=>{return b-a});//从大到小
                             //由距离accordingPano的近到远:
                             disToSides.sort((a,b)=>{return a.disToPano2d-b.disToPano2d})
-                             
-                            //console.log('disToSides', index0, disToSides)
-                            
-                            
+                              
+                            console.log('disToSides', index0, disToSides)
+                            if(disToSides.length == 1 && disToSides[0].disToSide < 0.5){
+                                disToSides = []     //如果太近直接去除
+                            }
+                         
                             disToSides.forEach(e=>{//求z
                                 let ratio = e.disToPano2d / dis2d
                                 let r = accordingPano == pano0 ? (1-ratio) : ratio
@@ -1917,7 +1918,8 @@ export class Images360 extends THREE.EventDispatcher{
                                 
                             }) 
                             
-                        }  
+                        } 
+                        sideCount[index0] = disToSides.length //记录侧边个数                        
                     })
                     
                 }else{

+ 3 - 3
src/custom/modules/panos/Panorama.js

@@ -567,7 +567,7 @@ class Panorama extends THREE.EventDispatcher{
     createTextLabel(){
         this.removeTextLabel()
         this.label = new TextSprite(Object.assign({},
-           labelProp, {text: this.id + "|"+this.originID}) //{text: `id:${this.id}, dataset:${this.pointcloud.name}, 4dkkId:${this.originID}`}
+           labelProp, {text: this.id + "("+this.originID+")"}) //{text: `id:${this.id}, dataset:${this.pointcloud.name}, 4dkkId:${this.originID}`}
         ); 
         this.images360.node.add(this.label);
         this.floorPosition && this.label.position.copy(this.floorPosition)
@@ -692,7 +692,7 @@ Panorama.prototype.loadTiledPano = function() {
                     
                     this.addEventListener(PanoramaEvents.TileLoaded, function(ev/* t, i, n */) {//每张加载完时
                         
-                         console.log('tileLoaded', 'id:'+this.id,  'size:'+ev.size, 'tileIndex:'+ev.index )
+                        //console.log('tileLoaded', 'id:'+this.id,  'size:'+ev.size, 'tileIndex:'+ev.index )
                         let tileIndex = ev.index
                         let total = ev.count
                         let size = ev.size
@@ -740,7 +740,7 @@ Panorama.prototype.loadTiledPano = function() {
                     }.bind(this))
                 }
             }
-            this.images360.tileDownloader.clearForceQueue(),
+            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, dirs, a)

+ 2 - 2
src/custom/modules/panos/tile/PanoRenderer.js

@@ -315,8 +315,8 @@ class PanoRenderer extends THREE.EventDispatcher{
             var r = this.getUploadQueueForPano(e.panoId);
             //console.log(window.sceneName, 'queueTileUpload: ', e.panoId, e.tileIndex,   i)
             if(i){
-                console.log('直接uploadTile')
-                this.uploadTile(e, !1)//提交
+                //console.log('512下载好了直接uploadTile')
+                this.uploadTile(e, !1)//提交后该tile直接loaded了,无需等待
             }else{
                 if(this.shoulPushToFrontOfQueue(e)){//如果是512的优先
                     this.forceQueue.push(e)

+ 17 - 7
src/custom/modules/siteModel/SiteModel.js

@@ -1197,14 +1197,12 @@ var SiteModel = {
 
             let boundingBox = entity.getBound()
             let position = boundingBox.getCenter(new THREE.Vector3())   //中心点不一定在entity中,比如半环形建筑(所以要不要改成到漫游点呢)
-            
+            let size = boundingBox.getSize(new THREE.Vector3())
+              
             if(viewer.modules.Clip && viewer.modules.Clip.editing){
                 viewer.modules.Clip.bus.dispatchEvent({type:'flyToPos', position})
             }else{
-                if(math.closeTo(position, viewer.images360.position)) return 'posNoChange'  
-                let size = boundingBox.getSize(new THREE.Vector3())
-
-             
+                if(math.closeTo(position, viewer.images360.position)) return 'posNoChange' 
                 viewer.scene.view.setView({position,  duration}) 
             } 
             viewer.mapViewer.moveTo(position, size, duration)  
@@ -1273,8 +1271,20 @@ navvis弊端:
     
 https://testlaser.4dkankan.com/indoor/t-8KbK1JjubE/api/site_model
 
-删点全删光了要删实体吗
+ 
+ 
+ 
+根据算法部给的楼层信息 初始化空间模型:
+
+coordinates来源于初始数据集的cloud.js文件中的 tightBoundingBox (逆时针) 
+ 
+coordinates = [[lx,ly],[ux,ly],[ux,uy],[lx,uy]]
+形状是矩形
+area = (ux - lx) * (uy - ly)
+volume = area * height
+
+
 
  */
 
-export {SiteModel} 
+export {SiteModel} 

+ 2 - 2
src/custom/objects/Axis.js

@@ -67,8 +67,8 @@ export default class Axis extends THREE.Object3D {// 坐标轴
 
 
         var material = new THREE.MeshBasicMaterial({color:"#00d7df",side:2,transparent:true,opacity:0.8, depthWrite:false});
-        let axis = Object.keys(Potree.config.axis)
-        axis.forEach((axisText)=>{
+        
+        ['x','y','z'].forEach((axisText)=>{
             let color = new THREE.Color().set(Potree.config.axis[axisText].color)
             var group = this.arrowGroup.clone()
             

+ 65 - 56
src/custom/potree.shim.js

@@ -31,7 +31,7 @@ KeyCodes.BACKSPACE = 8
 
 //注意,这时候Potree.js中export的内容还不在Potree变量中
 
-
+var texLoader = new THREE.TextureLoader()
 
 {//defines:
     Potree.defines = {}
@@ -155,62 +155,66 @@ KeyCodes.BACKSPACE = 8
 
 
 
-Utils.loadSkybox = function(path) {
-    let parent = new THREE.Object3D("skybox_root");
-
-    let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 100000);
-    if(!window.axisYup)  camera.up.set(0, 0, 1);//add
-    let scene = new THREE.Scene();
-
-    let format = '.jpg';
-    let urls = [
-        path + 'px' + format, path + 'nx' + format,
-        path + 'py' + format, path + 'ny' + format,
-        path + 'pz' + format, path + 'nz' + format
-    ];
+Utils.loadSkybox = function(path, oldSky ) {
+    let  camera, scene, parent , cameraOrtho
+    if(!oldSky){
+        parent = new THREE.Object3D("skybox_root");
 
-    let materialArray = [];
-    {
-        for (let i = 0; i < 6; i++) {
-            let material = new THREE.MeshBasicMaterial({
-                map: null,
-                side: THREE.BackSide,
-                depthTest: false,
-                depthWrite: false,
-                color: 0x424556
-            });
-
-            materialArray.push(material);
-
-            let loader = new THREE.TextureLoader();
-            loader.load(urls[i],
-                function loaded (texture) {
-                    material.map = texture;
-                    material.needsUpdate = true;
-                    material.color.setHex(0xffffff);
-                }, function progress (xhr) {
-                    // console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
-                }, function error (xhr) {
-                    console.log('An error happened', xhr);
-                }
-            );
-        }
-    }
-
-    let skyGeometry = new THREE.CubeGeometry(700, 700, 700);
-    let skybox = new THREE.Mesh(skyGeometry, materialArray);
+        camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 100000);
+        cameraOrtho = new THREE.OrthographicCamera(-1, 1, 1, -1, Potree.config.view.near, Potree.settings.cameraFar);
+        if(!window.axisYup)  camera.up.set(0, 0, 1);//add
+        scene = new THREE.Scene();
+        
+        let skyboxBgWidth = Potree.config.skyboxBgWidth
+        let skyGeometry = new THREE.BoxBufferGeometry(skyboxBgWidth,skyboxBgWidth,skyboxBgWidth) 
+        let skybox = new THREE.Mesh(skyGeometry, new THREE.ShaderMaterial({
+            vertexShader: Shaders['skybox.vs'],   
+            fragmentShader: Shaders['skybox.fs'],  
+            side: THREE.BackSide,           
+            uniforms:{
+                tDiffuse: {
+                    type: "t",
+                    value: null
+                },
+                matrix:{
+                    type: "m4",
+                    value: new THREE.Matrix4
+                } 
+            },
+            depthTest:false,
+            depthWrite:false
+        }) );
 
-    scene.add(skybox);
+        scene.add(skybox);
 
-    scene.traverse(n => n.frustumCulled = false);
+        scene.traverse(n => n.frustumCulled = false);
 
-    // z up
-    scene.rotation.x = Math.PI / 2;
+        // z up
+        //scene.rotation.x = Math.PI / 2;
 
-    parent.children.push(camera);
-    camera.parent = parent;
+        parent.children.push(camera);
+        camera.parent = parent;
+            
+    }else{
+        camera = oldSky.camera, 
+        scene = oldSky.scene
+        parent = oldSky.parent
+        cameraOrtho = oldSky.cameraOrtho
+    }
+    
+    let texture = texLoader.load( path, ()=>{
+        console.log('loadSkybox成功',path) 
+        texture.wrapS = THREE.RepeatWrapping;
+        texture.flipY = false 
+        texture.magFilter = THREE.LinearFilter
+        texture.minFilter = THREE.LinearFilter
+        scene.children[0].material.uniforms.tDiffuse.value = texture        
+    },null,(e)=>{//error
+        console.error('loadSkybox失败',path) 
+    });
+    
 
-    return {camera, scene, parent};
+    return {camera, scene, parent, cameraOrtho};
 };
 
 Utils.getMousePointCloudIntersection = function(viewport, mouse, pointer, camera, viewer, pointclouds, pickParams = {} ) {
@@ -1704,6 +1708,7 @@ VolumeTool.prototype.startInsertion = function(args = {}){
     volume.name = args.name || 'Volume-'+args.clipTask;
     volume.isNew = true
     viewer.transformObject(null)//先清空
+    //console.log('startInsertion',volume.uuid)
     
     let updatePose = ()=>{ //保证在视野中的大小一致: 
         let w = math.getScaleForConstantSize({
@@ -1763,10 +1768,11 @@ VolumeTool.prototype.startInsertion = function(args = {}){
     let cancel = ()=>{ 
         end('remove')  
     }
-    let end = (e) => {
+    let end = (e) => { 
         if(e.button == THREE.MOUSE.RIGHT && e.pressDistance<=Potree.config.clickMaxDragDis) {//remove
             e = 'remove'
         } 
+        //console.log('end',volume.uuid, e)
         if(e != 'remove' && (!e.isAtDomElement || e.pressDistance>Potree.config.clickMaxDragDis))return continueDrag()
         volume.removeEventListener('drag', drag);
         volume.removeEventListener('drop', end);
@@ -1784,11 +1790,14 @@ VolumeTool.prototype.startInsertion = function(args = {}){
         volume.dispatchEvent({type:'createFinish', success:e != 'remove'})
     };
      
-    let continueDrag = ( )=>{ 
+    let continueDrag = ( )=>{  
+        //console.log('continueDrag',volume.uuid )
         var timer = setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag  
-            viewer.inputHandler.startDragging( volume  ,  {notPressMouse:true}
-               /*  {endDragFun: e.drag.endDragFun, notPressMouse:e.drag.notPressMouse, dragViewport:e.drag.dragViewport}  */
-            ) 
+            if(volume.parent && volume.isNew){
+                viewer.inputHandler.startDragging( volume  ,  {notPressMouse:true}
+                   /*  {endDragFun: e.drag.endDragFun, notPressMouse:e.drag.notPressMouse, dragViewport:e.drag.dragViewport}  */
+                ) 
+            }
         },1)
         return timer
     }

+ 2 - 2
src/custom/settings.js

@@ -209,7 +209,7 @@ const config = {//配置参数   不可修改
         //navvis的shader在哪里 为什么不会抖动
     }
     ,
-     
+    skyboxBgWidth : 100 , 
     
     renderLayers:{//渲染层,方便分批渲染管理,替代scene的创建。数字不代表顺序。(数字不能太大)
         bg: 20, 
@@ -297,7 +297,7 @@ const config = {//配置参数   不可修改
      
      
     background: '#232323',
-    mapBG:'#F5F5F5', //地图的clearColor
+    mapBG:/* '#232323',   */  '#F5F5F5',   //地图的clearColor
 
     colors: {  //from navvis
         red:  [213,0,0],

+ 1 - 1
src/custom/start.js

@@ -141,7 +141,7 @@ export function start(dom, mapDom, number ){ //t-Zvd3w0m
             pointcloud.updateMatrixWorld()
             
             
-            Potree.Log(`点云${pointcloud.dataset_id}旋转值:${pointcloud.orientationUser}, 位置${math.toPrecision(pointcloud.translateUser.toArray(),3)}, 经纬度 ${locationLonLat}, spacing ${pointcloud.material.spacing}`, null, 17 )
+            Potree.Log(`点云${pointcloud.dataset_id}旋转值:${pointcloud.orientationUser}, 位置${math.toPrecision(pointcloud.translateUser.toArray(),3)}, 经纬度 ${locationLonLat}, spacing ${pointcloud.material.spacing}`, null, 13 )
             
             
             //-------------------

+ 113 - 162
src/custom/viewer/ViewerNew.js

@@ -411,7 +411,7 @@ export class Viewer extends ViewerBase{
                 outlinePass.renderToScreen = true  //这样更流畅,不用ssaa了,缺点是outline有锯齿
                 outlinePass.enabled = false
                 this.composer.addPass( outlinePass );
-                outlinePass.edgeStrength = 10
+                outlinePass.edgeStrength = 4
                 outlinePass.edgeGlow = 0 
                 outlinePass.visibleEdgeColor = new THREE.Color("#09a1b3")  
                 outlinePass.hiddenEdgeColor = new THREE.Color("#09a1b3")  
@@ -892,7 +892,7 @@ export class Viewer extends ViewerBase{
                 if(!camera_changed && count>50 || Potree.settings.displayMode == 'showPanos'  )return //只有当camera_changed后才继续循环, 除了最开始几次需要连续加载下
                 camera_changed = false
                 count ++;
-                 console.log('testPointcloudsMaxLevel中',count)
+                //console.log('testPointcloudsMaxLevel中',count)
                 
                 var success = true    
                 viewer.scene.pointclouds.forEach(e=>{
@@ -1066,13 +1066,13 @@ export class Viewer extends ViewerBase{
 		return this.background;
 	}
 
-	setBackground(bg){
-		if (this.background === bg) {
+	setBackground(bg, src){
+		/* if (this.background === bg ) {
 			return;
-		}
+		} */
 
 		if(bg === "skybox"){
-			this.skybox = Utils.loadSkybox(new URL(Potree.resourcePath + '/textures/skybox2/').href);
+			this.skybox = Utils.loadSkybox(src, this.skybox);
 		} 
 
 		this.background = bg;
@@ -2733,7 +2733,7 @@ export class Viewer extends ViewerBase{
         if(background instanceof THREE.Color){ //add
             renderer.setClearColor(background, backgroundOpacity);
         }else if(background === "skybox"){
-			renderer.setClearColor(0x000000, 0);
+			renderer.setClearColor(0x000000, 0 );
 		} else if (background === 'gradient') {
 			renderer.setClearColor(0x000000, 0);
 		} else if (background === 'black') {
@@ -2755,13 +2755,7 @@ export class Viewer extends ViewerBase{
         
         if(!this.visible   || this.paused  )return
         
-        
-        /* if(this.outlinePass.selectedObjects.length){
-            this.clear()
-            this.composer.render(this.scene.scene, this.mainViewport.camera );  
-            return;
-        } */
-        
+         
 		let pRenderer = this.getPRenderer();
         let viewports = params_.viewports || this.viewports
         
@@ -2808,105 +2802,57 @@ export class Viewer extends ViewerBase{
                     params_.target.viewport.set(left, bottom, width, height);  
                     scissorTest && params_.target.scissor.set(left, bottom, width, height); 
                     params_.target.scissorTest = scissorTest
-                    
+                    this.renderer.setRenderTarget(params_.target)
                 }else{        
                     this.renderer.setViewport(left, bottom, width, height) //规定视口,影响图形变换(画布的使用范围) 
                     scissorTest && this.renderer.setScissor( left, bottom, width, height );//规定渲染范围
                     this.renderer.setScissorTest( scissorTest );//开启WebGL剪裁测试功能,如果不开启,.setScissor方法设置的范围不起作用 | width==1且height==1时开启会只有鼠标的地方刷新,很奇怪
                     
-                }
-               
-            }    
-            
-
-
+                } 
+            } 
             
             if(needSResize){
                 this.emitResizeMsg( { viewport:view} )
             } 
-            
-            //needSResize && this.emitResizeMsg({resolution: params_.target ? new THREE.Vector2(width,height) : view.resolution2, left:view.left,  bottom:view.bottom })//resize everything  such as lines  targets 
-            
-            
-            
+             
             viewer.dispatchEvent({type: "render.begin",  viewer: viewer, viewport:view, params });
-            
              
+           
+            view.beforeRender && view.beforeRender()
+            
             if(view.render){ 
                 view.render($.extend({}, params, {
                     renderer:this.renderer,   clear:this.clear.bind(this), resize:null,
-                    renderOverlay: this.renderOverlay.bind(this),  force:!view.noPointcloud //如果要渲染点云,必须也一直渲染地图,否则地图会被覆盖(点云目前未能获取是否改变,也可能有其他动态物体,所以还是一直渲染的好)
+                     force:!view.noPointcloud //如果要渲染点云,必须也一直渲染地图,否则地图会被覆盖(点云目前未能获取是否改变,也可能有其他动态物体,所以还是一直渲染的好)
                 }))
-            }
-
-            if(!view.render){
-                this.clear(params) 
+            }else{ 
+                this.clear(params)  
                 pRenderer.clearTargets(params);
-                
-                
-                //先渲染不透明的model:
-                /* if(this.objs.children.length){
-                    this.renderer.setRenderTarget(params.target||null)
-                    this.setCameraLayers(params.camera,  ['model'] )//先渲染模型后渲染点云,否则半透明的点云的blend没有混合模型的部分(但模型为何可以混合点云的部分?估计还是PotreeRenderer有问题)
-                    
-                    this.renderer.render(this.scene.scene, params.camera); 
-                }  */
-                    
-                
-                
+                 
+                this.renderBG(view)
+                 
                 if(Potree.settings.notAdditiveBlending){
                     params.renderBeforeCloud = true
-                    this.renderOverlay1(params)   
-                    //view.render || this.renderOverlay(params)  
+                    this.renderOverlay1(params)   //先渲染不透明的model  
                 }   
-                
             }
-            /* view.render || this.clear(params)  
-            pRenderer.clearTargets(params); */
-
- 
-            if(!view.noPointcloud ){ 
-                //if(!params.target){ 
-                    //params.width = width; params.height = height;
-                    
-                //}
-                if(view.render){
-                    params.noBG = true
-                }
+   
+            
+            if(!view.noPointcloud ){  
+                this.updateViewPointcloud(params.camera, view.resolution, true)  
                  
-                
-                view.beforeRender && view.beforeRender()
-                
-                this.updateViewPointcloud(params.camera, view.resolution, true)
-                
-                params.background = view.background
-                params.backgroundColor = view.backgroundColor
-                params.backgroundOpacity = view.backgroundOpacity
-                
-                
-                pRenderer.render(params); 
+                pRenderer.render(params);  //渲染点云
                 
             } 
-                
-
-            if(!view.render){     
-                //view.render || this.renderOverlay(params) 
-                if(Potree.settings.notAdditiveBlending){
-                    params.renderBeforeCloud = false
-                    this.renderOverlay1(params) 
-                    this.renderOverlay2(params)  
-                }else{ 
-                    /* view.render ||  */this.renderOverlay(params)                 
-                }
-                    
-            }    
                  
-           
-             
-           
-            
-              
-            
+            if(Potree.settings.notAdditiveBlending){ // 融合页面才用到
+                params.renderBeforeCloud = false
+                this.renderOverlay1(params) 
+                this.renderOverlay2(params)  
+            }else{ 
+                this.renderOverlay(params)                 
+            }
+               
             view.afterRender && view.afterRender() 
 
             this.dispatchEvent({type: "render.end",  viewer: this, viewport:view  });
@@ -2919,16 +2865,10 @@ export class Viewer extends ViewerBase{
         /* if(params_.screenshot){ //抗锯齿
             params_.target.viewport.set(0, 0, params_.target.width, params_.target.height);  
             //scissorTest && params_.target.scissor.set(left, bottom, width, height); 
-            params_.target.scissorTest = false
-            
+            params_.target.scissorTest = false 
             this.renderer.setRenderTarget(params_.target) 
-             
-            
-            this.composer.render(); 
-
-            this.renderer.setRenderTarget(params_.target) //本想再画一层标签,但是viewport总是出错
-             
-            
+            this.composer.render();  
+            this.renderer.setRenderTarget(params_.target) //本想再画一层标签,但是viewport总是出错 
         }  */
         
         
@@ -2936,6 +2876,70 @@ export class Viewer extends ViewerBase{
         
         
 	}
+    
+    renderBG(view){
+        let background = view.background || viewer.background;
+        let backgroundOpacity = view.backgroundOpacity == void 0 ? viewer.backgroundOpacity : view.backgroundOpacity//如果想完全透明,只需要backgroundOpacity为0
+        if(backgroundOpacity != 0){//绘制背景
+            if(background === "skybox"){
+                //限制相机到原点的距离。 
+                let skyCamera = view.camera.type == "OrthographicCamera" ? viewer.skybox.cameraOrtho : viewer.skybox.camera
+                let safeRatio = 0.02;
+                let safeWidth = Potree.config.skyboxBgWidth * safeRatio / 2;  //相机只能在这个范围内移动
+                if(!view.skyboxFixPos){ //允许不在全景图中心,允许位移造成一定程度畸变 
+                    let dir = new THREE.Vector3().subVectors(view.camera.position, viewer.bound.center);
+                    let length = dir.length()
+                    const moveMax = 100;
+                    let aimRadius = easing.easeOutQuart(Math.min(length, moveMax) , 0, safeWidth, moveMax) //(x, startY, wholeY, maxX)
+                    dir.multiplyScalar(aimRadius/length)  
+                    skyCamera.position.copy(dir)
+                }else{
+                    skyCamera.position.set(0,0,0)
+                }
+                
+                skyCamera.rotation.copy(view.camera.rotation);
+                skyCamera.aspect = view.camera.aspect;
+                
+                if(view.camera.type == "OrthographicCamera"){ //调节zoom
+                    skyCamera.left = view.camera.left; skyCamera.right = view.camera.right; skyCamera.top = view.camera.top; skyCamera.bottom = view.camera.bottom
+                    
+                    let a = Potree.config.skyboxBgWidth / 2 - safeWidth
+                    let minY = Math.max(skyCamera.right / a, skyCamera.top / a,  view.skyboxMinZoom||0); //能够使skybox铺满画布的最小zoom.  提示:越远zoom越小
+                    let maxY = Math.max(20, minY) ;//自定义一个 不会超过的最大实际zoom
+                    //view.camera.zoom自变量的变化范围:
+                    let minX = 1
+                    let maxX = 80  
+                    let x = THREE.Math.clamp(view.camera.zoom - minX, minX, maxX) 
+                    skyCamera.zoom = easing.easeOutCubic(x-minX, minY, maxY-minY, maxX-minX) //自变量范围从0开始,所以减去minX
+                    
+                    //pos的范围先不管了 其实aimRadius是有误的,但效果还行
+                }else{
+                    skyCamera.fov = view.camera.fov;
+                    skyCamera.zoom = 1
+                }
+                  
+                
+                view.skyboxRenderFun && view.skyboxRenderFun()
+                
+                skyCamera.updateProjectionMatrix();
+                skyCamera.updateMatrixWorld()
+                viewer.renderer.render(viewer.skybox.scene, skyCamera);
+            }else if(background === 'gradient'){ 
+                viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg);
+                viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
+            }else if(background === 'overlayColor'){//在不clear的前提下加一层背景色 
+                viewer.scene.bg2.material.color.copy(params.backgroundColor)
+                viewer.scene.bg2.material.opacity = params.backgroundOpacity
+                viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg2);
+                viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
+                
+            }  
+              
+        }
+        
+        //全景图的部分和点云有点相关就不移动到这了
+        
+    }
 	
     /* 
         关于透明度:
@@ -2956,60 +2960,9 @@ export class Viewer extends ViewerBase{
 
     renderOverlay(params){
         this.renderOverlay1(params)
-        this.renderOverlay2(params)
-        /* let camera = params.camera ? params.camera : this.scene.getActiveCamera();
-        
-        this.reticule.updateAtViewports(params.viewport)
-        this.renderer.setRenderTarget(params.target||null)
-        
-         //为什么要在点云之后渲染,否则透明失效 、 会被点云覆盖 
-        let cameraLayers
-
-        if(params.cameraLayers) cameraLayers = params.cameraLayers
-        else{
-            if(params.isMap)cameraLayers = ['bothMapAndScene']
-            else cameraLayers = ['sceneObjects',    'model',   'bothMapAndScene' ];
-        }
-        
-        
-   
-        if(cameraLayers.length){
-            this.setCameraLayers(camera,  cameraLayers, params.extraEnableLayers) //透明贴图层 skybox 、reticule marker 不能遮住测量线
-             
-            this.renderer.render(this.scene.scene, camera);  
-        }
-          
-        this.dispatchEvent({type: "render.pass.scene", viewer: viewer});
-    
-    
-        
-    
-        //清除深度 !!!!
-        this.renderer.clearDepth(); 
-
-        //this.transformationTool.update();
-        
-         
-        if(!params.magnifier){ 
-            //测量线 
-            this.dispatchEvent({type: "render.pass.perspective_overlay", camera, screenshot:params.screenshot});
-            
-            if(!params.screenshot && !params.isMap){
-                this.setCameraLayers(camera, ['magnifier']) //magnifier 遮住测量线 
-                this.renderer.render(this.scene.scene, camera);
-            }
-        } 
-        
-        if(!params.isMap) {
-            this.setCameraLayers(camera, ['volume','transformationTool'])  
-            this.renderer.render(this.clippingTool.sceneVolume, camera);
-            this.renderer.render(this.transformationTool.scene, camera);
-        } */
-         
+        this.renderOverlay2(params) 
     }
-    
-    
-    
+     
     renderOverlay1(params){
         let camera = params.camera ? params.camera : this.scene.getActiveCamera();
         
@@ -3021,12 +2974,11 @@ export class Viewer extends ViewerBase{
 
         if(params.cameraLayers) cameraLayers = params.cameraLayers
         else{
-            if(params.isMap)cameraLayers = ['bothMapAndScene']
+            if(params.viewport.name == "mapViewport" )cameraLayers = ['bothMapAndScene']
             else cameraLayers = ['sceneObjects',   'model',  'bothMapAndScene' ];
         }
         
-        
-   
+         
         if(cameraLayers.length){
             this.setCameraLayers(camera,  cameraLayers, params.extraEnableLayers) //透明贴图层 skybox 、reticule marker 不能遮住测量线
             
@@ -3063,21 +3015,18 @@ export class Viewer extends ViewerBase{
         let camera = params.camera ? params.camera : this.scene.getActiveCamera();
         //清除深度 !!!!
         this.renderer.clearDepth(); 
-
-        //this.transformationTool.update();
-        
-         
+ 
         if(!params.magnifier){ 
             //测量线 
             this.dispatchEvent({type: "render.pass.perspective_overlay", camera, screenshot:params.screenshot});
             
-            if(!params.screenshot && !params.isMap){
+            if(!params.screenshot && params.viewport.name != "mapViewport" ){
                 this.setCameraLayers(camera, ['magnifier']) //magnifier 遮住测量线 
                 this.renderer.render(this.scene.scene, camera);
             }
         } 
         
-        if(!params.isMap) {
+        if(params.viewport.name != "mapViewport" ) {
             this.setCameraLayers(camera, ['volume','transformationTool'])  
             this.renderer.render(this.clippingTool.sceneVolume, camera);  //official 可以删
             this.renderer.render(this.transformationTool.scene, camera);
@@ -3088,7 +3037,7 @@ export class Viewer extends ViewerBase{
     
     
     
-      /* renderDefault(){//测试 ios15.4.1
+    /* renderDefault(){//测试 ios15.4.1
         //let pRenderer = this.getPRenderer();
         //this.clear()
         this.renderer.autoClear = false
@@ -3231,7 +3180,9 @@ export class Viewer extends ViewerBase{
             this.renderVR();
         }else{
             if(this.outlinePass.selectedObjects.length && this.outlinePass.edgeStrength > 0 && !params.screenshot){  
-                this.composer.render(this.inputHandler.interactiveScenes.concat(this.scene.scene).concat(viewer.scene.scenePointCloud), null, this.viewports, this.renderDefault.bind(this));  
+                let scenes = this.inputHandler.interactiveScenes.concat(this.scene.scene).concat(viewer.scene.scenePointCloud) 
+                //if(this.background == 'skybox') scenes = scenes.concat(this.skybox.scene)
+                this.composer.render(scenes, null, this.viewports, this.renderDefault.bind(this));  
             }else{  
                 this.renderDefault(params);
             }  

+ 36 - 10
src/custom/viewer/map/MapViewer.js

@@ -18,7 +18,8 @@ import {config } from "../../settings.js";
 /* var centerCross = new THREE.Mesh(new THREE.SphereGeometry(1, 4, 4),new THREE.MeshBasicMaterial({
     transparent:true,  color:"#ff0000", opacity:0.5
 })); */
-
+import CopyShader from '../../materials/postprocessing/CopyShader.js'
+import {ShaderPass} from '../../materials/postprocessing/ShaderPass.js' 
 
 /* const mapHeight = -1000;//要比点云低。最低
 const cameraHeight = 1000;  //最高 */
@@ -53,9 +54,17 @@ export class MapViewer extends ViewerBase{
         this.splitDir = 'leftRight'
         
         
-        //this.scene.add(centerCross)
+        //因context的preserveDrawingBuffer为false之后,canvas渲染多个viewport时会自动clear,所以若不渲染就会是空的。所以没有变化时就直接拷贝buffer好了。
+        this.copyPass = new ShaderPass( CopyShader );
+        this.copyBuffer = new THREE.WebGLRenderTarget( 100, 100 ,  {
+            minFilter: THREE.LinearFilter,
+			magFilter: THREE.LinearFilter,
+			format: THREE.RGBAFormat,
+			stencilBuffer: false, 
+        });
+        
+        
         
-     
         viewer.addEventListener("camera_changed", (e)=>{
             if(e.viewport == viewer.mainViewport) this.updateCursor()
             else this.updateWhenAtViewer() 
@@ -588,14 +597,25 @@ export class MapViewer extends ViewerBase{
     }
     
     render(params={}){
-       
-        if(!this.visible && !this.attachedToViewer || !this.needRender && !params.force)return
+        let needCopy, waitCopy
+        if(!this.visible && !this.attachedToViewer || !this.needRender && !params.force){
+            if(this.attachedToViewer ){
+                needCopy = true 
+            }else{
+                return
+            } 
+        }
+        waitCopy = this.attachedToViewer && this.needRender && !params.force//是否写入到copyBuffer。双屏时,若needRender就拷贝到copyBuffer中,双屏时就直接使用copyBuffer。 四屏时因渲染点云会每帧都渲染,所以不需要缓存。
+        
         
         let renderer = params.renderer || this.renderer
         
         if(params.target){
             renderer.setRenderTarget(params.target)
-        } 
+        }else if(waitCopy){
+            this.copyBuffer.setSize(params.viewport.resolution2.x, params.viewport.resolution2.y)
+            renderer.setRenderTarget(this.copyBuffer) 
+        }            
         /* if(params.resize){
             this.emitResizeMsg(new THREE.Vector2(params.width,params.height, viewport:params.viewport))
         }  */
@@ -617,13 +637,16 @@ export class MapViewer extends ViewerBase{
         
         //测量线等
         //params.renderOverlay && params.renderOverlay({camera:this.camera, isMap:true, viewport: this.viewports[0] })//其余如reticule 等场景层
-        params.renderOverlay && params.renderOverlay( $.extend({}, params, { isMap:true }))
+        //params.renderOverlay && params.renderOverlay( $.extend({}, params, { isMap:true }))
         
         
         renderer.setRenderTarget(null)
         
         this.needRender = false
         
+        if(needCopy || waitCopy){
+            this.copyPass.render(null,null, renderer, null, this.copyBuffer)
+        }
     }
     
     
@@ -642,8 +665,11 @@ export class MapViewer extends ViewerBase{
     
     
 }
-
-
-
+/* 
+    渲染顺序:
+        地图、overlay
+        点云(如果有)
+        场景中bothMapAndScene的物体
+*/
 //本地调试地图白屏是因为代码自动更新了 但没刷新
 

+ 1 - 1
src/custom/viewer/viewerBase.js

@@ -40,7 +40,7 @@ export class ViewerBase extends THREE.EventDispatcher{
             depth: true,
             stencil: false,
             antialias: true, 
-            preserveDrawingBuffer: false,// true,
+            preserveDrawingBuffer: false    ,
             powerPreference: "high-performance",
         }; 
 

+ 4 - 1
src/utils/TransformationToolNew.js

@@ -357,7 +357,10 @@ export class TransformationTool extends THREE.EventDispatcher{
             
              
 			node.setOpacity = (target) => {
-                if(handleName.includes('plane'))target *= 0.7
+                if(handleName.includes('plane')){
+                    let more = 1.5; //减掉更多,使min更低,max还是1
+                    target = 1 - (1-target)*more 
+                }
                 
 				let opacity = {x: material.opacity};
 				let t = new TWEEN.Tween(opacity).to({x: target},  0);

+ 6 - 26
src/viewer/EDLRendererNew.js

@@ -6,6 +6,10 @@ import {SphereVolume} from "../utils/Volume.js";
 import {Utils} from "../utils.js";
 import {copyShader} from '../materials/shaders/otherShaders.js'
 import {Features} from "../Features.js";
+import {easing} from "../custom/utils/transitions.js";
+
+
+
 
 export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 	constructor(viewer){
@@ -198,31 +202,7 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
 
 
         viewer.renderer.setRenderTarget(params.target || null);
-        let background = params.background || viewer.background;
-        let backgroundOpacity = params.backgroundOpacity == void 0 ? viewer.backgroundOpacity : params.backgroundOpacity//如果想完全透明,只需要backgroundOpacity为0
-        if(backgroundOpacity != 0){//绘制背景
-            if(background === "skybox"){
-                viewer.skybox.camera.rotation.copy(viewer.scene.cameraP.rotation);
-                viewer.skybox.camera.fov = viewer.scene.cameraP.fov;
-                viewer.skybox.camera.aspect = viewer.scene.cameraP.aspect;
-
-                viewer.skybox.parent.rotation.x = 0;
-                viewer.skybox.parent.updateMatrixWorld();
-
-                viewer.skybox.camera.updateProjectionMatrix();
-                
-                viewer.renderer.render(viewer.skybox.scene, viewer.skybox.camera);
-            }else if(background === 'gradient'){ 
-                viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg);
-                viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
-            }else if(background === 'overlayColor'){//在不clear的前提下加一层背景色 
-                viewer.scene.bg2.material.color.copy(params.backgroundColor)
-                viewer.scene.bg2.material.opacity = params.backgroundOpacity
-                viewer.scene.cameraBG.layers.set(Potree.config.renderLayers.bg2);
-                viewer.renderer.render(viewer.scene.scene, viewer.scene.cameraBG);
-            }  
-            
-        }
+        
         
         //skybox  全景图
         if(!params.magnifier){
@@ -236,7 +216,7 @@ export class EDLRenderer{//Eye-Dome Lighting 眼罩照明
             } 
             viewer.renderer.render(viewer.scene.scene, camera);
             if(useDepthTex)return 
-        } 
+        }  
          
         
 		const visiblePointClouds2 = viewer.scene.pointclouds.filter(pc => viewer.getObjVisiByReason(pc,'datasetSelection')  ); //需要绘制到rtEDL的