|
@@ -17,7 +17,7 @@ import * as THREE from "../../libs/three.js/build/three.module.js";
|
|
|
import {Utils} from "../utils.js";
|
|
|
import cameraLight from "../custom/utils/cameraLight.js";
|
|
|
import Common from "../custom/utils/Common.js";
|
|
|
-
|
|
|
+import math from "../custom/utils/math.js";
|
|
|
|
|
|
let Buttons = Potree.defines.Buttons
|
|
|
export class FirstPersonControls extends THREE.EventDispatcher {
|
|
@@ -85,7 +85,7 @@ export class FirstPersonControls extends THREE.EventDispatcher {
|
|
|
if(e.touches.length == 1){
|
|
|
mode = (!e.dragViewport || e.dragViewport.name == 'MainView') ? 'rotate' : 'pan'
|
|
|
}else if(e.touches.length == 2){
|
|
|
- mode = 'scale'
|
|
|
+ mode = 'pan-scale'
|
|
|
}else{
|
|
|
mode = (!e.dragViewport || e.dragViewport.name == 'MainView') ? 'pan' : 'scale'
|
|
|
}
|
|
@@ -229,8 +229,7 @@ export class FirstPersonControls extends THREE.EventDispatcher {
|
|
|
|
|
|
}else{ */
|
|
|
pointclouds = a && e.drag.intersectStart.pointcloud && [e.drag.intersectStart.pointcloud]
|
|
|
- //}
|
|
|
-
|
|
|
+ //}
|
|
|
}
|
|
|
|
|
|
if(pointclouds){
|
|
@@ -246,30 +245,23 @@ export class FirstPersonControls extends THREE.EventDispatcher {
|
|
|
pointclouds,
|
|
|
camera
|
|
|
})
|
|
|
- }else{
|
|
|
-
|
|
|
- this.translationWorldDelta.add(moveVec.negate())
|
|
|
-
|
|
|
+ }else{
|
|
|
+ this.translationWorldDelta.add(moveVec.negate())
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- }else{
|
|
|
+
|
|
|
+ }else{ //perspectiveCamera:
|
|
|
if(e.drag.intersectStart){//如果拖拽着点云
|
|
|
+ let ifInit = e.drag.z == void 0
|
|
|
+ let pointerStartPos2d = e.drag.intersectStart.location.clone().project(camera);//识别到的点云点的位置
|
|
|
+ e.drag.z = pointerStartPos2d.z //记录z,保持拖拽物体到屏幕距离不变,所以z深度不变(如果拖拽过程中没有缩放,这个z其实不变)
|
|
|
|
|
|
- if(e.drag.z == void 0){//拖拽开始
|
|
|
- let pointerStartPos2d = e.drag.intersectStart.location.clone().project(camera);//识别到的点云点的位置
|
|
|
- e.drag.z = pointerStartPos2d.z //记录z,保持拖拽物体到屏幕距离不变,所以z深度不变
|
|
|
+ if(ifInit){//拖拽开始
|
|
|
e.drag.projectionMatrixInverse = camera.projectionMatrixInverse.clone()
|
|
|
//防止吸附到最近点上(因为鼠标所在位置并非识别到的点云点的位置,需要得到鼠标所在位置的3d坐标。)
|
|
|
let pointerStartPos2dReal = new THREE.Vector3(this.pointerDragStart.x,this.pointerDragStart.y, e.drag.z);
|
|
|
e.drag.translateStartPos = pointerStartPos2dReal.clone().unproject(camera);
|
|
|
- /* this.viewer.dispatchEvent({
|
|
|
- type: 'dragPanBegin',
|
|
|
- projectionMatrixInverse : e.drag.projectionMatrixInverse
|
|
|
- }); */
|
|
|
//console.log('开始拖拽', e.pointer.clone())
|
|
|
- }
|
|
|
+ }
|
|
|
//拖拽的过程中将projectionMatrixInverse替换成开始拖拽时的,因为near、far一直在变,会导致unproject计算出的3d坐标改变很大而闪烁。
|
|
|
var _projectionMatrixInverse = camera.projectionMatrixInverse;
|
|
|
camera.projectionMatrixInverse = e.drag.projectionMatrixInverse;
|
|
@@ -281,16 +273,13 @@ export class FirstPersonControls extends THREE.EventDispatcher {
|
|
|
|
|
|
|
|
|
camera.projectionMatrixInverse = _projectionMatrixInverse
|
|
|
- this.translationWorldDelta.copy(moveVec.negate()) //这里没法用add,原因未知,会跳动
|
|
|
+ this.translationWorldDelta.add(moveVec.negate()) //这里没法用add,原因未知,会跳动
|
|
|
//console.log('pan 1', this.translationWorldDelta.clone())
|
|
|
|
|
|
|
|
|
|
|
|
//四指松开剩三指时会偏移一下,暂不知道哪里的问题,或许跟开头防止点云吸附有关?
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
}else{ //如果鼠标没有找到和点云的交点,就假设移动整个模型(也可以去扩大范围寻找最近点云)
|
|
|
|
|
|
/* let center = viewer.scene.pointclouds[0].position;
|
|
@@ -317,19 +306,17 @@ export class FirstPersonControls extends THREE.EventDispatcher {
|
|
|
}
|
|
|
|
|
|
|
|
|
- if(mode.includes('scale')){
|
|
|
-
|
|
|
+ if(mode.includes('scale')){//触屏缩放
|
|
|
+
|
|
|
this.dollyEnd.subVectors(e.touches[0].pointer, e.touches[1].pointer);
|
|
|
//if(!this.dollyStart)return
|
|
|
var scale = this.dollyEnd.length() / this.dollyStart.length()
|
|
|
-
|
|
|
- //console.log('scale ',scale)
|
|
|
-
|
|
|
+
|
|
|
let pointer = new THREE.Vector2().addVectors(e.touches[0].pointer, e.touches[1].pointer).multiplyScalar(0.5);//两个指头的中心点
|
|
|
|
|
|
dolly({
|
|
|
pointer,
|
|
|
- scale, camera
|
|
|
+ scale, camera, drag:e.drag
|
|
|
})
|
|
|
this.dollyStart.copy(this.dollyEnd);
|
|
|
|
|
@@ -387,36 +374,49 @@ export class FirstPersonControls extends THREE.EventDispatcher {
|
|
|
this.translationWorldDelta.add(moveVec.negate())
|
|
|
this.useAttenuation = false
|
|
|
}else{
|
|
|
- let speed , direction
|
|
|
+ let speed = this.currentViewport.getMoveSpeed() * 15, direction
|
|
|
|
|
|
|
|
|
if(e.delta != void 0){//滚轮缩放
|
|
|
- speed = this.currentViewport.getMoveSpeed() * 15
|
|
|
-
|
|
|
- //var direction = this.currentViewport.view.direction.clone();
|
|
|
+ if(e.delta == 0)return //mac
|
|
|
|
|
|
- /* if(this.target && !e.intersect){//如果没有intersect点云且有target的话,就朝target的方向. 但无限靠近时有问题,且到背面时前进却是后退
|
|
|
+ /*if(this.target && !e.intersect){//如果没有intersect点云且有target的话,就朝target的方向. 但无限靠近时有问题,且到背面时前进却是后退
|
|
|
direction = new THREE.Vector3().subVectors(this.target, camera.position).normalize()
|
|
|
}else{ */
|
|
|
- direction = this.viewer.inputHandler.getMouseDirection().direction //定点缩放
|
|
|
- //}
|
|
|
-
|
|
|
- if(e.delta == 0){//mac
|
|
|
- return
|
|
|
- }else if (e.delta < 0) {
|
|
|
+ direction = this.viewer.inputHandler.getMouseDirection().direction //定点缩放
|
|
|
+
|
|
|
+ if(e.intersect){//和intersect的墙越接近,速度越慢,便于focus细节
|
|
|
+ let dis = camera.position.distanceTo(e.intersect.location);
|
|
|
+
|
|
|
+ speed = THREE.Math.clamp(dis * 0.1, 0.3, speed)
|
|
|
+ }
|
|
|
+ if (e.delta < 0) {
|
|
|
speed *= -1
|
|
|
- }
|
|
|
- }else{
|
|
|
- const constantDis = this.currentViewport.getMoveSpeed() * 200 //constantDis = 10;//常量系数,当放大一倍时前进的距离。可以调整
|
|
|
- speed = (e.scale-1)*constantDis //触屏缩放
|
|
|
- //pointer = new THREE.Vector2().addVectors().multiplyScalar(0.5);//两个指头的中心点
|
|
|
+ }
|
|
|
+ this.useAttenuation = true
|
|
|
+ }else{//触屏缩放
|
|
|
direction = this.viewer.inputHandler.getMouseDirection(e.pointer).direction //定点缩放
|
|
|
+
|
|
|
+ if(e.drag.intersectStart){//和intersect的墙越接近,速度越慢,便于focus细节
|
|
|
+ let dis = camera.position.distanceTo(e.drag.intersectStart.location);
|
|
|
+
|
|
|
+ let r = 1-1/e.scale
|
|
|
+ let closeMin = 0.1, standardMin = 0.001, disBound1 = 2, disBound2 = 5
|
|
|
+ let min = math.linearClamp(dis, disBound1, disBound2, closeMin, standardMin) //触屏和滚轮不一样,触发较为连续,所以最小值设低一点。若要保持双指相对点云位置不变,理想最小值是0,但那样就无法穿越点云(最小值太小的话穿越密集点云如树丛很困难;太大会打滑)所以当离点云近时增大最小值
|
|
|
+ speed = Math.sign(r) * THREE.Math.clamp(dis * Math.abs(r), min, speed)
|
|
|
+
|
|
|
+ console.log(speed, dis, e.scale)
|
|
|
+
|
|
|
+ }else{
|
|
|
+ const constantDis = this.currentViewport.getMoveSpeed() * 200 //constantDis = 10;//常量系数,当放大一倍时前进的距离。可以调整
|
|
|
+ speed = (e.scale-1)*constantDis
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- this.useAttenuation = true
|
|
|
+
|
|
|
var vec = direction.multiplyScalar(speed )
|
|
|
- this.translationWorldDelta.copy(vec)
|
|
|
-
|
|
|
+ //this.translationWorldDelta.copy(vec)
|
|
|
+ this.translationWorldDelta.add(vec)
|
|
|
+ //console.log(vec, speed)
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -453,6 +453,7 @@ export class FirstPersonControls extends THREE.EventDispatcher {
|
|
|
|
|
|
let prepareScale = (e)=>{//触屏的scale
|
|
|
this.dollyStart.subVectors(e.touches[0].pointer, e.touches[1].pointer);
|
|
|
+ e.drag.camDisToPointStart = null
|
|
|
}
|
|
|
let prepareRotate = (e)=>{
|
|
|
this.pointerDragStart = e.pointer.clone()
|
|
@@ -462,8 +463,8 @@ 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 ? 'intersect' : viewer.inputHandler.selection.length ? 'selection' : 'boundCenter'
|
|
|
- rotCenter = pivotType == 'target'? this.target :pivotType == 'intersect' ? intersect.location : pivotType == 'selection' ? viewer.inputHandler.selection[0].position : viewer.bound.center
|
|
|
+ let pivotType = this.target ? 'target' : viewer.atDatasets.length > 0 ? '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.center
|
|
|
if(rotCenter){
|
|
|
rotCenter2d = rotCenter.clone().project(e.dragViewport.camera) //点在屏幕中的位置
|
|
|
}else{
|
|
@@ -500,14 +501,16 @@ export class FirstPersonControls extends THREE.EventDispatcher {
|
|
|
|
|
|
if(e.touches.length==2){//只监听开头两个指头
|
|
|
prepareScale(e)
|
|
|
+ preparePan(e)
|
|
|
}else if(e.touches.length>=3){
|
|
|
preparePan(e)
|
|
|
}
|
|
|
})
|
|
|
- this.viewer.addEventListener('global_touchend', (e)=>{
|
|
|
+ this.viewer.addEventListener('global_touchend', (e)=>{//e.touches是剩余的指头
|
|
|
if(!this.enabled)return
|
|
|
if(e.touches.length==2){//停止平移,开始scale
|
|
|
prepareScale(e)
|
|
|
+ preparePan(e)
|
|
|
}else if(e.touches.length==1){//停止scale,开始rotate
|
|
|
prepareRotate(e)
|
|
|
}else if(e.touches.length>=3){//重新准备下平移(因为抬起的指头可能包含平移使用的数据),否则抬起时漂移
|
|
@@ -535,8 +538,9 @@ export class FirstPersonControls extends THREE.EventDispatcher {
|
|
|
this.enabled = enabled;
|
|
|
|
|
|
}
|
|
|
- setTarget(target){//绕该点旋转,类似orbitControl
|
|
|
- this.target = target
|
|
|
+ setTarget(target, index){//绕该点旋转,类似orbitControl
|
|
|
+ if(index == 2)this.target2 = target
|
|
|
+ else this.target = target
|
|
|
}
|
|
|
setFPCMoveSpeed(viewport){
|
|
|
if(viewport.camera.type == 'OrthographicCamera'){
|