Selaa lähdekoodia

fix: highMap更新为tile后

xzw 1 vuosi sitten
vanhempi
commit
a99eca5671

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

@@ -1973,6 +1973,7 @@ export class Images360 extends THREE.EventDispatcher{
             
             var geo = new THREE.PlaneGeometry(1, 1, 1, 1)
             var cube = new THREE.Object3D;
+            cube.tiles = []
             for(var cubeIndex=0; cubeIndex<6; cubeIndex++){
                 var face = new THREE.Object3D;
                 for(var i=0;i<8;i++){
@@ -1993,6 +1994,11 @@ export class Images360 extends THREE.EventDispatcher{
                         }
                         
                         tile.visible = false 
+                        tile.tileX = i
+                        tile.tileY = j
+                        tile.cubeFace = cubeIndex
+                        //tile.renderOrder = RenderOrder.highTileCube
+                        cube.tiles.push(tile)
                         face.add(tile)
                     }
                 }
@@ -2025,6 +2031,7 @@ export class Images360 extends THREE.EventDispatcher{
                    
                 }  
                 face.scale.set(1,-1,1)
+                face.cubeFace = cubeIndex
                 cube.add(face) 
             }
             cube.name = 'highMapCube'
@@ -2040,6 +2047,25 @@ export class Images360 extends THREE.EventDispatcher{
             Potree.Utils.setObjectLayers(this.highMapCube, 'sceneObjects'/* 'skybox' */) //因它的深度是错误的,故不在skybox层渲染,影响edlRT, 而在renderOverlay时渲染覆盖。
             //console.warn('addHighMapCube')
             
+            
+            viewer.addEventListener('update',()=>{
+                if (this.highMapCube.visibleTiles) {
+                    this.updateTiles() //逐步将visibleTiles加载完
+                } 
+            })
+            
+            viewer.addEventListener('camera_changed',(e)=>{ 
+                //重新获取visibleTiles
+                Common.intervalTool.isWaiting(
+                    'update4kTiles',
+                    () => {
+                        console.log('update4kTiles')
+                        let vectorForward = this.getDirection()
+                        this.updateTiles(vectorForward)
+                    },
+                    500
+                ) 
+            })  
         }    
         
     }
@@ -2051,9 +2077,93 @@ export class Images360 extends THREE.EventDispatcher{
     }
     
     
