Explorar o código

测试新的map3d

xzw hai 8 meses
pai
achega
61beeb3dc3

+ 125 - 41
libs/three.js/3dtiles/three-loader-3dtiles.esm.js

@@ -8646,8 +8646,7 @@ function createSphere(sphere, transform, result) {
     result.center = center;
     result.radius = radius;
     return result;
-  }
-
+  } 
   return new BoundingSphere(center, radius);
 }
 
@@ -9102,14 +9101,18 @@ class TilesetTraverser {
     return tile.contentAvailable && !this.options.skipLevelOfDetail;
   }
 
-  shouldRefine(tile, frameState, useParentMetric) {
+  shouldRefine(tile, frameState, useParentMetric) {// 是否更新更精细的模型 canTraverse
+    if (tile.tileset.options.loadMaxLevelDirect) {
+        return true //xzw add : 直接加载到最高清晰度,用于截图  //是只加载屏幕里的吗
+    }
     let screenSpaceError = tile._screenSpaceError;
 
     if (useParentMetric) {
       screenSpaceError = tile.getScreenSpaceError(frameState, true);
     }
-
-    return screenSpaceError > this.options.maximumScreenSpaceError;
+    let maxSSE = this.options.maximumScreenSpaceError;
+    if(tile.tileset.root.header.boundingVolume.sphere) maxSSE /= 5 //cesium那边的自带坐标的模型
+    return screenSpaceError >  maxSSE; // 距离越近,SSE越大
   }
 
   updateTileVisibility(tile, frameState) {
@@ -9623,7 +9626,11 @@ class TileHeader {
   }
 
   _initializeTransforms(tileHeader) {
-    this.transform = tileHeader.transform ? new Matrix4(tileHeader.transform) : new Matrix4(); 
+    //xzw改
+    let transform = tileHeader.transform // || tileHeader.boundingVolume.sphere && [1,0,0,0, 0,1,0,0,  0,0,1,0,  ...tileHeader.boundingVolume.sphere.slice(0,3),1 ]  //xzw add
+    this.transform = transform ? new Matrix4(transform) : new Matrix4(); 
+      
+    //this.transform = tileHeader.transform ? new Matrix4(tileHeader.transform) : new Matrix4(); 
     const parent = this.parent;
     const tileset = this.tileset;
     const parentTransform = parent && parent.computedTransform ? parent.computedTransform.clone() :  new Matrix4().elements // tileset.modelMatrix.clone();  改:去掉左乘modelMatrix
@@ -9700,7 +9707,8 @@ class TileHeader {
         console.log('root_0')  
     }  */ 
     if(!this.tileset.lastRootTransform){//没事过后会因_updateTransform重算
-        computedTransform = new Matrix4(this.tileset.modelMatrix).multiplyRight(this.computedTransform);  //add
+        /* if(header.boundingVolume.sphere) computedTransform = new Matrix4(this.tileset.modelMatrix)//xzw改
+        else  */computedTransform = new Matrix4(this.tileset.modelMatrix).multiplyRight(this.computedTransform);  //add
     }else{
         computedTransform = new Matrix4(new Matrix4$1().multiplyMatrices(this.tileset.lastRootTransform, this.getContentTransform()).elements)
     }
@@ -9709,6 +9717,9 @@ class TileHeader {
     this.boundingVolume = createBoundingVolume(header.boundingVolume, computedTransform/* this.computedTransform */, this.boundingVolume);
     const content = header.content;
     
+    //if(this.boundingVolume.center.y > 500){
+       // console.log(this.boundingVolume.center)
+    //}
  
     if (!content) {
       return;
@@ -9726,9 +9737,7 @@ class TileHeader {
   
   
     getBoundUntransformed(){//add 这个会在mesh加载好后才会执行
-        if(!this.contentTransform){
-            console.error('?')
-        }
+        
         this.getContentTransform()
          
         let computedTransform2 = new Matrix4(this.contentTransform.elements)  
@@ -9743,30 +9752,41 @@ class TileHeader {
 
 
     getContentTransform(force){ //add 获取该tile在创建boundingVolume时需要的matrix,不包含最外层对整体模型的变换.
+        
         let rtcCenter, contentTransform
         if(this.contentTransform && !force){//无需更新
             return this.contentTransform.clone()
         } 
         
-        if(!this.tileset.tileTransInvert){
-            this.tileset.tileTransInvert = new Matrix4() 
-        }
         
-        this.contentTransform = new Matrix4$1().fromArray(this.computedTransform).premultiply(new Matrix4$1().fromArray(this.tileset.tileTransInvert))
-
-        if(this.tileContent){ 
-            rtcCenter = this.content.rtcCenter 
+        
+        if(this.header.boundingVolume.sphere){   
+            this.contentTransform = this.tileset.root.header.boundingVolume.rotGeoToZeroMat
+         
         }else{
-            rtcCenter = this.rtcCenterState
+        
+            if(!this.tileset.tileTransInvert){
+                this.tileset.tileTransInvert = new Matrix4() 
+            }
+            
+            this.contentTransform = new Matrix4$1().fromArray(this.computedTransform).premultiply(new Matrix4$1().fromArray(this.tileset.tileTransInvert))
+            
+            rtcCenter = !!this.tileset.root.header.boundingVolume.sphere //针对适应cesium的自带坐标的模型
+            if(!rtcCenter){
+                if(this.tileContent){ 
+                    rtcCenter = this.content.rtcCenter 
+                }else{
+                    rtcCenter = this.rtcCenterState
+                }
+            }
+          
+            if(!rtcCenter) {
+                let tranM = new Matrix4$1()  
+                tranM.makeScale(1,1,-1)//大部分是这种情况.  就是因为这个变换才加的这个函数,之前bounding没考虑这个不准。不知道为什么原生的代码不用scaleZ
+                this.contentTransform.premultiply(tranM) 
+            } 
+            //如果有rtcCenter的话一开始boundingVolume不准?会不会有显示问题?
         }
-      
-        if(!rtcCenter) {
-            let tranM = new Matrix4$1()  
-            tranM.makeScale(1,1,-1)//大部分是这种情况.  就是因为这个变换才加的这个函数,之前bounding没考虑这个不准。不知道为什么原生的代码不用scaleZ
-            this.contentTransform.premultiply(tranM) 
-        } 
-        //如果有rtcCenter的话一开始boundingVolume不准?会不会有显示问题?
- 
         return this.contentTransform.clone()
     }
 
@@ -10381,6 +10401,24 @@ class Tileset3D extends EventDispatcher{//xzw add EventDispatcher
   }
 
   _initializeTileSet(tilesetJson) {
+    if(tilesetJson.root.boundingVolume.sphere){//xzw add 针对适应cesium的自带坐标的模型
+        //this.boundWhole = new THREE.Box3  
+        
+        tilesetJson.root.boundingVolume.sphereOri = tilesetJson.root.boundingVolume.sphere      //cesium坐标
+        tilesetJson.root.boundingVolume.sphere = [0,0,0,tilesetJson.root.boundingVolume.sphere[3]]
+        
+        //将其转到地球正面(经纬度0,0)
+        let origin = new THREE.Vector3().fromArray(tilesetJson.root.boundingVolume.sphereOri)
+        let qua = Potree.math.getQuaFromPosAim(new THREE.Vector3, origin.normalize() ) //法向量
+        let quaInv = qua.invert()//这样就能朝向(0,0,-1)
+        //viewer.objs.children[0].applyQuaternion(quaInv)
+        let lastQua = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI,0,Math.PI))//最后翻转下修正 测出来的
+        //viewer.objs.children[0].applyQuaternion(qua1)
+        quaInv.premultiply(lastQua)
+        tilesetJson.root.boundingVolume.rotGeoToZeroMat = new THREE.Matrix4().makeRotationFromQuaternion(quaInv)
+        //尚不知是否所有sphere的都带坐标,不是的话再说
+    }  
+      
     this.root = this._initializeTileHeaders(tilesetJson, null);
 
     if (this.type === TILESET_TYPE.TILES3D) {
@@ -10425,11 +10463,30 @@ class Tileset3D extends EventDispatcher{//xzw add EventDispatcher
     this.stats.get(POINTS_COUNT, 'memory');
     this.stats.get(TILES_GPU_MEMORY, 'memory');
   }
-
-  _initializeTileHeaders(tilesetJson, parentTileHeader) {
+ 
+ 
+  changeHeaderBoundSphere(header, json){//add 去掉 适应cesium的自带坐标的模型的位移
+    if(header.boundingVolume.sphereOri )return //is root
+    const rootVolume = this.root ? this.root.header.boundingVolume : json.root.boundingVolume 
+    
+    if(header.boundingVolume.sphere){ 
+       
+       header.boundingVolume.sphereOri = header.boundingVolume.sphere
+       for(let i=0;i<3;i++){
+           header.boundingVolume.sphere[i] -= rootVolume.sphereOri[i]
+       } 
        
+       let center = new THREE.Vector3(...header.boundingVolume.sphere)
+       //this.boundWhole.expandByPoint(center) 
+    } 
+  }
+ 
+  _initializeTileHeaders(tilesetJson, parentTileHeader) {//建立该tileset的某个json所有tile     xzw改
+    
+   
+    this.changeHeaderBoundSphere(tilesetJson.root, tilesetJson)//add
     const rootTile = new TileHeader(this, tilesetJson.root, parentTileHeader, parentTileHeader == void 0 && 'root_'+tilesetSid++);
-
+ 
     if (parentTileHeader) {
       parentTileHeader.children.push(rootTile);
       rootTile.depth = parentTileHeader.depth + 1;
@@ -10447,6 +10504,7 @@ class Tileset3D extends EventDispatcher{//xzw add EventDispatcher
         // !zeg改  
         if(tile.depth < /* this.options. */maxDepth){                                     
             for (const childHeader of children) {
+                this.changeHeaderBoundSphere(childHeader, tilesetJson) //xzw add
               const childTile = new TileHeader(this, childHeader, tile);
               tile.children.push(childTile);
               childTile.depth = tile.depth + 1;
@@ -10456,7 +10514,9 @@ class Tileset3D extends EventDispatcher{//xzw add EventDispatcher
         window.maxTileDepth = Math.max(window.maxTileDepth||0,   tile.depth)
       }
     }
-
+    
+    
+    
     return rootTile;
   }
 
@@ -16846,7 +16906,7 @@ function normalizeTileData(tile, options) {
   tile.id = tile.contentUrl;
   tile.lodMetricType = LOD_METRIC_TYPE.GEOMETRIC_ERROR;
   tile.lodMetricValue = tile.geometricError;
-  tile.transformMatrix = tile.transform;
+  tile.transformMatrix = tile.transform 
   tile.type = getTileType(tile);
   tile.refine = getRefine(tile.refine);
   return tile;
@@ -17572,6 +17632,9 @@ class Loader3DTiles {
                 props.loadingManager.itemStart(url);
             }
             const tilesetJson = yield load(url, Tiles3DLoader, Object.assign({}, loadersGLOptions));
+            
+            
+            
             const renderMap = {};
             const boxMap = {};
             const unloadQueue = [];
@@ -18092,25 +18155,25 @@ function createGLTFNodes(gltfLoader, tile, unlitMaterial, options, rootTransform
                      
                     tile.rtcCenterState = rtcCenterGlobal = !!tile.content.rtcCenter
                     
+                    let translate = tile.content.rtcCenter || tile.header.boundingVolume.sphere //大部分模型无 rtcCenter
+                      
                     let contentTransform = tile.getContentTransform(needUpdate)
                     
-                    if(tile.content.rtcCenter){//大部分模型无 rtcCenter
-                        //console.error('rtcCenter有?!') //似乎bounding中包含这个信息了 所以getContentTransform不含这个
+                    if(translate){ //需要位移后才和boundingVolume一样
                         let tranM = new Matrix4$1()   
-                        tranM.makeTranslation(tile.content.rtcCenter[0], tile.content.rtcCenter[1], tile.content.rtcCenter[2])
-                        contentTransform.premultiply(tranM)
-                    }
-                    
+                        tranM.makeTranslation(...translate)
+                        contentTransform.multiply(tranM) 
+                    } 
+                     
                     if(needUpdate ){
                         tile._updateBoundingVolume(tile.header) //add  重新更新
-                    }
-                       
+                    } 
                     if (shouldRotate) { //大部分模型 无需 Rotate
                         contentTransform.multiply(rotateX); // convert from GLTF Y-up to Z-up
                     }
-                      
                     tileContent.applyMatrix4(contentTransform);
                     
+                    
                     //'https://testgis.4dage.com/LVBADUI_qp/tileset.json', //村庄 这个案例是 要rotateX 且有rtcCenter的。boundingVolume已经是转换这两者后的值所以getContentTransform不加这个
                     
                     //tile总共要左乘的矩阵 rotateX -> tileTransInvert * computedTransform -> 对geometry的tranM修改 -> 整个模型的matrixWorld
@@ -18287,6 +18350,8 @@ class tileset3D 最外层整体。 获取方法: viewer.objs.children[index].run
 class tileHeader 也就是tileset里面的一个个tile 。  其上有.tileset
 
 
+_initializeTileSet(tilesetJson) 
+_initializeTileHeaders(tilesetJson, parentTileHeader)  //json里tile初始化
 
 
 
@@ -18323,8 +18388,27 @@ viewer.objs.children[0].runtime.getTileset().tiles
 tile.depth最低为1 , root是0
 
 
+===============
+带坐标osgb参考ces初始化位置  (用付费软件转的那个)特点:tileset.json里的boundingVolume有sphere而非box,无transform
+用另一个工程 3DTilesRendererJS 也显示不出来。 改了很多代码才显示对。
+思路:把json里的sphere.center提取出来,作为最后默认的position,这样模型就在原点上,很多变量都是000了,简化很多。
+和box型的不同的是,需要手动将children里的也按照其sphere.center(减去外层的原始center)位移。box的似乎geo里已经位移好了。
+ 
+然后会看到模型是斜的,如案例港湾一号的mesh,因cesium中地球正面为经纬度0,0的位置,在非洲左侧,对应x轴正向,右侧为y轴正向。
+模型位于地球右侧靠后上一点,朝向地心。所以把它转正一下就行了。 (现在写进了rotGeoToZeroMat)
+ 
+原始center为cesium坐标,要转化为经纬度再用:
+let lonlat = Potree.sdk.cesMath.fromCes(center, true) 
+let pos = viewer.transform.lonlatToLocal.forward(lonlat)    // {x:113.5933488,y:22.36711151}
+model.position.copy(pos)     
+
+ 
+
+cesium显示:http://192.168.0.59:1234/examples/tomcat/allTest/Cesium-3dTiles/index.html
+tile.header.boundingVolume.sphere 应用上变换才是 tile.boundingVolume.center 
+
 
-============
+==============
 
 3dtiles在四维看看和激光里摆放不同,这里的需要位移一段距离才能和四维看看一样,也就是和无transform后的点云一样。
 见load4dkkPanos函数

+ 4 - 2
src/custom/mergeStartTest.js

@@ -318,11 +318,13 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
     //viewer.setControls(viewer.orbitControls) 
      
       
-               
+                
             
     let tilesetUrls = [   
         'http://192.168.0.25/oss/manage/media-library/result/test/tileset.json',
         'https://4dkk.4dage.com/scene_view_data/SG-t-GvKLWIKfJGC/images/3dtiles/tileset.json?_=1742785956443',
+        `${Potree.resourcePath}/models/3dtiles/CC/tileset.json`, 
+        'https://testgis.4dage.com/LVBADUI_qp/tileset.json', //村庄   含rtcCenter 
         'https://4dkk.4dage.com/fusion/test/b3dm/modelId_11947/tileset.json',//json有的包含多个materials,之前会花掉,现在解决了
         'https://4dkk.4dage.com/fusion/testb3dm/test001/tileset.json',  //体育中心
       // `${Potree.resourcePath}/models/3dtiles/SG-CPwbgVaPvcY/tileset.json`,
@@ -351,7 +353,7 @@ var start = function(dom, mapDom, number, fileServer, webSite){ //t-Zvd3w0m
         //'https://4dkk.4dage.com/fusion/test/model/modelId_570/3dt/3dtiles.json', //only has boundingVolume.sphere  拉远了特别模糊,凑近了模型不太对
         
         
-    ], tileIndex = 0
+    ], tileIndex = Potree.browser.urlHasValue('tileIndex',true) || 0
     
      let glbUrls = [ 
      

+ 7 - 7
src/custom/modules/mergeModel/MergeEditor.js

@@ -1151,18 +1151,18 @@ let MergeEditor = {
             
             resolved = true
         } 
-        
+         
         let min = overRatio > 1 ? 1.1 : 1.5,   max = 5;  
         Potree.settings.maxLRUPoints = THREE.Math.clamp(Potree.settings.maxLRUPoints , Potree.pointBudget * min, Potree.pointBudget * max)
-                 
+                  
         //压缩时先压缩缓存,然后是使用内存; 恢复时相反。
         
         //3dtiles不像点云那样可以在加载时拦截,使不高于tiles3DMaxMemory,只能自动动态调节maxSSE,所以有可能调节完还是降低不了
           
         //一次只更新一点,一点点调节,因为可能不是一个原因造成
           
-        
-          
+         
+            
         
         let changed
         if(old.pointBudget != Potree.pointBudget || old.tiles3DMaxMemory != Potree.settings.tiles3DMaxMemory || old.maxLRUPoints != Potree.settings.maxLRUPoints ){
@@ -1172,12 +1172,12 @@ let MergeEditor = {
                     model.runtime.getTileset().nextForceUpdate = true  
                     model.runtime.getTileset().needRenderNext = true 
                 })
-            }else{
+            }else{  
                 viewer.dispatchEvent('content_changed')
-            } 
+            }  
             changed = true
         }
-        
+           
        {
             
             let mSSE = math.linearClamp(Potree.fpsRendered2, [2, 52], [500,  70]) //有效降低卡顿 和贴图变白概率。越卡越提高msse

+ 2 - 1
src/custom/objects/Sprite.js

@@ -5,9 +5,10 @@ import math from "../utils/math.js";
 const geo = new THREE.PlaneBufferGeometry(1,1)
 export default class Sprite extends THREE.Mesh{
     
-    constructor(options={}){  
+    constructor(options={}){ 
         super(geo, options.mat || new DepthBasicMaterial(options))/* ({map:options.map, useDepth:options.useDepth})) */
          
+          
         this.root = options.root || this;
         this.renderOrder = options.renderOrder != void 0 ? options.renderOrder : 4;
         this.pickOrder = options.pickOrder || 0

+ 1 - 0
src/custom/objects/TextSprite.js

@@ -31,6 +31,7 @@ export class TextSprite extends THREE.Object3D{
             })
         )
         this.add(this.sprite)
+        this.sprite.material.map = map
         
         this.fontWeight = options.fontWeight == void 0 ? 'Bold' : options.fontWeight
 		this.rectBorderThick = options.rectBorderThick || 0

+ 38 - 10
src/custom/start.js

@@ -881,10 +881,10 @@ export function mergeEditStart(dom, mapDom){
     }
     let confirmPos = ()=>{ 
         MergeEditor.focusOn(modelEditing)
-        cancelMove()  
+        cancelMove()   
         return {stopContinue:true}
     }
-    
+      
      
     
     let modelType,  modelEditing, MergeEditor = viewer.modules.MergeEditor
@@ -1254,29 +1254,56 @@ var changeLog = ()=>{
 }
  
  
+//screenshotTube({wallWidths:[1,0.5]},  500)  http://192.168.0.59:1234/examples/4dkk.html?m=SG-t-h8pBKI9M0WF#/
  
 //隧道截图  暂时测试时要等当前全景图都加载完。要保持放大才会4k
-window.screenshotTube = (width = 2048, height = 1024, initDir, compress=1)=>{ 
+window.screenshotTube = (width = 2048, height = 1024, disToWall=1.2,  compress=0.7, initDir )=>{ 
+    
+    if(width.wallWidths){//根据其他参数计算 
+        let wallWidths = width.wallWidths 
+        //disToWall : 相机到墙面的距离 1-2m 。 根据计算,截图width/height = 墙长/墙高 = half墙长 / camDis
+        //let longWallWidth = Math.max(wallWidths[0],wallWidths[1]) 
+        //let fullWidth = height * longWallWidth / disToWall  
+        //let r = fullWidth / 2 / longWallWidth //比率
+        let r = height / 2 / disToWall
+        
+        width = [ r *  wallWidths[0], r * wallWidths[1]  ]
+    }
+     
+    let offsetX 
+    if(width instanceof Array){//相机偏移,左右墙长度不同
+        let widths = width
+        width = widths[0] + widths[1] //相机左、右宽度
+        offsetX = (widths[1] - widths[0]) / 2
+    }
+    
+    
+    
+    
     
     let dataUrls = []
     
- 
-    let oldFov = viewer.mainViewport.camera.fov 
+    let camera = viewer.mainViewport.camera
+    let oldFov = camera.fov 
     viewer.setFOV(90);
     if(initDir){
         initDir = new THREE.Vector3(initDir.x, initDir.y, 0) //水平、垂直于墙面 
         viewer.mainViewport.view.direction = initDir  //初始角度 
     } 
-         
-    let yaw = viewer.mainViewport.view.yaw
-    let camDirs = [{yaw, pitch:0},{yaw:yaw + Math.PI,pitch:Math.PI/2}, {yaw:yaw + Math.PI, pitch:0}]
     
     
+    
+    let yaw = viewer.mainViewport.view.yaw
+    //let camDirs = [{yaw, pitch:0, offsetX}, {yaw:yaw + Math.PI, pitch:Math.PI/2, offsetX:-offsetX}, {yaw:yaw + Math.PI, pitch:0, offsetX:-offsetX}]
+    let camDirs = [{yaw:yaw + Math.PI, pitch:0, offsetX:-offsetX}, {yaw, pitch:Math.PI/2, offsetX},{yaw, pitch:0, offsetX}]
      
     
     let screenshot = (curIndex)=>{  
         viewer.mainViewport.view.yaw = camDirs[curIndex].yaw
         viewer.mainViewport.view.pitch = camDirs[curIndex].pitch
+        if(offsetX){
+            camera.setViewOffset(width, height, camDirs[curIndex].offsetX, 0 , width, height)  
+        }
         var {getImagePromise, finishPromise} = viewer.startScreenshot({ type: 'default',  hideMarkers: true  }, width, height  )
         finishPromise.done( ({dataUrl}) => {
             console.log('get', curIndex)
@@ -1285,10 +1312,11 @@ window.screenshotTube = (width = 2048, height = 1024, initDir, compress=1)=>{
                 dataUrls = [dataUrls.map(e=>{return {dataUrl:e, width, height}})]
                 dataUrls[0][0].rot180 = true 
                 Potree.Utils.combineImgs(dataUrls, compress).then((dataUrlWhole)=>{
-                    Potree.Common.downloadFile(dataUrlWhole, '隧道.png') 
+                    Potree.Common.downloadFile(dataUrlWhole, '隧道'+viewer.images360.currentPano.id+'.png') 
                     viewer.setFOV(oldFov);
+                    camera.clearViewOffset()
                 })  
-                viewer.mainViewport.view.yaw = yaw
+              
             }else{
                 screenshot(++curIndex)
             }  

+ 51 - 40
src/custom/viewer/ViewerNew.js

@@ -1,12 +1,15 @@
+    
+      
+//import * as GaussianSplats3D from "../../../libs/gaussian/gaussian-splats-3d.module.js";
  
-
-import * as GaussianSplats3D from "../../../libs/gaussian/gaussian-splats-3d.module.js";
-
 import {Loader3DTiles} from '../../../libs/three.js/3dtiles/three-loader-3dtiles.esm.js'; 
 import {OBJLoader} from "../../../libs/three.js/loaders/OBJLoader.js";
-import {MTLLoader} from "../../../libs/three.js/loaders/MTLLoader.js";
+import {MTLLoader} from "../../../libs/three.js/loaders/MTLLoader.js"; 
 import {GLTFLoader} from  "../../../libs/three.js/loaders/GLTFLoader.js"; 
-import {PLYLoader} from "../../../libs/three.js/loaders/PLYLoader.js";
+import {PLYLoader} from "../../../libs/three.js/loaders/PLYLoader.js"; 
+ 
+ 
+
 //--------以上文件只在部分工程中添加-------------------------
 
 import * as THREE from "../../../libs/three.js/build/three.module.js";
@@ -27,8 +30,10 @@ import {Renderer} from "../../PotreeRendererNew.js";
 //import {PotreeRenderer} from "../viewer/PotreeRenderer.js";
 import {EDLRenderer} from "../../viewer/EDLRendererNew.js";
 import {HQSplatRenderer} from "../../viewer/HQSplatRenderer.js";
-import {MapViewer} from "./map/MapViewer.js";
-                                                                 
+import {MapViewer} from "./map/MapViewer.js"; 
+import {Map3D} from "./map/Map3D.js"           
+
+                        
 import {NavigationCube} from '../../viewer/NavigationCube.js'
    
 //import {MapView} from "../viewer/map.js"; 
@@ -87,7 +92,7 @@ import RenderPass from '../materials/postprocessing/RenderPass.js'
 import FXAAShader from "../materials/postprocessing/FXAAShader.js"
 import OutlinePass from "../materials/postprocessing/OutlinePass.js"
 import BasicMaterial from '../materials/BasicMaterial.js'  
-    
+     
         
         
 //import {RoomEnvironment} from './RoomEnvironment.js'
@@ -558,6 +563,9 @@ export class Viewer extends ViewerBase{
                 
                 if(Potree.settings.editType != "pano" && (Potree.settings.editType != 'merge' /* || Potree.settings.showObjectsOnMap */) && !args.noMap){
                     this.mapViewer = new MapViewer(mapArea/* $('#mapGaode')[0] */)
+                    
+                    this.map3d = new Map3D(this)
+                    
                 }
                 
                 this.inputHandler = new InputHandler(this, this.scene.scene);
@@ -5503,8 +5511,8 @@ export class Viewer extends ViewerBase{
     
     //调试时显示transformControl来调节object
     transformObject(object){
-        let seleted = viewer.inputHandler.selection[0]
-        if(!object){//取消 
+        let seleted = viewer.inputHandler.selection[0] 
+        if(!object){//取消  
             seleted && viewer.inputHandler.toggleSelection(seleted);
             return
         }
@@ -5520,8 +5528,8 @@ export class Viewer extends ViewerBase{
         if(!viewer.inputHandler.selection.includes(object)){
             viewer.inputHandler.toggleSelection(object);   
         }
-    }
-    
+    }  
+      
     pointInWhichPointcloud(pos){//选择最接近中心的那个 使用boundSphere 
         let result = Common.sortByScore(this.scene.pointclouds,[],[
             (pointcloud)=>{ 
@@ -5601,9 +5609,9 @@ export class Viewer extends ViewerBase{
         // 设置加载进度的回调函数(可选)
         this.fileManager.onProgress = (item, loaded, total) => {
             if(loaded < total) this.fileManager.loading = true
-            console.log(`Loading ${item}: ${loaded} of ${total}`);
+            console.log(`Loading ${item}: ${loaded} of ${total}`); 
         };
-
+ 
         // 设置加载失败的回调函数(可选)
         /* this.fileManager.onError = (url) => {
             console.error(`Failed to load resource: ${url}`);
@@ -5634,16 +5642,16 @@ export class Viewer extends ViewerBase{
     modelLoaded(object, fileInfo_={}, done){//普通模型加载完以后
         object.isModel = true
         
-        let boundingBox = new THREE.Box3()
+        let boundingBox = new THREE.Box3() 
         if(fileInfo_.parentInfo){
-            object.name = fileInfo_.name   
+            object.name = fileInfo_.name     
             fileInfo_.parentInfo.loadedCount ++
             fileInfo_.parentInfo.modelGroup.add(object) 
             if(fileInfo_.parentInfo.loadedCount == fileInfo_.parentInfo.url.length){ 
                 return this.modelLoaded(fileInfo_.parentInfo.modelGroup, fileInfo_.parentInfo, done)
             }else{ 
-                return
-            }   
+                return 
+            }     
         }
         
         object.name = fileInfo_.name != void 0 ? fileInfo_.name :  Potree.Common.getNameFromURL(fileInfo_.url,true)  // fileInfo_.fileType
@@ -5660,12 +5668,12 @@ export class Viewer extends ViewerBase{
         /* let weight = Math.round((total / 1024 / 1024) * 100) / 100;*/
         console.log( '加载完毕:', fileInfo_.name, Common.getNameFromURL(fileInfo_.url), '耗时(ms)', fileInfo_.loadCostTime, /* 模型数据量:' + weight + 'M' */)
           
-           
+            
         if(fileInfo_.fileType == '3dTiles'){
             let isGroup = !object.runtime  
             let children = object.runtime ? [object] : object.children
-            
-            
+             
+             
             children.forEach(object =>{
                 let boundingBox_ = new THREE.Box3()
                 
@@ -5686,33 +5694,33 @@ export class Viewer extends ViewerBase{
                     let vecX = new THREE.Vector3( box[ 3 ], box[ 4 ], box[ 5 ] )
                     let vecY = new THREE.Vector3( box[ 6 ], box[ 7 ], box[ 8 ] );
                     let vecZ = new THREE.Vector3( box[ 9 ], box[ 10 ], box[ 11 ] );
-
+ 
                     const scaleX = vecX.length();
                     const scaleY = vecY.length();
                     const scaleZ = vecZ.length(); 
                     
                     boundingBox_.min.set( - scaleX, - scaleY, - scaleZ );
                     boundingBox_.max.set( scaleX, scaleY, scaleZ );
-                    
+                     
                     if(isGroup){//如果是多个拼成的,每个都保留原先在parent中的offset。 如果是外层,作为独立个体,不用理会位置信息,直接放中央。
                         object.position.copy(center)
                         object.position.z *= -1
                         boundingBox_.translate(object.position) //由于是内层,其位移会改变整体的boundingbox
-                    }
-                    
-                }else if(json.root.boundingVolume.sphere){
-                    let sphereData = json.root.boundingVolume.sphere
+                    } 
+                      
+                }else if(json.root.boundingVolume.sphereOri){
+                    let sphereData = json.root.boundingVolume.sphereOri
                     let center = new THREE.Vector3(...sphereData)
-                    let radius = sphereData[3] / 2
+                    let radius = sphereData[3]  
                     /* let sphere = new THREE.Sphere(center, radius) 
                     let box = sphere.getBoundingBox()
-                    boundingBox.copy(box) */
-                     
+                    boundingBox.copy(box) */  
+                           
                     boundingBox_.min.set( - radius, - radius, - radius );
                     boundingBox_.max.set( radius, radius, radius );
                     console.log('boundingVolume sphere',sphereData)
-                    boundingBox_.translate(center.negate())
-                    
+                    // boundingBox_.translate(center/* .negate() */)
+                     
                     //2025:很少有模型用这个,之前是哪个模型有的?目前看到cesium的模型有 'http://192.168.0.25/oss/manage/media-library/result/test/tileset.json',
                     
                 }else{
@@ -5722,8 +5730,8 @@ export class Viewer extends ViewerBase{
                 //中心点居然没用。可能是漏用了什么信息,也许这和LVBADUI_qp是散的有关。
                 //console.log('3d tiles json',json)
                 
-                json.root.refine = 'ADD';
-                json.refine = 'ADD';
+                /* json.root.refine = 'ADD';
+                json.refine = 'ADD'; */
                     
                 
                 boundingBox.union(boundingBox_)
@@ -5954,7 +5962,7 @@ export class Viewer extends ViewerBase{
             
         }else if(fileInfo.fileType == 'ply'){
             loaders.plyLoader.load( fileInfo.url, (geometry) => {
-                let object
+                let object 
                 console.log('ply加载完毕', geometry)
                 if(!geometry.index){//点云 
                     object = new THREE.Points(geometry, new THREE.PointsMaterial({vertexColors:true, size:0.02})) 
@@ -5964,14 +5972,14 @@ export class Viewer extends ViewerBase{
                 }       
                 loadDone(object)
             })
-            
+             
         }else if(fileInfo.fileType == '3dTiles'){ 
                         
-            let result = await Loader3DTiles.load({
+            let result = await Loader3DTiles.load({ 
                 url: fileInfo.url, 
-                gltfLoader : loaders.glbLoader, 
-                //renderer: SceneRenderer.renderer   
-                options: {      
+                gltfLoader : loaders.glbLoader,  
+                //renderer: SceneRenderer.renderer    
+                options: {       
                     //dracoDecoderPath: '../utils/loaders/DRACOLoader/draco',
                     //basisTranscoderPath: '../utils/loaders/KTX2Loader/basis',
                     maximumScreenSpaceError: fileInfo.maximumScreenSpaceError || 80 ,  //越小越清晰。           如果本身tiles很密很小这个值就不能很大。
@@ -5981,6 +5989,8 @@ export class Viewer extends ViewerBase{
                     parent: this.scene.scene, 
                     is4dkk: fileInfo.is4dkk,//是否是4dkk中的模型. 通常maximumScreenSpaceError需要10
                     updateTime: fileInfo.updateTime, //加后缀防止缓存
+                    //cesiumIONToken:  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5OTc4MTFiYS1hYzhlLTQ3ZjYtYWJmMi1hODMwMWMxZGRiYTQiLCJpZCI6ODU1NDksImlhdCI6MTY1Mzc5NDc5N30.ldTi8bF3XvSOgnZrMITokRW4kE3i8Mwbarhk5OQbPsI',
+ 
                 },  
             })  
             //console.log(result)
@@ -6652,6 +6662,7 @@ export class Viewer extends ViewerBase{
         return sprite  
     }
     
+     
     
     switchHotType(){//   add
         let type = Potree.settings.showHotTemp ? 'temp' : Potree.settings.showHotIr ? 'ir' : null