1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456 |
- /**
- * @author mschuetz / http://mschuetz.at
- *
- *
- */
- import * as THREE from "../../libs/three.js/build/three.module.js";
- import {KeyCodes} from "../KeyCodes.js";
- import {Utils} from "../utils.js";
- import Common from "../custom/utils/Common.js";
- import DepthBasicMaterial from '../custom/materials/DepthBasicMaterial.js'
-
- let {Buttons} = Potree.defines
- export class InputHandler extends THREE.EventDispatcher {
- constructor (viewer,scene) {
- super();
- this.viewer = viewer;
- this.renderer = viewer.renderer;
- this.domElement = this.renderer.domElement;
- this.enabled = true;
-
- this.scene = scene;
- this.interactiveScenes = [];
- this.interactiveObjects = new Set();
- this.inputListeners = [];
- this.blacklist = new Set();
- this.drag = null;
- this.mouse = new THREE.Vector2(0, 0);
- //add:
- this.pointer = new THREE.Vector2(0, 0); //交互点的屏幕坐标,有别于DOM坐标,在此存放NDC坐标。(NDC,三维常用坐标系,二维坐标,整个屏幕映射范围(-1,1),屏幕中心为原点,+Y朝上,+X朝右)
- this.mouseDownMouse = new THREE.Vector2(0, 0);
-
- this.selection = [];
- this.hoveredElements = [];
- this.pressedKeys = {};
-
- this.wheelDelta = 0;
- this.speed = 1;
- this.logMessages = false;
- if (this.domElement.tabIndex === -1) {
- this.domElement.tabIndex = 2222;
- }
-
- this.lastPointerUpTime = 0
-
- this.touches = []
- this.interactHistory = {move:0} //add
- this.hoverViewport = viewer.viewports[0]
-
-
-
- this.domElement.addEventListener('contextmenu', (event) => { event.preventDefault(); }, false);
- this.domElement.addEventListener('click', this.onMouseClick.bind(this), false);
- this.domElement.addEventListener('mousedown', this.onMouseDown.bind(this), false);
- window.addEventListener('mouseup', this.onMouseUp.bind(this), false);
- if(Potree.isIframeChild){//子页面的话在父页面也要加侦听(应该不会有多层吧?否则要一直加到最外层)
- window.parent.addEventListener('mouseup', this.onMouseUp.bind(this), false);
- }
-
- this.domElement.addEventListener('mousemove', this.onMouseMove.bind(this), false);
- //add
- /* this.domElement.addEventListener("pointerout", this.onMouseUp.bind(this)),
- this.domElement.addEventListener("pointercancel", this.onMouseUp.bind(this)),
-
- */
-
- this.domElement.addEventListener('mousewheel', this.onMouseWheel.bind(this), false);
- this.domElement.addEventListener('DOMMouseScroll', this.onMouseWheel.bind(this), false); // Firefox
-
- //this.domElement.addEventListener('dblclick', this.onDoubleClick.bind(this)); //因为双击时间间隔是跟随系统的所以不好判断
-
- this.domElement.addEventListener('keydown', this.onKeyDown.bind(this));
- window.addEventListener('keyup', this.onKeyUp.bind(this));
-
-
- window.addEventListener('blur',this.onKeyUp.bind(this)); //add
-
-
-
- this.domElement.addEventListener('touchstart', this.onTouchStart.bind(this));
- this.domElement.addEventListener('touchend', this.onTouchEnd.bind(this));
- this.domElement.addEventListener('touchmove', this.onTouchMove.bind(this));
-
-
- {
- this.addEventListener('isMeasuring',(e)=>{
- //console.log('isMeasuring',e.v,e.cause)
- this.isMeasuring = e.v
- })
- }
-
- window.viewer.addEventListener('loopStart',()=>{
- this.interactHistory = {} //清空
- })
-
-
- }
-
- /* addInputListener (listener) {
- this.inputListeners.push(listener);
- }
- removeInputListener (listener) {
- this.inputListeners = this.inputListeners.filter(e => e !== listener);
- }
- getSortedListeners(){
- return this.inputListeners.sort( (a, b) => {
- let ia = (a.importance !== undefined) ? a.importance : 0;
- let ib = (b.importance !== undefined) ? b.importance : 0;
- return ib - ia;
- });
- } */
- //统一跟第一个触碰的viewport相同
- updateTouchesInfo(e){
- var viewport, pointer, camera
- let oldTouches = this.touches
- let changedTouches = Array.from(e.changedTouches)
- let touches = Array.from(e.touches)
- this.touches = touches.map(touch=>{
- let touch_ = oldTouches.find(a=>a.touch.identifier == touch.identifier)
- let pointer = touch_ && touch_.pointer //复制原先的值
- return {
- touch, pointer,
- }
- })
- if(e.touches.length > 0){
-
- let newTouches = touches.filter(e=>!
- oldTouches.some(a=>a.touch.identifier == e.identifier) && !changedTouches.some(a=>a.identifier == e.identifier)
- ) //从按钮处划过时e.touches中会出现this.touches和changedTouches中都没有的identifier
- if(newTouches.length>0){
- console.warn('has new',newTouches.map(e=>e.identifier))
- }
-
- newTouches.concat(changedTouches).forEach(touch=>{ //修改changedTouches的
- let touch_ = this.touches.find(a=>a.touch.identifier == touch.identifier)
- if(touch_){
- let a = this.getPointerInViewport(touch.pageX, touch.pageY, this.dragViewport||viewport, new THREE.Vector2)
- touch_.pointer = a.pointer.clone()
- viewport = a.viewport; camera = a.camera
- }
- })
-
-
-
- //使用当前touches的平均
- if(e.touches.length > 1){
- let pageX = Common.average(e.touches, "pageX")
- let pageY = Common.average(e.touches, "pageY")
- let a = this.getPointerInViewport(pageX, pageY, viewport, new THREE.Vector2)
- this.pointer.copy(a.pointer)
- //console.log('updateTouchesInfo', this.pointer.clone())
-
- }else{
- this.pointer = this.touches[0].pointer.clone() //更新,使用当前touches中的第一个
- }
-
-
- /* if(this.touches.find(e=>!e.pointer)){
- console.error(' touches has no pointer', oldTouches.map(e=>e.touch.identifier),
- Array.from(e.touches).map(e=>e.identifier), Array.from(e.changedTouches).map(e=>e.identifier) )
- } */
- //console.log(this.touches)
-
- //console.log('更新pointer1',this.pointer.toArray())
- return {viewport, camera/* , pointer:this.pointer */}
- }
-
-
- }
-
- onTouchStart (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onTouchStart');
- e.preventDefault();
-
- /* if (e.touches.length === 1 || !this.drag) { //!this.drag代表一次性下了两个指头
- let rect = this.domElement.getBoundingClientRect();
- let x = e.touches[0].pageX
- let y = e.touches[0].pageY
- this.dealPointerDown(x,y,e,true)
- }else{
- this.updateTouchesInfo(e)
- this.drag.end.copy(this.pointer)
- } */
-
-
- this.dealPointerDown(e,true)
-
-
- this.viewer.dispatchEvent($.extend(
- this.getEventDesc(e,true),
- {
- type: 'global_' + e.type,
- changedTouches: e.changedTouches
- }
- ));
-
- /* console.log('targetTouches :', Array.from(e.targetTouches).map(e=>'| identifier: '+ e.identifier),
- 'changedTouches :', Array.from(e.changedTouches).map(e=>'| identifier: '+ e.identifier)
- ) */
- //console.log('')
- }
-
-
-
-
- onTouchMove (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onTouchMove');
- e.preventDefault();
-
- /* if (e.touches.length === 1) {
- let rect = this.domElement.getBoundingClientRect();
- let x = e.touches[0].pageX;
- let y = e.touches[0].pageY;
-
-
-
- }else{
- this.updateTouchesInfo(e)
- this.drag.pointerDelta.subVectors(this.pointer, this.drag.end)
- this.drag.end.copy(this.pointer)
- }
- */
-
- this.dealPointerMove(e, true)
-
-
-
-
- this.viewer.dispatchEvent($.extend(
- this.getEventDesc(e,true),
- {
- type: 'global_' + e.type,
- changedTouches: e.changedTouches
- }
- ));
-
-
- /* console.log('targetTouches :', Array.from(e.targetTouches).map(e=>'| identifier: '+ e.identifier),
- 'changedTouches :', Array.from(e.changedTouches).map(e=>'| identifier: '+ e.identifier)
- ) */
- }
-
-
- onTouchEnd (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onTouchEnd');
- e.preventDefault();
- //console.log('onTouchEnd')
- this.updateTouchesInfo(e)
-
- /* if (e.touches.length === 0) {
- let rect = this.domElement.getBoundingClientRect();
- let x = e.changedTouches[0].pageX //万一一次松开两个指头的怎么办
- let y = e.changedTouches[0].pageY
-
- this.dealPointerUp(x,y,e,true)
-
- }else {
- this.drag.end.copy(this.pointer)
- } */
- this.dealPointerUp(e,true)
-
-
-
- this.viewer.dispatchEvent($.extend(
- this.getEventDesc(e,true),
- {
- type: 'global_' + e.type,
- }
- ));
- //console.log('touchend length '+e.touches.length, this.touches.length)
- }
-
- onKeyDown (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onKeyDown');
- // DELETE
- /* if (e.keyCode === KeyCodes.DELETE && this.selection.length > 0) {
- this.dispatchEvent({
- type: 'delete',
- selection: this.selection
- });
- this.deselectAll();
- } */
- this.dispatchEvent({
- type: 'keydown',
- keyCode: e.keyCode,
- event: e
- });
- // for(let l of this.getSortedListeners()){
- // l.dispatchEvent({
- // type: "keydown",
- // keyCode: e.keyCode,
- // event: e
- // });
- // }
- this.pressedKeys[e.keyCode] = true;
- // e.preventDefault();
- }
- onKeyUp (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onKeyUp');
-
- if(e.keyCode != void 0){
- delete this.pressedKeys[e.keyCode];
- }else{
- this.pressedKeys = {}
- }
-
-
- e.preventDefault();
- }
-
- onDoubleClick (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onDoubleClick');
- let consumed = false;
- for (let hovered of this.hoveredElements) {
- if (hovered._listeners && hovered._listeners['dblclick']) {
- hovered.object.dispatchEvent({
- type: 'dblclick',
- mouse: this.mouse,
- object: hovered.object
- });
- consumed = true;
- break;
- }
- }
- if (!consumed) {
- /* for (let inputListener of this.getSortedListeners()) {
- inputListener. */this.viewer.dispatchEvent({
- type: 'global_dblclick',
- mouse: this.mouse,
- object: null
- });
- //}
- }
- this.needSingleClick = false//add
- e.preventDefault();
- }
- onMouseClick (e) {
- if (this.logMessages) console.log(this.constructor.name + ': onMouseClick');
- e.preventDefault();
- }
- dealPointerDown(e,isTouch){
- e.preventDefault();
-
- //重新获取一下pointer, 因点击了浏览器的按钮展开列表时 move回来不会触发onmousemove,所以pointer是旧的
-
- if(isTouch){
- var { camera, viewport } = this.updateTouchesInfo(e)
- if(this.drag){
- //因为触屏在按下前缺少pointermove所以要更新下
- this.drag.end = this.pointer.clone()
- }
-
-
- }else{
-
- var { camera, viewport } = this.getPointerInViewport(e.clientX, e.clientY )
- }
-
-
- this.dragViewport = this.hoverViewport = viewport
-
-
- //if(isTouch || !Potree.settings.intersectWhenHover ){
- if(!this.dragViewport.view.isFlying() && Potree.settings.intersectWhenHover && Potree.settings.editType != 'pano' ){//漫游点编辑如果拖拽前getIntersect旋转会延迟
- this.hoveredElements = this.getHoveredElements();
- let dontIntersect = false
- this.intersect = this.getIntersect(viewport,null,null,dontIntersect) //更新intersect,避免在没有mousemove但flyToPano后intersect未更新。
- //this.intersect = this.getWholeIntersect()
- }
- if(!viewport)return //why add this?
- if (!this.drag) {
- let target = (isTouch||e.button == THREE.MOUSE.LEFT) && this.hoveredElements.find(el => (//只有左键能拖拽
- el.object._listeners &&
- el.object._listeners['drag'] &&
- el.object._listeners['drag'].length > 0));
- if (target) {
- this.startDragging(target.object, {location: target.point});
- } else {
- this.startDragging(null);
- }
- }
- this.drag.intersectStart = this.intersect;
-
-
-
-
- if(!isTouch || e.touches.length == 1){
-
- let consumed = false;
- let consume = () => { return consumed = true; };
- //if (this.hoveredElements.length === 0) {
- this.viewer.dispatchEvent($.extend(
- this.getEventDesc(e,isTouch),
- {
- type: 'global_mousedown'
- }
- ));
-
-
- for(let hovered of this.hoveredElements){
- let object = hovered.object;
- object.dispatchEvent({
- type: 'mousedown',
- viewer: this.viewer,
- consume: consume
- });
- if(consumed){
- break;
- }
- }
- }
-
-
-
-
-
- this.mouseDownMouse = this.mouse.clone()
-
- this.pointerDownTime = Date.now()
- }
- onMouseDown (e) {
-
- if (this.logMessages) console.log(this.constructor.name + ': onMouseDown');
- this.dealPointerDown(e)
-
- }
- /* getWholeIntersect(hoveredElements, intersectPoint){//add
- hoveredElements = hoveredElements || this.hoveredElements
- intersectPoint = intersectPoint || this.intersectPoint
- if(Potree.settings.intersectOnObjs && hoveredElements[0] && hoveredElements[0].object.isModel){
- return {//模拟点云的intersectPoint的结构写法
- hoveredElement : hoveredElements[0] ,
- location: hoveredElements[0].point,
- point: {normal: hoveredElements[0].face.normal },
- distance: hoveredElements[0].distance,
- object: hoveredElements[0].object
- }
- }else return intersectPoint
- } */
- getEventDesc(e,isTouch){//搜集dispatchEvent要给的一般数据
- let o = {
- viewer: this.viewer,
- mouse: this.mouse,
- pointer:this.pointer,
- drag :this.drag,
- isTouch,
- dragViewport : this.dragViewport,
- hoverViewport: this.hoverViewport,
- // button: isTouch ? 0 : e.button,
- //intersectPoint:this.intersectPoint,
- hoveredElement: this.hoveredElements[0],
- intersect: this.intersect//this.getWholeIntersect() , //可能包含mesh上的,针对融合页面
- }
-
-
-
- if(e){
- o.isAtDomElement = e.target == this.domElement
- }
- if(isTouch){
- o.touches = this.touches
- }else if(e){
- o.button = e.button
- o.buttons = e.buttons
- }
- return o;
- }
- dealPointerUp(e,isTouch){
-
- if(!this.drag){// 在canvas外mousedown
- return
- }
-
- this.drag.end.copy(this.pointer)
-
- if(isTouch && e.touches.length >= 1){
- return
- }
- let now = Date.now()
-
-
- if (this.logMessages) console.log(this.constructor.name + ': onMouseUp');
- e.preventDefault();
-
- let pressDistance = this.mouseDownMouse.distanceTo(this.mouse);
- let pressTime = now - this.pointerDownTime;
-
- let noMovement = this.drag.pointerDelta.length() == 0//this.getNormalizedDrag().length() === 0;
-
- let consumed = false;
- let consume = () => { return consumed = true; };
- //if (this.hoveredElements.length === 0) {
- /* for (let inputListener of this.getSortedListeners()) {
- inputListener */this.viewer.dispatchEvent($.extend(
- this.getEventDesc(e,isTouch),
- {
- type: 'global_mouseup',
- pressDistance,
- consume,
- }
- ));
- /* if(consumed){//??
- break;
- } */
- //}
- //}
- if (this.hoveredElements.length > 0) {
- let hovered = this.hoveredElements
- .map(e => e.object)
- .find(e => (e._listeners && e._listeners['mouseup']));
- if(hovered){
- hovered.dispatchEvent({
- type: 'mouseup',
- viewer: this.viewer,
- consume: consume
- });
- }
- }
-
-
-
- if (this.drag) {
- //拖拽结束
- if (this.drag.object/* && e.button == THREE.MOUSE.LEFT */) {//add LEFT
- if (this.logMessages) console.log(`${this.constructor.name}: drop ${this.drag.object.name}`);
-
- this.drag.object.dispatchEvent($.extend(
- this.getEventDesc(e,isTouch),
- {
- type: 'drop',
- pressDistance,
- }
- ));
-
-
- } else {
- this.viewer.dispatchEvent($.extend(
- this.getEventDesc(e,isTouch),
- {
- type: 'global_drop',
- pressDistance
- }
- ));
-
-
- }
-
- // check for a click
-
- if(pressDistance < Potree.config.clickMaxDragDis && pressTime<Potree.config.clickMaxPressTime && !e.unableClick){
- let clickElement, consumed = false;
- if(this.hoveredElements){
- clickElement = this.hoveredElements.find(e=>e.object._listeners['click'])
- if(clickElement){
- //console.log('clickElement',clickElement)
- if (this.logMessages) console.log(`${this.constructor.name}: click ${clickElement.name}`);
- clickElement.object.dispatchEvent($.extend(
- this.getEventDesc(e,isTouch),
- {
- type: 'click',
- pressDistance
- }
- ));
- }
- }
-
-
- let selectable
- if(/* !consumed && */ !this.fixSelection){
- if (e.button === THREE.MOUSE.LEFT) {
- if (noMovement) {
- selectable = this.hoveredElements.find(el => el.object._listeners && el.object._listeners['select']);
- if (selectable) {
- selectable = selectable.object;
-
- if (this.isSelected(selectable)) {
- this.deselectAll();
- } else {
- this.deselectAll();
- this.toggleSelection(selectable);
- }
- consumed = true //add
- } else {
- if(this.selection.length>0)consumed = true //add 取消选择后,阻断后续
- this.deselectAll();
- }
- }
- } else if ((e.button === THREE.MOUSE.RIGHT) && noMovement) {
- this.deselectAll();
- }
- }
-
-
- let consume = () => { return consumed = true; };
- let desc = this.getEventDesc(e,isTouch)
-
- if(!consumed){
-
- this.viewer.dispatchEvent($.extend(
- desc,
- {
- type: 'global_click',
- pressDistance,
- clickElement:clickElement/* || selectable */,
- consume
- }
- ));
- }
-
-
-
- //增加 单击:
- this.needSingleClick = true;
-
-
- consumed || setTimeout(()=>{
- if(this.needSingleClick){
- this.viewer.dispatchEvent($.extend(
- desc,
- {
- type: 'global_single_click',
- pressDistance,
- clickElement
- }
- ));
- }
- }, Potree.config.doubleClickTime+1)
-
- //自行执行双击:
-
- if(now - this.lastClickTime < Potree.config.doubleClickTime){
- this.onDoubleClick(e)
- }
-
- this.lastClickTime = now
- }
-
- this.drag = null;
- }
- this.dragViewport = null
-
-
- }
-
- onMouseUp (e) {
- this.dealPointerUp( e )
- }
- getPointerInViewport(clientX, clientY, viewForceAt, pointer ){
- let rect = this.domElement.getBoundingClientRect();
- let x = clientX - rect.left;
- let y = clientY - rect.top;
- let camera
- let viewport
- pointer = pointer ||this.pointer
- //if(this.viewer.viewports || viewForceAt){
- var getDimension = (view)=>{
- var left = Math.ceil(this.domElement.clientWidth * view.left)
- , bottom = Math.ceil(this.domElement.clientHeight * view.bottom)
- , width = Math.ceil(this.domElement.clientWidth * view.width)
- , height = Math.ceil(this.domElement.clientHeight * view.height)
- , top = this.domElement.clientHeight - bottom - height
- return {left, bottom, width, height, top}
- }
- var getView = (view, left, bottom, width, height, top)=>{
- this.mouse.set(x-left, y - top )
- Utils.convertScreenPositionToNDC(pointer, this.mouse, width, height);
- //console.log('更新pointer2',this.pointer.toArray())
- camera = view.camera;
- viewport = view
- }
-
- if(viewForceAt){
- let {left, bottom, width, height, top} = getDimension(viewForceAt)
- getView(viewForceAt, left, bottom, width, height, top)
-
-
- }else{
- var length = this.viewer.viewports.length;
- //var getif = false
- for(var i=0;i<length;i++){
- var view = this.viewer.viewports[i];
- if(!view.active)continue
- var {left, bottom, width, height, top} = getDimension(view)
-
-
- if(x >= left && x <= left + width && y >= top && y <= top + height){
- getView(view, left, bottom, width, height, top)
-
- //getif = true
- break;
- }
-
- }
-
-
- }
-
- return {
- camera, viewport, pointer
- }
- }
- ifBlockedByIntersect({pos3d, margin=0, cameraPos, pickWindowSize, pano, useDepthTex}={}){//某点是否被遮挡(不允许camera修改位置, 因为depthTex不好置换)
-
- let intersect = this.getIntersect(this.hoverViewport, true, pickWindowSize, null, null, useDepthTex, {pos3d, cameraPos, pano})
- let cameraPos_ = (!cameraPos && pano) ? pano.position : (cameraPos||this.hoverViewport.view.position)
- if(intersect && intersect.distance+margin <= pos3d.distanceTo(cameraPos_)){
- return intersect //被遮挡
- }
- //点云模式,对没加载出的点云不准确。 尤其是需要修改相机位置时,因临时修改并不能使点云加载。
- }
- getIntersect(viewport, onlyGetIntersect, pickWindowSize, dontIntersect, usePointcloud, useDepthTex, prop={}){// usePointcloud:必须使用点云
- let intersectPoint
- let camera = viewport.camera
- let raycaster
-
- viewer.addTimeMark('getIntersect','start')
- let getByDepthTex = ()=>{
- let intersect
- if(prop.pos3d){
- let cameraPos = prop.pano ? prop.pano.position : camera.position
- let dir = new THREE.Vector3().subVectors(prop.pos3d, cameraPos).normalize();
- intersect = {dir}
- }else{
- intersect = Utils.getIntersect(camera, [viewer.images360.cube], this.pointer, raycaster)
- }
- intersectPoint = viewer.images360.depthSampler.sample(intersect, prop.pano, !!prop.pos3d) //可能不准确, 因pano可能未加载depthTex
- if(intersectPoint && Potree.settings.depTexLocBindDataset){
- intersectPoint.pointcloud = (prop.pano || viewer.images360.currentPano).pointcloud
- //在全景模式下,虽然深度图上的点可能对应别的pointcloud,但因为是在当前全景图处得到的,所以即使将原本对应的点云移走,该点也不移动是有道理的。它可以永远跟着该全景图。
- }
- }
-
- let getByCloud = ()=>{
- if(prop.pos3d){//指定了目标点,而非只是用pointer所在位置
- prop.cameraPos && camera.position.copy(prop.cameraPos)
- camera.lookAt(prop.pos3d)
- camera.updateMatrixWorld()
- prop.pointer = this.pointer.clone()
- prop.mouse = this.mouse.clone()
- this.pointer.set(0,0) //画布中心
- this.mouse.set(Math.round(viewport.resolution.x/2), Math.round(viewport.resolution.y/2))
- }
-
- intersectPoint = (viewport.noPointcloud || dontIntersect)? null : Utils.getMousePointCloudIntersection(
- viewport,
- this.mouse,
- this.pointer,
- camera,
- this.viewer,
- this.viewer.scene.pointclouds,
- {pickClipped: true, isMeasuring: this.isMeasuring, pickWindowSize, cameraChanged: !!prop.pos3d }
-
- );
- //恢复
- if(prop.pos3d){
- viewport.view.applyToCamera(camera)
- this.pointer.copy(prop.pointer)
- this.mouse.copy(prop.mouse)
- }
- }
-
-
-
- let canUseDepthTex = (Potree.settings.displayMode == 'showPanos' || useDepthTex)
- && viewer.images360.currentPano.pointcloud.hasDepthTex && viewport == viewer.mainViewport && !usePointcloud
-
-
- if(canUseDepthTex)getByDepthTex()
- else getByCloud()
- /* if(canUseDepthTex && !this.isMeasuring){
- getByDepthTex()
- }else{
- getByCloud()
- if(!intersectPoint && canUseDepthTex ){ //若在测量,先尝试点云,再用全景 //后来发现有深度图的点云全景visibleNode为空,pick不到的
- getByDepthTex()
- }
- } */
-
-
-
-
- //console.log(viewport.name , intersectPoint && intersectPoint.location )
- let intersect
- let intersectOnModel, allElements
-
-
- if(Potree.settings.intersectOnObjs && !dontIntersect){
- if(prop.point){
- raycaster = new THREE.Raycaster()
- var dir = new THREE.Vector3().subVectors(prop.point, camera.position).normalize()
- raycaster.set(camera.position, dir) //var origin = new THREE.Vector3(pointer.x, pointer.y, -1).unproject(camera),
- }
-
-
- allElements = this.getHoveredElements(viewer.objs.children, true, raycaster)
-
-
- if(allElements[0]){
- intersectOnModel = {//模拟点云的intersectPoint的结构写法
- hoveredElement : allElements[0] ,
- location: allElements[0].point,
- //point: {normal: allElements[0].face.normal },
- normal: allElements[0].face && allElements[0].face.normal,
- distance: allElements[0].distance,
- object: allElements[0].object
- }
- }
-
-
- }
-
- if(intersectPoint && intersectOnModel){
- if(intersectPoint.distance < intersectOnModel.distance){
- intersect = intersectPoint
- }else{
- intersect = intersectOnModel
- }
- }else{
- intersect = intersectOnModel || intersectPoint
- }
-
-
- if(viewport.camera.type == 'OrthographicCamera'/* == 'mapViewport' */){
- let pos3d = new THREE.Vector3(this.pointer.x,this.pointer.y,-1).unproject(viewport.camera); //z:-1朝外
-
- if(!intersect){
- intersect = {}
- }
- intersect.orthoIntersect = pos3d.clone()
- }
-
- //记录全部hover到的:
- if(intersect){
- intersect.allElements = allElements
- intersect.pointclouds = intersectPoint ? intersectPoint.pointclouds : []
- }
-
-
-
- viewer.addTimeMark('getIntersect','end')
- //点云费时:2-15ms
- //深度图费时: 0.1-0.2ms
- /*
- intersect && intersect.location && intersect.location.applyMatrix4(viewer.scene.scene.matrix)//add
- */
-
-
-
- if(onlyGetIntersect){
- return intersect
- }
-
- if (intersect) {
- if(viewer.showCoordType){ //显示坐标位置时
- let pos = intersect.point.position.toArray()
- if(viewer.showCoordType == "local"){
-
- }else if(viewer.showCoordType == "lonlat"){
- pos = viewer.transform.lonlatToLocal.inverse(pos)
- }else{
- pos = viewer.transform.lonlatToLocal.inverse(pos)
- pos = viewer.transform.lonlatTo4550.forward(pos)
- }
-
- viewer.dispatchEvent({
- type : "coordinateChange", pos
- })
- }
- }
- //console.log('getIntersect', !!intersectPoint)
-
- this.intersect = intersect
-
- intersect && (this.hoverViewport.lastIntersect = intersect)
-
- return intersect
- }
-
-
-
-
-
- onMouseMove (e) {
- return this.dealPointerMove( e )
- }
- dealPointerMove(e, isTouch){
-
- if(this.interactHistory.move) return //一帧只触发一次
- this.interactHistory.move = 1
-
- if(isTouch){
- var { camera, viewport } = this.updateTouchesInfo(e)
- }else {
- var { camera, viewport } = this.getPointerInViewport(e.clientX, e.clientY, this.dragViewport)
- }
-
- this.hoverViewport = viewport
- if(!viewport)return//刚变化viewport时会找不到
-
- let isFlying = this.viewer.viewports.some(e=>e.view.isFlying()) || viewer.scene.cameraAnimations.some(c=>c.onUpdate)
- let intersect
-
-
- if(e.onlyGetIntersect || (!this.drag || this.drag.object || viewport.alignment ) ){ //没有拖拽物体,但按下鼠标了的话,不intersect。触屏的就能直接避免intersect
-
- let dontIntersect = this.drag && viewport.alignment || isFlying || !Potree.settings.intersectWhenHover // flying 时可能卡顿
- //console.log('dontIntersectPointcloud',dontIntersectPointcloud)
-
- /* if(e.onlyGetIntersect ) */intersect = this.getIntersect(viewport, e.onlyGetIntersect, e.pickWindowSize, !!dontIntersect, e.whichPointcloud) //数据集多的时候卡顿
- /* else Potree.Common.intervalTool.isWaiting('getIntersect', ()=>{
- this.intersect = this.getIntersect(viewport, e.onlyGetIntersect, e.pickWindowSize, !!dontIntersect, e.whichPointcloud) //数据集多的时候卡顿
- }, 156); */
-
- //console.log('intersect', intersect)
- }
-
- if(e.onlyGetIntersect){
- /* if(Potree.settings.intersectOnObjs){
- let hoveredElements = this.getHoveredElements() //应该不用发送mouseover事件吧
- let intersect = this.getWholeIntersect(hoveredElements, intersectPoint)
- return intersect
- }
- return intersectPoint */
- return intersect
- }
- e.preventDefault();
-
-
-
- if (this.drag) {//有拖拽(不一定拖拽了物体, 也不一定按下了鼠标)
- this.drag.mouse = isTouch ? 1 : e.buttons;
- //add:
- //this.drag.pointer = this.pointer.clone();
- //this.drag.hoverViewport = this.hoverViewport
- this.drag.pointerDelta.subVectors(this.pointer, this.drag.end)
- this.drag.end.copy(this.pointer)
-
-
- if (this.drag.object && (e.buttons == Buttons.NONE || !this.drag.notPressMouse )){//如果是本不需要按鼠标的拖拽,但按下了鼠标,就不执行这段(改为拖拽场景,如添加测量时突然拖拽画面)
- if (this.logMessages) console.log(this.constructor.name + ': drag: ' + this.drag.object.name);
-
- this.drag.object.dispatchEvent($.extend(
- this.getEventDesc(e,isTouch),
- {
- type: 'drag', //拖拽物体
- }
- ))
- viewer.dispatchEvent('content_changed')
-
- } else {
-
- if (this.logMessages) console.log(this.constructor.name + ': drag: ');
- let dragConsumed = false;
- this.viewer.dispatchEvent($.extend(
- this.getEventDesc(e,isTouch),
- {
- type: 'global_drag', //拖拽画面
- consume: () => {dragConsumed = true;}
- }
- ))
-
-
- }
- }
-
-
-
- if(!isTouch || e.touches.length == 1){
-
- if((!this.drag || this.drag.notPressMouse || Potree.settings.intersectOnObjs && this.drag.object) && !isFlying){
-
- /* let blacklist = this.drag && this.drag */
- let hoveredElements = this.getHoveredElements( );
- if(hoveredElements.length > 0){
- let names = hoveredElements.map(h => h.object.name).join(", ");
- if (this.logMessages) console.log(`${this.constructor.name}: onMouseMove; hovered: '${names}'`);
- }
-
- let curr = hoveredElements.map(a => a.object).find(a => true);//只取第一个
- let prev = this.lastMouseoverElement //this.hoveredElements.map(a => a.object).find(a => true);
- if(curr !== prev){
- if(curr){
- if (this.logMessages) console.log(`${this.constructor.name}: mouseover: ${curr.name}`);
- curr.dispatchEvent({
- type: 'mouseover',
- object: curr,
- });
- }
- if(prev){
- if (this.logMessages) console.log(`${this.constructor.name}: mouseleave: ${prev.name}`);
- prev.dispatchEvent({
- type: 'mouseleave',
- object: prev,
- });
- }
-
- this.lastMouseoverElement = curr
- viewer.dispatchEvent('content_changed')
- }
- if(hoveredElements.length > 0){
- let object = hoveredElements
- .map(e => e.object)
- .find(e => (e._listeners && e._listeners['mousemove']));
-
- if(object){
- object.dispatchEvent({
- type: 'mousemove',
- object: object
- });
- }
- }
- this.hoveredElements = hoveredElements
- }
-
-
-
- //this.intersect = this.getWholeIntersect()
-
-
-
- this.viewer.dispatchEvent($.extend(
- this.getEventDesc(e,isTouch),
- {
- type: 'global_mousemove',
-
- }
- ))
-
-
- }
-
-
-
- }
-
- onMouseWheel(e){
- if(!this.enabled) return;
- if(this.logMessages) console.log(this.constructor.name + ": onMouseWheel");
-
- e.preventDefault();
- let delta = 0;
- if (e.wheelDelta !== undefined) { // WebKit / Opera / Explorer 9
- delta = e.wheelDelta;
- } else if (e.detail !== undefined) { // Firefox
- delta = -e.detail;
- }
- let ndelta = Math.sign(delta);
- // this.wheelDelta += Math.sign(delta);
-
-
- if(!this.hoverViewport){//调试手机版时会无
- var { viewport } = this.getPointerInViewport(e.clientX, e.clientY )
- this.hoverViewport = viewport
- }
-
- if (this.hoveredElement) {
- this.hoveredElement.object.dispatchEvent($.extend(
- this.getEventDesc(e,isTouch),
- {
- type: 'mousewheel',
- delta: ndelta,
- object: this.hoveredElement.object
- }
- ));
-
- } else {
- this.viewer.dispatchEvent($.extend(
- this.getEventDesc(e),
- {
- type: 'global_mousewheel',
- delta: ndelta,
- }
- ));
-
- }
-
- setTimeout(()=>{
- this.dealPointerMove(e )//add 在更新完view后重新获取intersect 和 drag
- },1)//只延迟1会崩溃吗
-
-
- }
- startDragging (object, args = null) {
- let name = object ? object.name : "no name";
- if (this.logMessages) console.log(`${this.constructor.name}: startDragging: '${name}'`);
- this.drag = {
- start: this.pointer.clone(),
- end: this.pointer.clone(),
- pointerDelta: new THREE.Vector2(0, 0),
- object: object,
- hoverViewport: this.hoverViewport, //会变化
- dragViewport: this.hoverViewport, //不变
- };
- if (args) {
- for (let key of Object.keys(args)) {
- this.drag[key] = args[key];
- }
- }
-
- if(object){
- object.dispatchEvent($.extend(
- this.getEventDesc(),
- {
- type: 'startDragging'
- }
- ));
- }
-
- }
- /* getMousePointCloudIntersection (mouse) {
- return Utils.getMousePointCloudIntersection(
- this.mouse,
- this.scene.getActiveCamera(),
- this.viewer,
- this.scene.pointclouds);
- } */
- toggleSelection (object) {
- let oldSelection = this.selection;
- let index = this.selection.indexOf(object);
- if (index === -1) {
- this.selection.push(object);
- object.dispatchEvent({
- type: 'select'
- });
- } else {
- this.selection.splice(index, 1);
- object.dispatchEvent({
- type: 'deselect'
- });
- }
- this.dispatchEvent({
- type: 'selection_changed',
- oldSelection: oldSelection,
- selection: this.selection
- });
- viewer.dispatchEvent('content_changed')
- }
- deselect(object){
- let oldSelection = this.selection;
- let index = this.selection.indexOf(object);
- if(index >= 0){
- this.selection.splice(index, 1);
- object.dispatchEvent({
- type: 'deselect'
- });
- this.dispatchEvent({
- type: 'selection_changed',
- oldSelection: oldSelection,
- selection: this.selection
- });
- }
- viewer.dispatchEvent('content_changed')
- }
- deselectAll () {
- for (let object of this.selection) {
- object.dispatchEvent({
- type: 'deselect'
- });
- }
- let oldSelection = this.selection;
- if (this.selection.length > 0) {
- this.selection = [];
- this.dispatchEvent({
- type: 'selection_changed',
- oldSelection: oldSelection,
- selection: this.selection
- });
- }
- viewer.dispatchEvent('content_changed')
- }
- isSelected (object) {
- let index = this.selection.indexOf(object);
- return index !== -1;
- }
- registerInteractiveObject(object){
- this.interactiveObjects.add(object);
- }
- removeInteractiveObject(object){
- this.interactiveObjects.delete(object);
- }
- registerInteractiveScene (scene) {
- let index = this.interactiveScenes.indexOf(scene);
- if (index === -1) {
- this.interactiveScenes.push(scene);
- }
- }
- unregisterInteractiveScene (scene) {
- let index = this.interactiveScenes.indexOf(scene);
- if (index > -1) {
- this.interactiveScenes.splice(index, 1);
- }
- }
- getHoveredElement () {
- let hoveredElements = this.getHoveredElements();
- if (hoveredElements.length > 0) {
- return hoveredElements[0];
- } else {
- return null;
- }
- }
-
-
-
-
- getHoveredElements (interactables, dontCheckDis, raycaster) {
-
- if(!interactables){
-
-
- let scenes = this.hoverViewport.interactiveScenes || this.interactiveScenes.concat(this.scene);
- let interactableListeners = ['mouseup', 'mousemove', 'mouseover', 'mouseleave', 'drag', 'drop', 'click', 'select', 'deselect'];
- interactables = []
- for (let scene of scenes) {
- scene.traverseVisible(node => {//检测加了侦听的object
- if (node._listeners && node.visible && !this.blacklist.has(node) ) {
- let hasInteractableListener = interactableListeners.filter((e) => {
- return node._listeners[e] !== undefined;
- }).length > 0;
- if (hasInteractableListener) {
- interactables.push(node);
- }
- }
- });
- }
- }
-
- let camera = this.hoverViewport.camera
- if(!raycaster){
- let ray = Utils.mouseToRay(this.pointer, camera );
-
- raycaster = new THREE.Raycaster();
- raycaster.ray.set(ray.origin, ray.direction);
- raycaster.camera = camera //add
- }
- if(camera.type == "OrthographicCamera"){//使无论多远,threshold区域都是一样宽的
- raycaster.params.Line.threshold = 20/camera.zoom
- }else{
- raycaster.params.Line.threshold = 0.04; //相对长度
- }
- raycaster.params.Line2 = {threshold :20 } //拓宽的lineWidth
-
- //raycaster.layers.enableAll()//add
- Potree.Utils.setCameraLayers(raycaster, //设置能识别到的layers(如空间模型里只有mapViewer能识别到marker)
- ['sceneObjects','mapObjects','measure', 'transformationTool', 'model'],
- this.hoverViewport && this.hoverViewport.extraEnableLayers
- )
- //this.hoverViewport.beforeRender && this.hoverViewport.beforeRender()
-
- viewer.dispatchEvent( {type:'raycaster', viewport: this.hoverViewport})//add
- let intersections = raycaster.intersectObjects(interactables.filter(o => o.visible), true, null, true); //原本是false 检测不到children
-
- let intersectionsCopy = intersections.slice()
-
-
-
- if(this.intersect && this.intersect.distance != void 0 && !dontCheckDis){//add
- intersections = intersections.filter(e=>{
- let material = e.object.material
-
- return e.object.pickDontCheckDis || ( material.depthTest == false || material.depthWrite == false) && !material.realUseDepth //!material.depthTestWhenPick
- || ( material.useDepth ? e.distance < this.intersect.distance + material.uniforms.occlusionDistance.value : e.distance < this.intersect.distance )
- })
- }
-
-
- intersections = intersections.map(e=>{//add 转化为interactables
- var object = e.object;
- do{
- if(interactables.includes(object)) {
- e.oriObject = e.object;
- e.object = object;
- break
- }
- object = object.parent
- }while(object)
-
- return e
- })
-
-
-
-
-
-
- //add for测量线,在检测到sphere时优先选中sphere而非线
-
- //intersections = intersections.sort(function(a,b){return b.object.renderOrder-a.object.renderOrder}) // 降序
- intersections = intersections.sort(function(a,b){
- let order2 = b.object.pickOrder || 0
- let order1 = a.object.pickOrder || 0
- return order2-order1
- }) // 降序
-
-
- //console.log('getHoveredElement ', intersections)
- return intersections;
- }
- /* setScene (scene) {
- this.deselectAll();
- this.scene = scene;
- } */
- update (delta) {
- }
- /*getNormalizedDrag () {
- if (!this.drag) {
- return new THREE.Vector2(0, 0);
- }
- let diff = new THREE.Vector2().subVectors(this.drag.end, this.drag.start);
- diff.x = diff.x / this.domElement.clientWidth;
- diff.y = diff.y / this.domElement.clientHeight;
- return diff;
- }
- getNormalizedLastDrag () {
- if (!this.drag) {
- return new THREE.Vector2(0, 0);
- }
- let mouseDelta = this.drag.mouseDelta.clone();
- mouseDelta.x = mouseDelta.x / this.domElement.clientWidth;
- mouseDelta.y = mouseDelta.y / this.domElement.clientHeight;
- return mouseDelta;
- } */
-
- getMouseDirection(pointer) {//add
- pointer = pointer || this.pointer
- let camera = this.hoverViewport.camera
- var t = new THREE.Vector3(pointer.x, pointer.y, -1).unproject(camera),
- i = new THREE.Vector3(pointer.x, pointer.y, 1).unproject(camera);
-
- return {origin: t, direction:i.clone().sub(t).normalize() }
-
- }
-
-
- }
|