Reticule.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. import * as THREE from "../../../libs/three.js/build/three.module.js";
  2. import {transitions, easing, lerp} from '../utils/transitions.js'
  3. import math from '../utils/math.js'
  4. let texLoader = new THREE.TextureLoader()
  5. let defaultOpacity = 0.7
  6. let Buttons = Potree.defines.Buttons
  7. //鼠标指示小圆片
  8. export default class Reticule extends THREE.Mesh{
  9. constructor(viewer){
  10. var defaultTex = texLoader.load(Potree.resourcePath+'/textures/whiteCircle.png'/* reticule-256x256.png' */)
  11. super(new THREE.PlaneBufferGeometry(0.11,0.11,1,1),new THREE.MeshBasicMaterial({
  12. side: THREE.DoubleSide ,
  13. map: defaultTex,
  14. transparent:true,
  15. depthTest: !1,
  16. opacity: defaultOpacity,
  17. //depthWrite: !1,
  18. }))
  19. this.name = 'reticule'
  20. this.defaultTex = defaultTex
  21. this.crosshairTex = texLoader.load(Potree.resourcePath+'/textures/reticule_cross_hair.png')
  22. this.forbitTex = texLoader.load(Potree.resourcePath+'/textures/pic-forbid.png')
  23. this.defaultTex.anisotropy = 4
  24. this.crosshairTex.anisotropy = 4
  25. this.forbitTex.anisotropy = 4
  26. //this.layers.set(0/* RenderLayers.RETICULE */);
  27. this.renderOrder = 100
  28. this.layers.set(Potree.config.renderLayers.marker);
  29. this.direction = new THREE.Vector3;
  30. this.mouseLastMoveTime = Date.now();
  31. this.hoverViewport;
  32. this.matrixMap = new Map
  33. this.matrixAutoUpdate = false
  34. this.hide(0)
  35. //viewer.inputHandler.addInputListener(this);
  36. Potree.settings.intersectWhenHover && viewer.addEventListener('global_mousemove',this.move.bind(this))
  37. //viewer.addEventListener('global_click',this.move.bind(this))
  38. viewer.addEventListener('global_mousedown',this.move.bind(this))//主要针对触屏
  39. this.state = {}
  40. let startCrossStyle = ()=>{
  41. this.state.cross = true
  42. this.judgeTex()
  43. }
  44. let endCrossStyle = ()=>{
  45. this.state.cross = false
  46. this.judgeTex()
  47. }
  48. viewer.addEventListener('measureMovePoint',startCrossStyle)
  49. viewer.addEventListener('endMeasureMove',endCrossStyle)
  50. viewer.addEventListener('start_inserting_tag',startCrossStyle)
  51. viewer.addEventListener('endTagMove',endCrossStyle)
  52. viewer.addEventListener('reticule_forbit',(e)=>{
  53. /* if(this.state.forbit != e.v){
  54. console.log('change forbit ',e.v)
  55. } */
  56. this.state.forbit = e.v
  57. this.judgeTex()
  58. })
  59. Potree.Utils.setObjectLayers(this, 'sceneObjects' )
  60. }
  61. judgeTex(){
  62. if(this.state.forbit){
  63. this.material.map = this.forbitTex
  64. }else if(this.state.cross){
  65. this.material.map = this.crosshairTex
  66. }else{
  67. this.material.map = this.defaultTex
  68. }
  69. viewer.mapViewer && viewer.mapViewer.dispatchEvent({type:'content_changed'})
  70. }
  71. move(e){
  72. if(e.type == "global_mousemove" && (e.isTouch || e.buttons != Buttons.NONE) && this.state != 'crosshair'){
  73. return//按下时不更新,除非拖拽测量
  74. }
  75. this.mouseLastMoveTime = Date.now()
  76. this.updatePosition(e.intersect, e.hoverViewport)
  77. }
  78. hide(duration = 500){
  79. if(this.hidden)return
  80. this.hidden = !0
  81. transitions.start(lerp.property(this.material , "opacity", 0, ()=>{//progress
  82. viewer.dispatchEvent('content_changed')
  83. }), duration,()=>{//done
  84. this.dispatchEvent({type:'update', visible:false})
  85. })
  86. this.dispatchEvent({type:'update', visible:false})
  87. setTimeout(()=>{
  88. },duration)
  89. }
  90. show(duration = 300){
  91. if(!Potree.Utils.getObjVisiByReason(this, 'force'))return
  92. //console.log("show Reticule")
  93. this.hidden = !1
  94. if(this.material.opacity <= 0){
  95. transitions.start(lerp.property(this.material, "opacity", defaultOpacity, ()=>{//progress
  96. viewer.dispatchEvent('content_changed')
  97. }), duration,()=>{//done
  98. this.dispatchEvent({type:'update', visible:false})
  99. })
  100. this.dispatchEvent({type:'update', visible:true})
  101. }
  102. }
  103. //鼠标静止一段时间它就会消失
  104. updateVisible(){
  105. Date.now() - this.mouseLastMoveTime > 1500 && !this.hidden && this.hide()
  106. }
  107. updateScale(viewport){
  108. let s, camera = viewport.camera
  109. if(camera.type == "OrthographicCamera"){
  110. var sizeInfo = this.state.cross ? {width2d:500} : {minSize : 100, maxSize : 400, nearBound : 100 , farBound : 700}
  111. s = math.getScaleForConstantSize($.extend( sizeInfo ,
  112. {position:this.position, camera, resolution:viewport.resolution/* 2 */} ))
  113. }else{
  114. let n = camera.position.distanceTo(this.position)
  115. s = 1 + .1 * n;
  116. n < 1 && (s -= 1 - n)
  117. }
  118. this.scale.set(s, s, s);
  119. }
  120. updateAtViewports(viewport){//当多个viewports时更新。更新大小等
  121. if(viewport.name == 'magnifier' )return
  122. if(this.orthoPos && this.hoverViewport && this.hoverViewport.name == 'mapViewport' && viewport != this.hoverViewport){
  123. //若是在地图上更新,在其他viewport要隐藏。因为在地图上无法得知高度。
  124. Potree.Utils.updateVisible(this, 'hoverMap', false)
  125. return;
  126. }
  127. Potree.Utils.updateVisible(this, 'hoverMap', true)
  128. if(viewport.name == 'mapViewport'){
  129. Potree.Utils.setObjectLayers(this, "bothMapAndScene")
  130. }else{//通常地图不显示reticule,只有在特殊编辑时才显示
  131. Potree.Utils.setObjectLayers(this, 'sceneObjects')
  132. }
  133. var matrix = this.matrixMap.get(viewport)
  134. if(!matrix){
  135. this.updateScale(viewport)
  136. this.updateMatrix();
  137. //this.updateMatrixWorld()
  138. this.matrixMap.set(viewport, this.matrix.clone())
  139. }else{
  140. this.matrix.copy(matrix)
  141. //this.updateMatrixWorld()
  142. }
  143. }
  144. updatePosition(intersect, viewport ){ //在地图(当地图融合到viewer时)和场景里都显示且完全相同(大小可能不同)
  145. if (Potree.Utils.getObjVisiByReason(this, 'force')) {//没有被强制隐藏,如进入某个页面后强制不显示
  146. if (!intersect /* || !intersect.point.normal */){
  147. return //this.hide();
  148. }
  149. let location = intersect.location //|| intersect.orthoIntersect.clone()
  150. let normal
  151. if(!location)return
  152. this.show( 300);
  153. normal = intersect.normal
  154. if(normal){
  155. let ratio = /* Potree.settings.useDepthTex ? 1 : */ 0.2;
  156. this.direction = this.direction.multiplyScalar(1-ratio);
  157. this.direction.add(normal.clone().multiplyScalar(ratio));
  158. }
  159. this.position.copy(location)/* .add(normal.clone().multiplyScalar(.01)); */
  160. this.updateMatrix(); //lookAt之前要保证得到matrix
  161. this.lookAt(this.position.clone().add(this.direction));
  162. this.hoverViewport = viewport //记录下最近一次hover过的viewport
  163. this.updateScale(viewport)
  164. {//存储matrix,节省计算
  165. this.updateMatrix();
  166. //this.updateMatrixWorld()
  167. this.matrixMap.clear();//重新计算
  168. this.matrixMap.set(viewport, this.matrix.clone())
  169. //别处会updateMatrixWorld
  170. }
  171. this.dispatchEvent({type:'update'})
  172. //为什么navvis在校准数据集时每个viewport里reticule的朝向都刚好垂直于屏幕,似乎限定在了一定范围内,还是在pick时就只pick范围内的点?
  173. }
  174. }
  175. //navvis在地图等地方看reticule是有厚度的
  176. /* updateMatrixWorld(force){
  177. console.log('updateMatrixWorld', force)
  178. super.updateMatrixWorld(force)
  179. } */
  180. }