فهرست منبع

fix: 边拍边传 初步

xzw 2 ماه پیش
والد
کامیت
1100d608fc

+ 3 - 0
src/Potree.js

@@ -42,6 +42,9 @@ export * from "./PotreeRenderer.js";
 export * from "./ProfileRequest.js";
 export * from "./custom/objects/TextSprite.js";
 //export * from "./custom/objects/3dgs/Splat.js";
+export * from "./custom/objects/3dgs/splatter/SplatterThree.js";
+
+
 export * from "./utils.js";
 export * from "./Version.js";
 export * from "./WorkerPool.js";

+ 1 - 1
src/PotreeRendererNew.js

@@ -1788,7 +1788,7 @@ export class Renderer {
                 if(tree.material.opacity==1){
                     tree._z = Infinity //不透明的先渲染   //2024.10发现没用,会透过不透明的看到后面透明的orz
                 }else{
-                    let center = tree.boundCenter ? tree.boundCenter.clone() : tree.boundingBox.getCenter(tree.boundCenter).applyMatrix4(tree.matrixWorld) 
+                    let center = tree.boundCenter ? tree.boundCenter.clone() : tree.boundingBox.getCenter(new THREE.Vector3).applyMatrix4(tree.matrixWorld) 
                     center.project(camera) 
                     tree._z = center.z 
                 }

+ 4 - 4
src/custom/modules/panos/Images360.js

@@ -186,7 +186,7 @@ export class Images360 extends THREE.EventDispatcher{
             )  return 
              
             if(Potree.settings.editType != 'pano' && Potree.settings.editType != 'merge'){
-                if( e.hoverViewport == viewer.mapViewer.viewports[0]){
+                if( e.hoverViewport == viewer.mapViewer?.viewports[0]){
                     return viewer.mapViewer.dispatchEvent(e/* {type:'global_click',e } */) 
                 }else if(e.hoverViewport != viewer.mainViewport){ //如数据集校准其他viewport
                     return
@@ -1829,9 +1829,9 @@ export class Images360 extends THREE.EventDispatcher{
         option1 = void 0 !== option1 ? option1 : 0.6   //.75;    2024.3.22改小,也就是可以走的角度范围增加,主要针对像山野那种很大的场景,不知道可以走哪,容易因角度范围内无近点而飞到远处的情况。但不能太小,总是横着走路
         var o = option2 ? "angle" : "direction";
         
-        var floor = viewer.modules.SiteModel.currentFloor;
-        var entity = viewer.modules.SiteModel.inEntity; 
-        let scaleFactor = Math.pow( this.currentPano?.pointcloud.scale.x || 1 , 2) 
+        //var floor = viewer.modules.SiteModel.currentFloor;
+        //var entity = viewer.modules.SiteModel.inEntity; 
+        //let scaleFactor = Math.pow( this.currentPano?.pointcloud.scale.x || 1 , 2) 
         let changeTexCount = 0, maxWaitDur = 300  
             //maxSamplerChangeTex = THREE.Math.clamp( maxWaitDur / Potree.timeCollect.depthSampler.median, 2, 10)  //计算换贴图最大数目
          

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

@@ -96,7 +96,7 @@ class Panorama extends THREE.EventDispatcher{
          */ 
          
         
-        if(Potree.settings.editType == 'pano'){//漫游点拼合编辑
+        if(Potree.settings.editType == 'pano' || o.single){//漫游点拼合编辑
             this.uuid = this.originID = o.uuid  //对应4dkk中的id,可能不连续
             this.index = o.index  //下标, 用于visibles
               

+ 16 - 11
src/custom/modules/panos/tile/TileDownloader.js

@@ -390,20 +390,25 @@ class TileDownloader extends THREE.EventDispatcher{
 
     
 
-    getTiles(d, sceneNum, useV4url, pointcloud){ 
-          
+    getTiles(d, sceneNum, useV4url, pointcloud, id){ 
         let v3OrV4Str = useV4url ? `/scene_view_data/${sceneNum}/images/` : `/images/images${sceneNum}/`
+        if(Potree.settings.urls.templates.panoTile){ 
+            let url = Potree.Common.replaceAll(Potree.settings.urls.templates.panoTile, '{sceneCode}', pointcloud.sceneCode)    
+                url = Potree.Common.replaceAll(url, '{id}',  id ) + d   
+            return url
         
-        let prefix = Potree.settings.urls.getPrefix(3,pointcloud) //Potree.settings.urls.panoOssRoot || pointcloud.prop?.raw?.panoOssRoot ||  Potree.settings.urls.prefix3
-        if(Potree.settings.isLocal && !this.local2SrcFailed && pointcloud.datasetData.mapping && !Potree.settings.isLocal2){   //非离线包的话加mapping  
+        }else{  
             
-            return `${prefix}/${pointcloud.datasetData.mapping}${v3OrV4Str}${d}`  
-             
+            let prefix = Potree.settings.urls.getPrefix(3,pointcloud) //Potree.settings.urls.panoOssRoot || pointcloud.prop?.raw?.panoOssRoot ||  Potree.settings.urls.prefix3
+            if(Potree.settings.isLocal && !this.local2SrcFailed && pointcloud.datasetData.mapping && !Potree.settings.isLocal2){   //非离线包的话加mapping  
+                
+                return `${prefix}/${pointcloud.datasetData.mapping}${v3OrV4Str}${d}`  
+                 
+            }
+            
+            return `${prefix}${v3OrV4Str}${d}`    
         }
         
-        return `${prefix}${v3OrV4Str}${d}`    
-        
-        
         
         /* 
         if(Potree.settings.isLocal && !this.local2SrcFailed || useV4url){//新的地址  scene_view_data/场景码/images/tiles
@@ -515,7 +520,7 @@ TileDownloader.prototype.getTileUrl = function() {
             //1 === config.tiling.customCompression && (u = "_" + config.tiling["q" + e[panoSize]]);
             //1 === o.tiling.customCompression && (u = "_" + o.tiling["q" + e[n]]);
             d = "tiles/" + id + "/" + e[panoSize] + u + "_face" + h + "_" + t.tileX + "_" + t.tileY + ".jpg" 
-            d =  this.getTiles(d, sceneCode, useV4url, o.pano.pointcloud);
+            d =  this.getTiles(d, sceneCode, useV4url, o.pano.pointcloud, id);
             g = "?"  
           
         }else{//阿里云oss的规则   if (metadata.sceneScheme == 10) 
@@ -544,7 +549,7 @@ TileDownloader.prototype.getTileUrl = function() {
                 } 
             }
             
-            d = this.getTiles(d, sceneCode, useV4url, o.pano.pointcloud);
+            d = this.getTiles(d, sceneCode, useV4url, o.pano.pointcloud, id);
             g = "&" 
         } 
         //Potree.settings.panoVersion = 4

+ 8 - 1
src/custom/potree.shim.js

@@ -278,7 +278,14 @@ Utils.getMousePointCloudIntersection = function(viewport, mouse, pointer, camera
     /* let result = viewer.edlRenderer.depthTexSampler.sample(viewport, mouse)//add
     if(result != 'unsupport')return result
       */
-    
+    if(viewer.splatter?.visible){
+        
+        let point = viewer.splatter.hitTest(camera, mouse.toArray())
+        if(point instanceof Array) point = point[0]
+        return point && {
+            location: new THREE.Vector3().copy(point),
+        }
+    }
      
     
     if(!pointclouds || pointclouds.filter(e=>Potree.Utils.getObjVisiByReason(e, 'datasetSelection')).length == 0)return

+ 1 - 1
src/custom/settings.js

@@ -217,7 +217,7 @@ const config = {//配置参数   不可修改
     measure:{
         color:  mainColor ,
         default:{
-            color: "#64C8BB", 
+            color: mainColor, //Common.getHSV(mainColor, {add:{s:-5, v:-2 }}),
             opacity:0.7
         },
         highlight:{

+ 127 - 1
src/custom/start.js

@@ -11,6 +11,8 @@ import "./potree.shim.js"
 window.THREE = THREE
 
 let baseZ = 0  //所以数据集高度都要减去这个值。在laser场景里该值为初始数据集的高程
+Potree.datasetData = []
+
 
 var transformPointcloud = (pointcloud, dataset)=>{
     
@@ -719,8 +721,132 @@ export function panoEditStart(dom, number, EditCloudsArgs){
     EditCloudsArgs && Potree.loadPanosCloudStart(EditCloudsArgs)
 }
 
+///////////////////////////////////////////////////////-------------------------
+///////////////////////////////////////////////////////-------------------------
+///////////////////////////////////////////////////////-------------------------
+export function realTimePanosStart(dom, number){//边拍边传,和点位编辑一样每个点位一个电源
+    
+    
+    Potree.settings.editType = 'singlePanoToCloud'
 
-
+    Potree.settings.isLocal = Potree.settings.tileOriginUrl = true;
+    Potree.settings.intersectOnObjs = true
+    Potree.settings.boundAddObjs = true 
+    Potree.settings.UserPointDensity = 'high'//'middle'
+    
+    
+    
+    let viewer = new Potree.Viewer(dom, null, {noMap:true});
+    let Alignment = viewer.modules.Alignment
+    viewer.setEDLEnabled(false);
+    viewer.setFOV(Potree.config.view.fov); 
+    
+    Potree.settings.urls.templates.panoTile = 'laser-data/testdata/{sceneCode}/data/preview/{id}/'
+    const rotQua = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1,0,0),  -Math.PI / 2  )    
+    //new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1),  -Math.PI   )      
+    
+    viewer.scene.add360Images(viewer.images360);
+    const datasetId = 1
+    
+    
+    Potree.loadPanos = function(panoData, callback){
+        
+        panoData = panoData.filter(e=> !viewer.images360.panos.some(p=>p.uuid == e.uuid)) 
+            
+        
+        let panoCount = panoData.length
+        let pointcloudLoaded = 0
+        if(!panoCount){
+            return callback()
+        }
+        panoData.forEach((d,index)=>{
+            let timeStamp = 0 
+            let cloudPath = `laser-data/testdata/${number}/data/preview/${d.uuid}/webcloud/cloud.js`
+            
+            
+            //pano.index = index //注意:index不等于uuid,因为有的uuid缺失。但是visibles中存的是下标! 
+            
+            Potree.loadPointCloud(cloudPath, d.uuid , number, timeStamp, e => { //开始加载点云
+               
+                let pointcloud = e.pointcloud; 
+                let config = Potree.config.material
+                let material = pointcloud.material; 
+                material.minSize =  config.minSize
+                material.maxSize =  config.maxSize   
+                material.pointSizeType = /* 'ADAPTIVE'// */config.pointSizeType //Potree.PointSizeType[config.pointSizeType]//Potree.PointSizeType.ADAPTIVE;//FIXED
+                pointcloud.changePointSize( 0.1 /* config.realPointSize  */   )  //material.size =  config.pointSize;
+                pointcloud.changePointOpacity(1)
+                material.shape = Potree.PointShape.SQUARE; 
+                pointcloud.color = config.pointColor  
+                pointcloud.dataset_id = datasetId;   //多个点云指向一个datasetId
+                pointcloud.panoUuid = d.uuid ///!!
+                pointcloud.timeStamp = timeStamp
+                
+                /* if(datasetData){//非4dkk
+                    pointcloud.datasetData = datasetData
+                    pointcloud.hasDepthTex = Potree.settings.useDepthTex && !!datasetData.has_depth   
+                } */
+                 
+                viewer.scene.addPointCloud(pointcloud);
+                pointcloudLoaded ++;
+                 
+                if(pointcloudLoaded == panoCount ){
+                 
+                    let datas = panoData.map(p=>{
+                        let newData = Object.assign(p,{
+                            single:true
+                        }) 
+                        return newData 
+                    })  
+                    viewer.images360.addPanoData(datas  )  
+                     
+                    panoData.forEach(ee => {
+                        let pano = viewer.images360.panos.find(e=>e.uuid == ee.uuid)
+                         
+                        let data = pano.panoData
+                        let dataPosition = new THREE.Vector3().fromArray(data.pose3d.position) 
+                        let qua = data.pose3d.rotation
+                            qua = [qua[1], qua[2], qua[3], qua[0]] 
+                            
+                        let dataQuaternion = new THREE.Quaternion().fromArray(qua)  
+                         
+                        pano.pointcloud.orientationUser = math.convertQuaternion.YupToZup(dataQuaternion)//new THREE.Quaternion().multiplyQuaternions(dataQuaternion, rotQua)  //math.convertQuaternion.YupToZup(dataQuaternion) //new THREE.Quaternion().multiplyQuaternions(dataQuaternion,rotQua2) 
+                        
+                        
+                        console.log('dataQuaternion', new THREE.Euler().setFromQuaternion(pano.pointcloud.orientationUser)) 
+                        
+                        pano.pointcloud.translateUser.copy(math.convertVector.YupToZup(dataPosition))
+                        Alignment.setMatrix(pano.pointcloud);
+                    })
+                    viewer.images360.loadDone() 
+                    
+                    
+                    callback()
+                    
+                    /* 
+                    let {boundSize, center} = viewer.bound
+                   
+                    Potree.Log(`中心点: ${math.toPrecision(center.toArray(),2)}, boundSize: ${math.toPrecision(boundSize.toArray(),2)} `  )
+                      
+                    viewer.scene.view.setView({ 
+                        position: center.clone().add(new THREE.Vector3(10,5,10)), 
+                        target: center
+                    }) */
+                }
+                
+            })
+            
+            
+        })
+            
+         
+        
+        
+        
+    }
+    
+}
+///////////////////////////////////////////////////////////////-----------------------
   
 
 export function mergeEditStart(dom, mapDom){

+ 21 - 22
src/custom/viewer/ViewerNew.js

@@ -151,11 +151,11 @@ export class Viewer extends ViewerBase{
         } 
          
          
-        if(Potree.settings.editType == "pano" || Potree.settings.editType == "merge"){
+        if(Potree.settings.editType == "pano" || Potree.settings.editType == "merge"  ){
             this.modules = { 
                 Alignment,  
                 SiteModel,
-                volumeComputer: new VolumeComputer //暂时
+                //volumeComputer: new VolumeComputer //暂时
             }
             
             
@@ -170,7 +170,11 @@ export class Viewer extends ViewerBase{
                 
             }
             
-        }else{
+        }else if(Potree.settings.editType == 'singlePanoToCloud'){
+            this.modules = { 
+                Alignment 
+            }
+        }else{   
             this.modules = { 
                 Clip,
                 Alignment,
@@ -642,23 +646,18 @@ export class Viewer extends ViewerBase{
             this.volumeTool = new VolumeTool(this);
             this.tagTool = new TagTool(this);
             
-            
-            
-            
+             
             //-----------
             CursorDeal.init(this, this.mapViewer ? [this, this.mapViewer] : [this])//ADD
-            if(Potree.settings.editType == "pano"){
-                this.modules.PanoEditor.init()
-                this.modules.SiteModel.init()  //add
-            }else if(Potree.settings.editType == "merge"){
-                this.modules.MergeEditor.init()
-            }else{
-                this.modules.SiteModel.init()
-                this.modules.ParticleEditor.init()
-            }                
-            this.modules.Alignment.init()
             
             
+            this.modules.PanoEditor?.init()
+            this.modules.SiteModel?.init()  //add
+            this.modules.Alignment?.init()
+            this.modules.MergeEditor?.init()
+            this.modules.ParticleEditor?.init()
+            
+          
             
             this.images360 = new Images360(this);
             
@@ -674,7 +673,7 @@ export class Viewer extends ViewerBase{
             //-----------
             
             
-            this.modules.volumeComputer && this.modules.volumeComputer.init()
+            this.modules.volumeComputer?.init()
             
             
 		}catch(e){
@@ -836,7 +835,7 @@ export class Viewer extends ViewerBase{
          
         
         
-        if(Potree.settings.editType != 'pano' && Potree.settings.editType != 'merge' || Potree.settings.mergeType2){  
+        if(Potree.settings.editType != 'pano' && Potree.settings.editType != 'singlePanoToCloud' && Potree.settings.editType != 'merge' || Potree.settings.mergeType2){  
             let updated, zoomLevel
             let update = (e)=>{ 
                 if(e.type == 'updateModelBound' || e.viewport == this.mainViewport && (e.changeInfo.positionChanged || zoomLevel != this.images360.zoomLevel)){ 
@@ -3041,13 +3040,13 @@ export class Viewer extends ViewerBase{
 		}
 
 		
-        this.transformationTool.update();
+        this.transformationTool?.update();
         
  	
         if(Potree.settings.editType != 'pano' && Potree.settings.editType != 'merge'){
-            this.modules.ParticleEditor.update(delta)  
+            this.modules.ParticleEditor?.update(delta)  
         }
-        this.mapViewer && this.mapViewer.update(delta)     //地图更新
+        this.mapViewer?.update(delta)     //地图更新
         
 		this.dispatchEvent({ type: 'update', delta: delta, timestamp: timestamp});  //在有sidebar时耗高cpu,占本update函数80%
          
@@ -3743,7 +3742,7 @@ export class Viewer extends ViewerBase{
         
         if(this.screenshoting && !params.screenshot)return //正在截图
    
-        let s = SiteModel.editing && SiteModel.selected && (SiteModel.selected.buildType == 'room' || SiteModel.selected.buildType == 'floor') //空间模型的房间选中材质是需要depth的,这时候需要绘制两次点云
+        let s = SiteModel?.editing && SiteModel.selected && (SiteModel.selected.buildType == 'room' || SiteModel.selected.buildType == 'floor') //空间模型的房间选中材质是需要depth的,这时候需要绘制两次点云
          
         Potree.settings.pointEnableRT = /* !this.screenshoting && */ (this.scene.measurements.filter(e=>e.visible).length > 0 || s || PanoEditor?.entered || this.tags.children.some(e=>e.visible))
                                             //2024.12为什么截图时不遮挡?

+ 6 - 2
src/navigation/FirstPersonControlsNew.js

@@ -310,7 +310,7 @@ export class FirstPersonControls extends THREE.EventDispatcher {
                             speed = Math.max(1 , speed) 
                         }  */
                         let lastIntersect = this.target || viewport.lastIntersect && (viewport.lastIntersect.location || viewport.lastIntersect)//该viewport的最近一次鼠标和点云的交点
-                        if(!lastIntersect || !(lastIntersect instanceof THREE.Vector3))lastIntersect = viewer.bound.center  
+                        if(!lastIntersect || !(lastIntersect instanceof THREE.Vector3))lastIntersect = viewer.bound?.center || new THREE.Vector3
                         let speed = camera.position.distanceTo(lastIntersect)   
                         let fov = cameraLight.getHFOVForCamera(camera, true)
                         let ratio = speed  * Math.tan(fov/2) 
@@ -506,14 +506,18 @@ export class FirstPersonControls extends THREE.EventDispatcher {
             let rotAroundPoint = Potree.settings.rotAroundPoint && e.dragViewport.camera.type != 'OrthographicCamera' /* &&  (viewer.atDatasets.length == 0 || intersect) */ && this.canMovePos(viewport) && !viewer.images360.isAtPano() && !this.viewer.inputHandler.pressedKeys[32]
             let rotCenter2d, rotCenter
             if(rotAroundPoint){
-                let pivotType = this.target ? 'target' : (viewer.atDatasets.length > 0 || Potree.settings.editType == 'pano')? 'intersect' :  viewer.inputHandler.selection.length ? 'selection' : this.target2 ? 'target2' : 'boundCenter'  
+               /*  let pivotType = this.target ? 'target' : (viewer.atDatasets.length > 0 || Potree.settings.editType == 'pano')? 'intersect' :  viewer.inputHandler.selection.length ? 'selection' : this.target2 ? 'target2' : 'boundCenter'  
                 rotCenter = pivotType == 'target'? this.target :pivotType == 'intersect' ? intersect?.location : pivotType == 'selection' ? viewer.inputHandler.selection[0].position : pivotType == 'target2' ? this.target2 : viewer.bound && viewer.bound.center
+                  */
+                let useIntersect = viewer.atDatasets.length > 0 || Potree.settings.editType == 'pano'
+                rotCenter = this.target || useIntersect && intersect?.location || viewer.inputHandler.selection[0]?.position || this.target2 || viewer.bound?.center
                 if(rotCenter){
                     rotCenter2d = rotCenter.clone().project(e.dragViewport.camera) //点在屏幕中的位置。   若z>1 则在背面 或 超出far范围 
                 }else{
                     rotAroundPoint = false
                 } 
             }
+            if(rotAroundPoint && isNaN(rotCenter2d.x)) rotAroundPoint = false //when camera and rotCenter both  at 000
             this.rotateStartInfo = {  
                 rotAroundPoint, //定点旋转 
                 rotCenter,

+ 12 - 1
src/viewer/ExtendView.js

@@ -484,7 +484,18 @@ class ExtendView extends View {
         
     }
     
-     
+    getJson(){
+        let json = {
+            yaw: this.yaw,  pitch: this.pitch,  position: this.position
+        }
+        return json  //JSON.stringify(json)
+    } 
+    
+    applyJson(json){
+        typeof json == 'string' &&  (json = JSON.parse(json))
+        this.position.copy(json.position)
+        this.yaw = json.yaw,  this.pitch = json.pitch
+    }
     
 
 };