-    updateHighMap(tex, cubeFace, tileX, tileY){ 
+    updateTiles(direction) {
+        if (!this.highMapCube || !this.highMapCube.visible) return
+
+        if (this.highMapCube.tiles.filter(e => e.image).length <= 10) return //加载的太少了
+        //performance.mark('updateTiles-start')
+
+        if (direction) {
+            let camera = viewer.mainViewport.camera
+            let hfov = cameraLight.getHFOVForCamera(camera, true) / 2
+            let vfov = THREE.MathUtils.degToRad(camera.fov) / 2
+            /* let hcos = Math.cos(hfov / 2)
+            let vcos = Math.cos(vfov / 2)  */
+            let list = this.highMapCube.tiles
+            list.forEach(e => {
+                //屏幕外的不显示
+                let pos = e.getWorldPosition(new THREE.Vector3())
+                let dir = new THREE.Vector3().subVectors(pos, this.highMapCube.position).normalize()
+
+                let hcos_ = dir.clone().setY(direction.y).normalize().dot(direction) //在direction的斜面上水平角度差
+                let hRad = Math.acos(hcos_)
+                let vRad = -200
+                if (hRad > hfov + 0.1) {
+                    e.score = -100
+                } else {
+                    vRad = Math.abs(Math.acos(dir.y) - Math.acos(direction.y))
+                    if (vRad > vfov + 0.1) {
+                        e.score = -100
+                    } else {
+                        e.score = -(hRad / hfov + vRad / vfov)
+                    }
+                }
+                e.scores = hRad.toFixed(3) + ', ' + vRad.toFixed(3)
+
+                if (e.score == -100) {
+                    this.resetTile(e)
+                }
+            })
+            this.highMapCube.visibleTiles = list.filter(e => e.score > -100)
+            //list.forEach(e=>e.scoreLabel.setText(e.scores))
+        }
+
+        let needRecover = this.highMapCube.visibleTiles.filter(e => !e.material.map)
+
+        if (needRecover.length) {
+            let maxCount = Common.getBestCount( '4kmaxTileRecover',  0,  2,   1.5,   6,  false, 2 )
+            let count = 0
+            console.log(maxCount)
+            needRecover.forEach((e, i) => {
+                //只更新若干个,因为太耗时了, 其余的等下帧更新
+                if (count >= maxCount) return
+                let r = this.recoverTile(e)
+                if (r) count++
+            })
+        }
+    }
+    
+    
+    getHighImage(image, cubeFace, tileX, tileY) {
+        let tile = this.highMapCube.children[cubeFace].children[tileX * 8 + tileY]
+        tile.image = image //先记录下来
+    }
+    
+    
+    
+     
+    updateHighMap(image, cubeFace, tileX, tileY){ 
         //console.warn('updateHighMap')
         var tile = this.highMapCube.children[cubeFace].children[tileX*8+tileY]; 
+        if (image) tile.image = image //先记录下来
+        if(tile.material.map)return
+        
+        if (this.highMapCube.visibleTiles && !this.highMapCube.visibleTiles.includes(tile) /* this.highMapCube.texLoadedCount >= this.getMaxTileCount() */) {
+            return
+        }
+        
+        //简易创建贴图
+        /* var tex = this.$app.core.get('SceneRenderer').initSizedTexture2D(512, THREE.ClampToEdgeWrapping)
+        //var loaded = this.$app.core.get('Player').model.isHighMapLoaded(tile.cubeFace, tile.tileX, tile.tileY)
+        this.$app.core.get('SceneRenderer').uploadTexture2D(image, tex, 0, 0, 512, 512) //只替换tex对应的img,不新建
+         */
+        var tex = new THREE.Texture()
+        tex.image = image
+        tex.flipY = false
+        tex.wrapS = tex.wrapT = THREE.ClampToEdgeWrapping
+        tex.generateMipmaps = false
+        tex.minFilter = THREE.LinearFilter
+        tex.needsUpdate = true
         
         tile.material.map = tex;
         
@@ -2065,31 +2175,58 @@ export class Images360 extends THREE.EventDispatcher{
         tile.material.needsUpdate = true  //发现每次开始放大但还未放大到4k时也会把之前加载过的4k加载
     }
     
+    recoverTile(tile) {
+        if (tile.material.map) return
+        if (tile.image) {
+            this.updateHighMap(tile.image, tile.cubeFace, tile.tileX, tile.tileY)
+            return true
+        } else {
+            //console.log('no image')
+        }
+    }
+    
+    resetTile(tile, kill) {
+        if (kill) {
+            //完全消灭
+            tile.image = null
+        }
+
+        let map = tile.material.map
+        if (map) {
+            map.dispose() //这句执行了以后,h.__webglTexture一直就是undefined
+            map.loaded = !1
+            map.version = 0
+
+            //保底再执行一下这个,类似app.sceneRenderer.deallocateCubeTexture(tile.material.map)
+            var h = viewer.renderer.properties.get(map)
+            //console.log('__webglTexture',!!h.__webglTexture)
+            viewer.renderer.getContext().deleteTexture(h.__webglTexture)
+
+            tile.material.map = null
+
+             
+            tile.material.needsUpdate = true
+            tile.visible = false
+
+            //this.highMapCube.texLoadedCount --
+            //console.log('resetTile'/* , tile.cubeFace, tile.tileX, tile.tileY */)
+        }
+    }    
+    
     
     
-    resetHighMap(){ 
     
-        if(!this.highMapCube)   return 
-        //console.warn('resetHighMap')
-        this.highMapCube.children.forEach(e=>e.children.forEach(tile=>{
-            if(tile.material.map){
-                tile.material.map.dispose() //这句其实无效。本来可以使用three自带的deallocateTexture(texture),但因为创建的方式不是普通的new Texture,所以并没有onTextureDispose的侦听,故要自己写
-                tile.material.map.loaded = !1 
-                tile.material.map.version = 0 
-                
-                //这两句才是真正释放贴图资源的 ,类似app.sceneRenderer.deallocateCubeTexture(tile.material.map)
-                var h = viewer.renderer.properties.get(tile.material.map)
-                viewer.renderer.getContext().deleteTexture(h.__webglTexture)
-                //类似app.sceneRenderer.deallocateCubeTexture(tile.material.map) 
-                  
-                tile.material.map = null            
-                /* tile.material.opacity = 0.4;
-                tile.material.transparent = true */
-                tile.material.needsUpdate = true
-                tile.visible = false 
-            }
-        }))
+    resetHighMap() {
+        if (!this.highMapCube) return
+        this.highMapCube.children.forEach(e =>
+            e.children.forEach(tile => {
+                this.resetTile(tile, true)
+            })
+        )
+        //this.highMapCube.texLoadedCount = 0
+        this.highMapCube.visibleTiles = null
         this.hideHighMap()
+        //console.log('resetHighMap')
     }
     
     setHighMap(pano){ 

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

@@ -970,27 +970,27 @@ PanoRenderer.prototype.uploadTile = function () {//重写
                 E = tileSize / panoSize * size, // tile在renderTarget上渲染出的宽度
                 b = C / panoSize * size,  // tile在renderTarget上渲染的startX
                 w = I / panoSize * size;  // tile在renderTarget上渲染的startY
-            collection[tileSize] || (collection[tileSize] = this.initSizedTexture2D(tileSize, THREE.ClampToEdgeWrapping));
-             
              
             if(panoSize > this.qualityManager.maxRenderTargetSize ){ //4096 改
-                var tex = this.initSizedTexture2D(tileSize, THREE.ClampToEdgeWrapping);
-                var loaded = this.viewer.images360.isHighMapLoaded(info.cubeFace, tileX,tileY)                 
-            }else{ 
-                var tex = collection[tileSize]; 
-            }                    
-            this.uploadTexture2D(img, tex, 0, 0, tileSize, tileSize);//只替换tex对应的img,不新建
-            
-            if(panoSize > this.qualityManager.maxRenderTargetSize){
-                loaded || this.viewer.images360.updateHighMap(tex, info.cubeFace, tileX,tileY)
+                /* var tex = this.initSizedTexture2D(tileSize, THREE.ClampToEdgeWrapping);
+                var loaded = this.viewer.images360.isHighMapLoaded(info.cubeFace, tileX,tileY)   */ 
+                this.viewer.images360.getHighImage(img, info.cubeFace, tileX, tileY)                
+            }else{  
+                collection[tileSize] || (collection[tileSize] = this.initSizedTexture2D(tileSize, THREE.ClampToEdgeWrapping));
+                var tex = collection[tileSize];
              
-            }else{ 
-                if (1 === overlayStyle || 2 === overlayStyle) {
-                    var T = 1 === overlayStyle ? this.overlayTilesBasic : this.overlayTilesEnhanced;
-                    this.renderToCubeMap(tex, renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace);
-                    this.renderToCubeMap(T[panoSize], renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace, THREE.NormalBlending, !0, .5);
-                } else { 
-                    this.renderToCubeMap(tex, renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace);
+                this.uploadTexture2D(img, tex, 0, 0, tileSize, tileSize);//只替换tex对应的img,不新建
+                  
+                if(panoSize > this.qualityManager.maxRenderTargetSize){
+                    loaded || this.viewer.images360.updateHighMap(tex, info.cubeFace, tileX,tileY) 
+                }else{ 
+                    if (1 === overlayStyle || 2 === overlayStyle) {
+                        var T = 1 === overlayStyle ? this.overlayTilesBasic : this.overlayTilesEnhanced;
+                        this.renderToCubeMap(tex, renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace);
+                        this.renderToCubeMap(T[panoSize], renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace, THREE.NormalBlending, !0, .5);
+                    } else { 
+                        this.renderToCubeMap(tex, renderTarget, tileSize, tileSize, 0, 0, tileSize, tileSize, b, w, E, E, info.cubeFace);
+                    }
                 }
             }
             done()

+ 32 - 22
src/custom/utils/Common.js

@@ -342,28 +342,38 @@ var Common = {
         }
     },
      
-   
- 
-    getBestCount : function(name, minCount=1,maxCount=6, durBound1 = 1.2, durBound2 = 10, ifLog){
-       
-       
-        let timeStamp = performance.getEntriesByName("loop-start");
-        let count
-        if(timeStamp.length){
-            let dur = performance.now() - timeStamp[timeStamp.length-1].startTime;  //dur在iphoneX中静止有7,pc是2
-           
-            count = Math.round(math.linearClamp(dur, durBound1,durBound2,   maxCount,  minCount))
-             
-            if(ifLog){//注意,console.log本身用时挺高, 降4倍时可能占用0.5毫秒
-               name   && count  && console.log(name,   count , ' ,dur:', dur.toFixed(3))
-            } 
-        }else{
-            count = maxCount  //  ? 
-        } 
-        
-        //主要在手机端有效果。 
-        return count 
-    },
+    
+    getBestCount : (function(){
+        let lastCount = {}
+        return function(name, minCount=1,maxCount=6, durBound1 = 1.2, durBound2 = 10, ifLog, maxHistory){ 
+            let timeStamp = performance.getEntriesByName("loop-start");
+            let count
+            if(timeStamp.length){
+                let dur = performance.now() - timeStamp[timeStamp.length-1].startTime;  //dur在iphoneX中静止有7,pc是2
+               
+                count = Math.round(math.linearClamp(dur, durBound1,durBound2,   maxCount,  minCount))
+                 
+                if (maxHistory) {
+                    if (!lastCount[name]) lastCount[name] = []
+                    if (count == 0 && lastCount[name].length > maxHistory - 1 && !lastCount[name].some(e => e > 0)) {
+                        count = 1
+                    }
+                    lastCount[name].push(count)
+                    if (lastCount[name].length > maxHistory) lastCount[name].splice(0, 1)
+                }  
+                 
+                 
+                 
+                if(ifLog){//注意,console.log本身用时挺高, 降4倍时可能占用0.5毫秒
+                   name   && count  && console.log(name,   count , ' ,dur:', dur.toFixed(3))
+                } 
+            }else{
+                count = maxCount  //  ? 
+            }  
+            //主要在手机端有效果。 
+            return count 
+        }
+    })(),