Bladeren bron

fix: 估算pano顶部的高度,使顶部以上的marker得到遮挡, 且使深度图intersect到的顶部更为准确,从而使垂直方向的pano之间是否相邻的计算更准确,从而避免隔层漫游。另外优化垂直方向上的pano间的skybox模型,避免模型穿帮。

xzw 2 jaren geleden
bovenliggende
commit
80cc0bcc3c

+ 34 - 15
src/custom/materials/ModelTextureMaterial.js

@@ -76,7 +76,14 @@ let shader = {
 				type: "f",
 				value: 1
 			},
-            
+            ceilHeight0:{
+                type: "f",
+				value: 2
+            },
+            ceilHeight1:{
+                type: "f",
+				value: 2
+            }
         },
        
         vertexShader: prefixVertex + `
@@ -149,9 +156,6 @@ let shader = {
             uniform float minDistance;
             uniform float minOpa;
             
-            uniform float cameraHeight0;
-            uniform float cameraHeight1;
-
           
        
             /* uniform sampler2D pano0Map;
@@ -190,8 +194,12 @@ let shader = {
                 uniform mat4 inverseProjectionMatrix;
                 uniform mat4 projectionMatrix;
                 uniform vec4 viewport; 
-            
-                vec2 getDepth(vec3 dir, sampler2D depthMap, float height, vec4 eyePos){
+                uniform float cameraHeight0;
+                uniform float cameraHeight1;
+                uniform float ceilHeight0;
+                uniform float ceilHeight1;
+                
+                vec2 getDepth(vec3 dir, sampler2D depthMap, float heightDown, float heightUp, vec4 eyePos){
                     vec2 depthValue = vec2(0.0, 0.0);
                     vec2 uv2 = getSamplerCoord2(/* vWorldPosition12 */dir.xyz);  //暂时只用基于目标漫游点的方向
                     uv2.x -= 0.25;    //全景图和Cube的水平采样起始坐标相差90度,这里矫正 0.25 个采样偏移
@@ -203,7 +211,8 @@ let shader = {
                     float distance = (depth.g + depth.r / 256.) * 255.;  //为什么要乘以255 
                     
                     if(distance == 0.0){//漫游点底部识别不到的区域,给一个地板高度 
-                         if(uv2.y > 0.75) distance = height / -dir.y;   
+                         if(uv2.y < 0.25) distance = heightUp / dir.y;    
+                         else if(uv2.y > 0.75) distance = heightDown / -dir.y;   
                          else distance = 100000.0;//给个超级远的值
                     } 
                     
@@ -259,9 +268,9 @@ let shader = {
                     vec4 eyePos = inverseProjectionMatrix * clipPos;
                     vec2 depth0 = vec2(0.0,0.0); 
                     if(progress < 1.0){
-                        depth0 = getDepth(vWorldPosition0N, depthMap0, cameraHeight0, eyePos);
+                        depth0 = getDepth(vWorldPosition0N, depthMap0, cameraHeight0, ceilHeight0, eyePos);
                     }
-                    vec2 depth1 = getDepth(vWorldPosition1N, depthMap1, cameraHeight1, eyePos);
+                    vec2 depth1 = getDepth(vWorldPosition1N, depthMap1, cameraHeight1, ceilHeight1, eyePos);
                     
                     /* if(progress < 1.0 && depth1.x == 0.0 && depth0.x > 0.0){
                         gl_FragDepthEXT = depth0.y; 
@@ -355,9 +364,7 @@ export default class ModelTextureMaterial extends THREE.RawShaderMaterial {
         if(pano0){
             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 */ );
-            this.uniforms.cameraHeight0.value = pano0.floorPosition.distanceTo(pano0.position)
-            
+            this.uniforms.pano0Matrix.value.copy(pano0.panoMatrix/* pano0.mesh.matrixWorld */ ); 
             //pano1.ensureSkyboxReadyForRender();
         }
         
@@ -365,7 +372,9 @@ export default class ModelTextureMaterial extends THREE.RawShaderMaterial {
 		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 */ );
-        this.uniforms.cameraHeight1.value = pano1.floorPosition.distanceTo(pano1.position)
+        
+        
+        
         this.pano0 = pano0
         this.pano1 = pano1
         
@@ -382,8 +391,18 @@ export default class ModelTextureMaterial extends THREE.RawShaderMaterial {
     updateDepthTex(pano){
         if( !Potree.settings.useDepthTex || !pano || !pano.depthTex || pano!=this.pano0 && pano!=this.pano1)return
         //console.log('updateDepthTex', pano.id,  this.pano0 && this.pano0.id,  this.pano1 && this.pano1.id)
-        this.uniforms.depthMap0.value = this.pano0 && this.pano0.depthTex 
-        this.uniforms.depthMap1.value = this.pano1 && this.pano1.depthTex 
+        
+         
+        if(this.pano0){ 
+            this.uniforms.depthMap0.value = this.pano0.depthTex 
+            this.uniforms.cameraHeight0.value = this.pano0.floorPosition.distanceTo(this.pano0.position)
+            this.uniforms.ceilHeight0.value = this.pano0.getCeilHeight() - this.pano0.position.z  
+        }
+        if(this.pano1){ 
+            this.uniforms.depthMap1.value = this.pano1.depthTex 
+            this.uniforms.cameraHeight1.value = this.pano1.floorPosition.distanceTo(this.pano1.position)
+            this.uniforms.ceilHeight1.value = this.pano1.getCeilHeight() - this.pano1.position.z  
+        } 
         this.updateDepthTexEnable()
     }
     

+ 12 - 3
src/custom/modules/panos/DepthImageSampler.js

@@ -73,16 +73,25 @@ class DepthImageSampler {
         let distance = this.getDepth(uv.x, uv.y);
         //console.log('depth', depth,  uv.y)
         if (!distance){
+            const margin =  0.1
             if(uv.y > 0.75){//漫游点底部识别不到的区域,给一个地板高度
                 //let height = origin.distanceTo(currentPano.floorPosition); 
-                const margin =  0.1
+                
                 distance = (currentPano.floorPosition.z - origin.z - margin) / dir.z
                 location.copy(dir).multiplyScalar(distance).add(origin);
                 let normal = new THREE.Vector3(0,0,1)
                 
                 return {location, normal, distance} 
-            }
-            else return !1;  //应该是天空或模型外 , 因为很少有漫游点的地方还拍不到地板
+            }else if(uv.y < 0.25){
+                let ceilZ = currentPano.getCeilHeight()
+                if(ceilZ == Infinity)return !1
+                else{ 
+                    distance = (ceilZ - origin.z - margin) / dir.z
+                    location.copy(dir).multiplyScalar(distance).add(origin);
+                    let normal = new THREE.Vector3(0,0,-1)
+                    return {location, normal, distance} 
+                } 
+            }return !1;  //应该是天空或模型外 , 因为很少有漫游点的地方还拍不到地板
         }  
         
         //this.mainDepth = depth

File diff suppressed because it is too large
+ 618 - 598
src/custom/modules/panos/Images360.js


+ 40 - 0
src/custom/modules/panos/Panorama.js

@@ -561,6 +561,46 @@ class Panorama extends THREE.EventDispatcher{
         //删除tile贴图、depthTex等以后再写
     }
     
+    
+    getCeilHeight(){//天花板高度值   (假设不存在depth为0的点,所有为0的要么是在盲区,要么是无穷远。)
+         
+        if(this.ceilZ == void 0){
+            const depthTiming = Potree.timeCollect.depthSampler.median    //pc firefox达到4.  chrome为0.01
+                     
+            
+            //用三个间隔120度散开,和中心垂直线成一定夹角的三个向量去求 最高高度 (不求平均的原因:万一是0不好算)
+            let rotMat = new THREE.Matrix4().makeRotationX(THREE.Math.degToRad(40))// 角度不能小于天花板中空的半径,大概就是0.2*Math.PI=36度
+             
+            let dirs = [new THREE.Vector3(0,0,1).applyMatrix4(rotMat)];
+            if(depthTiming < 1){
+                let rotMat1 = new THREE.Matrix4().makeRotationZ(Math.PI*2 / 3);
+                dirs.push(dirs[0].clone().applyMatrix4(rotMat1))
+            }
+            if(depthTiming < 0.3){
+                let rotMat2 = new THREE.Matrix4().makeRotationZ(-Math.PI*2 / 3);
+                dirs.push(dirs[0].clone().applyMatrix4(rotMat2)); 
+            }
+             
+            let zs = dirs.map(dir_=>{ 
+                let intersect = viewer.images360.getIntersect(this, dir_) 
+                let z = intersect ? intersect.location.z : Infinity/* this.position.z+skyHeight */ //没有intersect代表可能是天空
+                return z 
+            })
+            zs.sort((a,b)=>{return b-a});//得最大值  (不用中位数的原因:在屋檐处,如果仅有一个intersect是天空,因到了室外所以也用天空高度)
+            
+             
+            this.ceilZ = zs[0]
+            let min = this.position.z + 1  // 防止意外太低
+            this.ceilZ = Math.max(min, this.ceilZ)
+            //console.log(this.id, 'ceilZ:', this.ceilZ )
+        }
+        
+        return this.ceilZ 
+
+    
+        
+    }
+    
 };