xzw 2 лет назад
Родитель
Сommit
39266a2e7f

+ 35 - 31
src/modules/datasetAlignment/Alignment.js

@@ -9,11 +9,21 @@ var Alignment = {
     handleState:null,  //操作状态 'translate'|'rotate'
     bus: new THREE.EventDispatcher(), 
     
+    history : new History({ 
+        callback: (data)=>{ 
+            data.forEach(item=>{
+                Alignment.applyTemp(item)  
+            }) 
+        } 
+    }),
+
     prepareRecord : true, 
     
-    writeToHistory(content){ 
+    writeToHistory(pointclouds){ 
         if(!this.prepareRecord)return;
         this.prepareRecord = false
+        
+        let content = this.getTemp(pointclouds)
         this.history.writeIn(content)
     },
     
@@ -54,20 +64,17 @@ var Alignment = {
             }
             
             
-            this.writeToHistory(this.getTemp(e.pointclouds) ) 
-             
-            
-            
-            
+            this.writeToHistory( e.pointclouds ) 
+              
         
             if(this.handleState == 'translate'){
                 e.pointclouds.forEach(cloud=>Alignment.translate(cloud, e.moveVec))
                 
                 
             }else if(this.handleState == 'rotate'){
-                if(Potree.settings.editType == 'pano'){
-                    
-                    let center = e.intersectStart //旋转中心是mousedown的位置
+                if(Potree.settings.editType == 'pano'){  
+                    //旋转中心是intersectStart的版本
+                    /* let center = e.intersectStart //旋转中心是mousedown的位置
                     if(e.intersect.equals(center))return
                     if(!rotateInfo){  
                         rotateInfo = {
@@ -82,15 +89,24 @@ var Alignment = {
                         if(vec.length() * e.camera.zoom >  30){  //在屏幕上距离初始点有一定距离后开始算
                             //console.log('moveVec',vec)
                             rotateInfo.vecStart = vec
-                        }
-                    }else{
-                        
+                        } */ 
+                   
+                     
+                    let center = e.pointclouds[0].translateUser //旋转中心是第一个点云的位置  
+                    if(e.intersect.equals(center))return
+                    if(!rotateInfo){  
+                        rotateInfo = {
+                            orientationUser : e.pointclouds[0].orientationUser,
+                            vecStart : new THREE.Vector3().subVectors(e.intersectStart, center).setZ(0), 
+                            pointclouds: e.pointclouds
+                        }  
+                    }else{ 
+                    
                         let vec = new THREE.Vector3().subVectors(e.intersect, center).setZ(0)
                         let angle = math.getAngle(rotateInfo.vecStart,vec,'z')   
                         let diffAngle = rotateInfo.orientationUser + angle - rotateInfo.pointclouds[0].orientationUser
                         
-                        rotateInfo.pointclouds.forEach(cloud=>{
-                            
+                        rotateInfo.pointclouds.forEach(cloud=>{ 
                            /*  let centerNoTranfrom = Potree.Utils.datasetPosTransform({ toDataset: true, pointcloud:cloud, position: center }) //中心点在数据集中的位置
                             Alignment.rotate(cloud, null, diffAngle)
                              
@@ -98,16 +114,11 @@ var Alignment = {
                             let shift = new THREE.Vector3().subVectors( center, centerNow); //偏移量
                             Alignment.translate(cloud,shift)   //使center还保留在原位
                             //let centerNow1 = Potree.Utils.datasetPosTransform({ fromDataset: true, pointcloud:rotateInfo.pointcloud, position: centerNoTranfrom }) //中心点的现在位置
-                                 */
-                                 
-                            Alignment.rotateAround(center, cloud, null, diffAngle)   
-                                
-                                 
-                        })
-                        
-                        
+                                 */ 
+                            Alignment.rotateAround(center, cloud, null, diffAngle)    
+                        }) 
                     }
-                    this.bus.dispatchEvent({type:'rotate', endPoint: e.intersect})
+                    //this.bus.dispatchEvent({type:'rotate', endPoint: e.intersect})
                     
                 }else{ 
                     let center = e.pointclouds[0].translateUser //移动到的位置就是中心
@@ -368,14 +379,7 @@ var Alignment = {
 }
 
 
-Alignment.history = new History({ 
-    callback: (data)=>{ 
-        data.forEach(item=>{
-            Alignment.applyTemp(item)  
-        }) 
-    } 
-})
-
+ 
 /* 
 
 关于控制点:

+ 144 - 78
src/modules/panoEdit/panoEditor.js

@@ -21,7 +21,7 @@ const texLoader = new THREE.TextureLoader()
 const rotQua = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), Math.PI)    
 const lineMats = {}
 const circleMats = {}
-
+ 
 const renderOrders = {
     circleSelected:3,
     circle:2,
@@ -67,6 +67,7 @@ class PanoEditor extends THREE.EventDispatcher{
         this.views = {}
         this.cameras = {}
         this.orthoCamera = new THREE.OrthographicCamera(-100, 100, 100, 100, 0.01, 10000)
+        this.orthoCamera.up.set(0,0,1)
         this.selectedPano;
         this.selectedGroup;
         this.operation; 
@@ -94,54 +95,6 @@ class PanoEditor extends THREE.EventDispatcher{
              
         }
     
-        {
-            this.transformControls = new TransformControls(viewer.mainViewport.camera, viewer.renderArea,{
-                dontHideWhenFaceCamera: true,
-                rotFullCircle:true
-            }); 
-            this.transformControls.setSize(1.5)
-            viewer.scene.scene.add(this.transformControls)
-            this.transformControls._gizmo.hideAxis = {translate:[], rotate:['x','y','e'] }
-            this.transformControls.setRotateMethod(2)
-            
-            this.fakeMarkerForTran = new THREE.Mesh(new THREE.BoxBufferGeometry(0.3,0.3,0.3) , new THREE.MeshBasicMaterial({
-                color:"#FFFFFF",  opacity:0.4,  transparent:true, visible:false
-            }));//一个看不见的mesh,只是为了让transformControls移动点云
-            viewer.scene.scene.add(this.fakeMarkerForTran)
-            
-            
-       
-            let afterMoveCircle = (type)=>{
-                  
-                if(type == 'position'){
-                    let moveVec = new THREE.Vector3().subVectors(this.fakeMarkerForTran.position, this.fakeMarkerForTran.oldState.position)
-                    this.selectedClouds.forEach(cloud=>Alignment.translate(cloud, moveVec))
-                }else{
-                    let center = this.selectedPano.position;
-                    let forward = new THREE.Vector3(0,1,0);
-                    let vec1 = forward.clone().applyQuaternion(this.fakeMarkerForTran.oldState.quaternion)
-                    let vec2 = forward.clone().applyQuaternion(this.fakeMarkerForTran.quaternion)
-                     
-                    let diffAngle = math.getAngle(vec1,vec2,'z')    
-                        
-                    this.selectedClouds.forEach(cloud=>{ 
-                        Alignment.rotateAround(center, cloud, null, diffAngle)    
-                    })
-                }
-                
-                
-                this.fakeMarkerForTran.oldState = {
-                    position: this.fakeMarkerForTran.position.clone(),
-                    quaternion: this.fakeMarkerForTran.quaternion.clone(),
-                }
-            }
-             
-            this.fakeMarkerForTran.addEventListener('position_changed', afterMoveCircle.bind(this,'position')) 
-            this.fakeMarkerForTran.addEventListener("rotation_changed", afterMoveCircle.bind(this,'rotation') )
-          
-            
-        }
-        
         
         
         this.initViews()
@@ -159,6 +112,69 @@ class PanoEditor extends THREE.EventDispatcher{
             viewer.scene.scene.add(this.lineMeshes)
             
             
+            
+            {
+                this.transformControls = new TransformControls(viewer.mainViewport.camera, viewer.renderArea,{
+                    dontHideWhenFaceCamera: true,
+                    rotFullCircle:true
+                }); 
+                this.transformControls.setSize(1.5)
+                viewer.scene.scene.add(this.transformControls)
+                this.transformControls._gizmo.hideAxis = {translate:[], rotate:['x','y','e'] }
+                this.transformControls.setRotateMethod(2)
+                
+                this.fakeMarkerForTran = new THREE.Mesh(new THREE.BoxBufferGeometry(0.3,0.3,0.3) , new THREE.MeshBasicMaterial({
+                    color:"#FFFFFF",  opacity:0.4,  transparent:true, visible:false
+                }));//一个看不见的mesh,只是为了让transformControls移动点云
+                viewer.scene.scene.add(this.fakeMarkerForTran)
+                
+                
+           
+                let afterMoveCircle = (type)=>{
+                      
+                    if(type == 'position'){
+                        let moveVec = new THREE.Vector3().subVectors(this.fakeMarkerForTran.position, this.fakeMarkerForTran.oldState.position)
+                        this.selectedClouds.forEach(cloud=>Alignment.translate(cloud, moveVec))
+                    }else{
+                        let center = this.selectedPano.position;
+                        let forward = new THREE.Vector3(0,1,0);
+                        let vec1 = forward.clone().applyQuaternion(this.fakeMarkerForTran.oldState.quaternion)
+                        let vec2 = forward.clone().applyQuaternion(this.fakeMarkerForTran.quaternion)
+                         
+                        let diffAngle = math.getAngle(vec1,vec2,'z')    
+                            
+                        this.selectedClouds.forEach(cloud=>{ 
+                            Alignment.rotateAround(center, cloud, null, diffAngle)    
+                        })
+                    }
+                    
+                    
+                    this.fakeMarkerForTran.oldState = {
+                        position: this.fakeMarkerForTran.position.clone(),
+                        quaternion: this.fakeMarkerForTran.quaternion.clone(),
+                    }
+                    Alignment.writeToHistory( this.selectedClouds ) 
+                
+                }
+                 
+                this.fakeMarkerForTran.addEventListener('position_changed', afterMoveCircle.bind(this,'position')) 
+                this.fakeMarkerForTran.addEventListener("rotation_changed", afterMoveCircle.bind(this,'rotation') )
+              
+                this.transformControls.addEventListener('transform_end',()=>{
+                    Alignment.prepareRecord = true
+                })
+                
+                Alignment.history.addEventListener('undo',()=>{
+                    this.updateTranCtl()
+                })
+            }
+            
+            
+            
+            
+            
+            
+            
             this.initPanoLink() 
             
             this.addPanoMesh()
@@ -206,7 +222,7 @@ class PanoEditor extends THREE.EventDispatcher{
             
             
              
-            {//旋转时的辅助线
+            /* {//旋转时的辅助线
                 this.rotGuideLine = LineDraw.createLine([], {color:'#aaffee'})
                 this.rotGuideLine.visible = false
                 this.rotGuideLine.name = 'rotGuideLine'
@@ -225,7 +241,7 @@ class PanoEditor extends THREE.EventDispatcher{
                     startPoint = null
                     this.rotGuideLine.visible = false
                 })
-            }
+            } */
             
             {//连接时的辅助线
                 this.linkGuideLine = LineDraw.createLine([], {color:'#aaa', deshed:true, dashSize:0.1,gapSize:0.1,})
@@ -249,6 +265,15 @@ class PanoEditor extends THREE.EventDispatcher{
                 //为何打开调试时移动很卡
             }
             
+            /* 
+            viewer.inputHandler.addEventListener('keydown', (e)=>{
+                if(e.event.key == "r" ){ 
+                    this.setTranMode('rotate') 
+                }else if(e.event.key == "t"){
+                    this.setTranMode('translate') 
+                }
+            }) */      
+            
         }) 
     }
     
@@ -339,10 +364,10 @@ class PanoEditor extends THREE.EventDispatcher{
             })
             viewer.updateVisible(viewer.reticule, 'force', true)
              
-            if(lastView){
+            if(lastView){//2d->3d
                 
                 view.copy(lastView)
-                //view.position.
+                 
                 let direction = view.direction
                 let panos = images360.panos.filter(e=>e.circle.visible)
                 let nearestPano = Common.sortByScore(panos , [], [(pano)=>{
@@ -365,33 +390,74 @@ class PanoEditor extends THREE.EventDispatcher{
             viewer.fpControls.lockKey = false
             
         }else{ 
-            
-            if(prop.openCount == 0){//只需执行一次
-                this.viewportFitBound(name,  boundSize, center)
-            }else{
-                if(this.lastViewName == 'mainView'){
-                    let direction = lastView.direction
-                    let panos = images360.panos.filter(e=>e.circle.visible)
-                    let nearestPano = Common.sortByScore(panos , [], [(pano)=>{
-                        let vec = new THREE.Vector3().subVectors(pano.position,  lastView.position);
-                        return -vec.dot(direction); 
-                    }], true);
+             
+            if(this.lastViewName == 'mainView'){//3d->2d
+                let direction = lastView.direction
+                let panos = images360.panos.filter(e=>e.circle.visible)
                 
-                    if(nearestPano && nearestPano[0] ){
-                        let pos1 = nearestPano[0].item.position.clone()
-                        let pos2 = pos1.clone()
-                        let dis = -nearestPano[0].score
-                        pos1.project(lastCamera)
-                        pos2.project(camera)
-                        
-                        let vecOnscreen = new THREE.Vector3().subVectors(pos1,pos2) 
-                        let moveVec = Potree.Utils.getOrthoCameraMoveVec(vecOnscreen, camera )
-                        console.log('moveVec',moveVec)
-                        view.position.sub(moveVec)
+                //尽量靠近画布中心,且距离相机较近
+                let nearestPano = Common.sortByScore(panos , [], [(pano)=>{
+                    let vec = new THREE.Vector3().subVectors(pano.position,  lastView.position);
+                    let dis = vec.dot(direction);  
+                    return dis < 0 ? dis * 10 : - dis 
+                },(pano)=>{
+                    let vec = new THREE.Vector3().subVectors(pano.position,  lastView.position);
+                    let angle = vec.angleTo(direction)
+                    return  - angle * 70 
+                }], true);  
+                //目前还存在的问题就是不知selectedPano和最近点的取舍
+                //console.log('panos',nearestPano )
+                if(nearestPano && nearestPano[0] ){
+                    //console.log('nearestPano',nearestPano[0].item.id )                    
+                    let pos1 = nearestPano[0].item.position.clone()
+                    let pos2 = pos1.clone()
+                    let dis = new THREE.Vector3().subVectors(nearestPano[0].item.position,  lastView.position).dot(direction)   //-nearestPano[0].score
+                    
+                    //根据2d->3d的式子逆求zoom
+                    let halfHeight = Math.abs(dis) * Math.tan( THREE.Math.degToRad(lastCamera.fov/2)) 
+                    camera.zoom = camera.top / halfHeight
+                    camera.updateProjectionMatrix()
+                    
+                    if(name == 'right'){//侧视图
+                        view.direction = direction.clone().setZ(0) //水平方向设定为3d的方向
+                        this.targetPlane.setFromNormalAndCoplanarPoint( view.direction.clone(), center )  
+                        this.targetPlane.projectPoint(view.position, this.shiftTarget )  //target转换到过模型中心的平面,以保证镜头一定在模型外
+                        view.position.copy(this.splitScreenTool.getPosOutOfModel(viewer.mainViewport))
                     }
-                
+                    
+                    view.applyToCamera(camera)//update
+                    
+                    pos1.project(lastCamera) 
+                    pos2.project(camera)
+                    
+                    
+                    //目标是找到画面上最接近中心的一点(最好是漫游点,不然就是点云),让其在转换画面后在画面上的位置不变。万一找到的点不在屏幕中(比如当屏幕中没点云时),就默认让那个点移动到屏幕中央,也就是假设当前它pos1在屏幕中央位置。
+                     
+                    //
+                    if(pos1.z>1){
+                        console.warn('选取的点在相机背后了!?')
+                    }
+                    //如果最近点超出屏幕范围 (-1,1), 最好将其拉到边缘,甚至居中 。这样屏幕上就不会没有漫游点了
+                    let bound = 0.9
+                    pos1.x = THREE.Math.clamp(pos1.x, -bound, bound)
+                    pos1.y = THREE.Math.clamp(pos1.y, -bound, bound)
+                    
+                   
+                    
+                    let vecOnscreen = new THREE.Vector3().subVectors(pos1,pos2) 
+                    let moveVec = Potree.Utils.getOrthoCameraMoveVec(vecOnscreen, camera )
+                    
+                    //console.log('pos1',    pos1)
+                    
+                    view.position.sub(moveVec)
                 }
+            
+            }else{
+                if(prop.openCount == 0){//至多执行一次
+                    this.viewportFitBound(name,  boundSize, center)
+                } 
             }
+             
             prop.openCount ++;
             
             
@@ -423,7 +489,7 @@ class PanoEditor extends THREE.EventDispatcher{
         
         
         this.updateTranCtl()
-        this.setTranMode() // update
+        this.setTranMode(this.tranMode) // update
         this.setZoomInState(false) //取消放大模式
         
     }
@@ -520,7 +586,7 @@ class PanoEditor extends THREE.EventDispatcher{
     
     zoomIn(intersect, pointer){ 
         let camera = viewer.mainViewport.camera
-        let endZoom = 700
+        let endZoom = 200
         //this.moveFit(intersect, {endZoom:viewer.mainViewport.camera.zoom < aimZoom ? aimZoom : null}  , 300) 
         let startZoom = camera.zoom
         if(startZoom >= endZoom){return}

+ 10 - 2
src/navigation/FirstPersonControls.js

@@ -197,7 +197,12 @@ export class FirstPersonControls extends THREE.EventDispatcher {
                                 if(handleState == 'translate' && ( e.drag.intersectStart.pointclouds && Common.getMixedSet(PanoEditor.selectedClouds, e.drag.intersectStart.pointclouds).length  || PanoEditor.selectedPano.hovered)//拖拽到点云上 或 circle
                                     || handleState == 'rotate' ) 
                                 {  
-                                    pointclouds = PanoEditor.selectedClouds
+                                    let centerCloud = PanoEditor.selectedPano.pointcloud //选中的漫游点为旋转中心
+                                    //pointclouds = PanoEditor.selectedClouds
+                                    pointclouds = [centerCloud, ...PanoEditor.selectedClouds.filter(e=>e!=centerCloud)]//旋转中心点云放第一个
+                                    if(handleState == 'translate' && PanoEditor.activeViewName == 'right'){
+                                        moveVec.x = moveVec.y = 0  //只能上下移动
+                                    }  
                                 }  
                             }else{
                                 PanoEditor.dispatchEvent('needToDisConnect')
@@ -289,7 +294,10 @@ export class FirstPersonControls extends THREE.EventDispatcher {
                             speed = FirstPersonControls.boundPlane.distanceToPoint(this.currentViewport.position)   
                             speed = Math.max(1 , speed) 
                         }  */
-                        let lastIntersect = viewport.lastIntersect ? (viewport.lastIntersect.location || viewport.lastIntersect) : viewer.bound.center  //该viewport的最近一次鼠标和点云的交点
+                        
+                        let lastIntersect = viewport.lastIntersect && (viewport.lastIntersect.location || viewport.lastIntersect)//该viewport的最近一次鼠标和点云的交点
+                        if(!lastIntersect || !(lastIntersect instanceof THREE.Vector3))lastIntersect = viewer.bound.center  
+                         
                         let speed = camera.position.distanceTo(lastIntersect)   
                         let fov = cameraLight.getHFOVForCamera(camera, true)
                         let ratio = speed  * Math.tan(fov/2) 

+ 3 - 2
src/objects/tool/MeasuringTool.js

@@ -416,6 +416,7 @@ export class MeasuringTool extends THREE.EventDispatcher{
 		let end = (e={}) => {//确定、结束
             if(!measure.isNew)return
             if(args.minMarkers != void 0){
+                
                 if(!e.finish && measure.markers.length<=args.minMarkers){//右键  当个数不够时取消
                     //this.viewer.scene.removeMeasurement(measure)
                     //cancelFun && cancelFun()
@@ -437,13 +438,13 @@ export class MeasuringTool extends THREE.EventDispatcher{
                     } */
                 } 
             }
-            if (/* !e.finish &&  */measure.markers.length > 3) {
+            if (/* !e.finish&& */ measure.markers.length > args.minMarkers) {
 				measure.removeMarker(measure.points.length - 1); 
                 measure.markers[0].removeEventListener('mouseover', mouseover);
                 measure.markers[0].removeEventListener('mouseleave', mouseleave);
                 measure.markers[0].removeEventListener('click'/* 'mousedown' */,Exit) 
                 
-                if(e.byClickMarker && measure.markers.length > 3){//通过点击第一个marker而结束的话,会多一个marker
+                if(e.byClickMarker && measure.markers.length > args.minMarkers){//通过点击第一个marker而结束的话,会多一个marker
                     measure.removeMarker(measure.points.length - 1); 
                 }
 			}

+ 2 - 1
src/objects/tool/TransformControls.js

@@ -769,7 +769,8 @@ var TransformControls = function ( camera, domElement, options ) {
                 this.player.cameraControls.activeControl.enabled = true
             } */
             this.rotateStart = null//add
-
+            this.dispatchEvent({type:'transform_end'})
+            
 		}
 
 		this.dragging = false;

+ 20 - 1
src/utils/Common.js

@@ -4,7 +4,7 @@ import * as THREE from "../../libs/three.js/build/three.module.js";
 
 
 var Common = {
-    sortByScore: function(list, request, rank){
+    /* sortByScore: function(list, request, rank){
         var i = request ? Common.filterAll(list, request) : list
         return 0 === i.length ? null : i = i.map(function(e) {
             return {
@@ -16,7 +16,26 @@ var Common = {
         }).sort(function(e, t) {
             return t.score - e.score;
         })
+    }  */
+    
+    
+    sortByScore: function(list, request, rank){
+        var i = request ? Common.filterAll(list, request) : list
+        return 0 === i.length ? null : i = i.map(function(e) {
+            let scores = rank.map(function(f){return f(e)}) //add
+            
+            return {
+                item: e,
+                scores,
+                score: scores.reduce(function(t, i) {
+                    return t + i
+                }, 0)
+            }
+        }).sort(function(e, t) {
+            return t.score - e.score;
+        })
     } 
+    
     ,
       
     filterAll: function(e, t) {

+ 1 - 1
src/utils/History.js

@@ -16,7 +16,7 @@ class History extends THREE.EventDispatcher{
     undo(){
         let last = this.list.pop();
         last && this.callback && this.callback(last) 
-        
+        this.dispatchEvent('undo')
         
     }
     

+ 3 - 1
src/utils/SplitScreen.js

@@ -151,7 +151,9 @@ class SplitScreen extends THREE.EventDispatcher{
     }
     
     getOrthoCamera(){
-        return new THREE.OrthographicCamera(-100, 100, 100, 100, 0.01, 10000)
+        let camera = new THREE.OrthographicCamera(-100, 100, 100, 100, 0.01, 10000)
+        camera.up.set(0,0,1)
+        return camera
     } 
     
     focusOnViewport(name){//全屏