Magnifier.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import * as THREE from "../../libs/three.js/build/three.module.js";
  2. import math from './math'
  3. import Viewport from '../viewer/Viewport'
  4. let texLoader = new THREE.TextureLoader()
  5. let circleGeo = new THREE.CircleGeometry(1.45,100);
  6. const magDistance_ = 2;//相机离目标位置的距离的分界线,当离得远时要缩小fov以使看到的视野固定(望远镜效果)
  7. const radius_ = 0.2; //当相机离目标位置的距离>magDistance_时,希望看到的视野的半径
  8. const maxFov = THREE.Math.radToDeg(Math.atan(radius_ / magDistance_ )) * 2//提前计算出当相机离目标位置的距离<magDistance_时的fov,均使用=magDistance_时的fov。只要保证该fov大于主相机的fov就会有放大效果
  9. const width2dPX = 200/1.4;//px
  10. export default class Magnifier extends THREE.Object3D {//放大镜or望远镜
  11. constructor (viewer) {
  12. super()
  13. this.width = this.height = 256;
  14. this.camera = new THREE.PerspectiveCamera(50, 1, 0.1, 10000); //fov aspect near far
  15. this.camera.up = new THREE.Vector3(0,0,1)
  16. this.viewport = new Viewport( null, this.camera, {
  17. left:0, bottom:0, width:1, height: 1, name:'magnifier'
  18. })
  19. this.viewport.setResolution(this.width, this.height,0,0)
  20. this.renderTarget = new THREE.WebGLRenderTarget(this.width,this.height, {
  21. minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter,
  22. format: THREE.RGBAFormat ,
  23. /* type: THREE.FloatType,
  24. minFilter: THREE.NearestFilter,
  25. magFilter: THREE.NearestFilter,
  26. */
  27. } )
  28. this.rtEDL = new THREE.WebGLRenderTarget(this.width, this.height, {
  29. minFilter: THREE.NearestFilter,
  30. magFilter: THREE.NearestFilter,
  31. format: THREE.RGBAFormat,
  32. type: THREE.FloatType,
  33. depthTexture: new THREE.DepthTexture(undefined, undefined, THREE.UnsignedIntType)
  34. });
  35. this.mesh = new THREE.Mesh(circleGeo, new THREE.MeshBasicMaterial({
  36. side: THREE.DoubleSide ,
  37. map: this.renderTarget.texture ,
  38. transparent:true,
  39. depthTest: !1,
  40. //depthWrite: !1,
  41. }))
  42. this.overlayMesh = new THREE.Mesh(circleGeo, new THREE.MeshBasicMaterial({
  43. side: THREE.DoubleSide ,
  44. map:texLoader.load(Potree.resourcePath+'/textures/crosshair.png') ,
  45. transparent:true,
  46. depthTest: !1,
  47. //depthWrite: !1,
  48. }))
  49. this.add(this.mesh)
  50. this.add(this.overlayMesh)
  51. this.position.set(-1000,-1000,-100000)//令它看不见
  52. this.mesh.renderOrder = 10;
  53. this.overlayMesh.renderOrder = 11;
  54. this.aimPos
  55. viewer.setObjectLayers(this, 'magnifier' )
  56. //viewer.inputHandler.addInputListener(this)
  57. viewer.addEventListener('camera_changed',(e)=>{ // 平移、滚轮时更新
  58. if(e.viewport == viewer.mainViewport) this.update()
  59. })
  60. this.mesh.layers.set(Potree.config.renderLayers.magnifier);
  61. this.overlayMesh.layers.set(Potree.config.renderLayers.magnifier);
  62. //this.layers.set(Potree.config.renderLayers.magnifier);//这句在外层写没用
  63. this.dontRender = false
  64. viewer.addEventListener('global_drag', (e)=>{//拖拽时不渲染。主要是右键平移时渲染延迟了,会闪烁。
  65. this.dontRender = true
  66. })
  67. viewer.addEventListener('global_drop', (e)=>{
  68. this.dontRender = false
  69. })
  70. viewer.addEventListener('global_mousemove', (e)=>{
  71. if(e.hoverViewport == viewer.mainViewport){
  72. viewer.updateVisible(this,"atViewport", true)
  73. this.update(e.intersectPoint && e.intersectPoint.location)
  74. }else{
  75. viewer.updateVisible(this,"atViewport", false) //小地图不显示
  76. }
  77. })
  78. /* viewer.addEventListener("beginSplitView",()=>{
  79. this.updateVisible("splitView", false)
  80. })
  81. viewer.addEventListener("finishSplitView",()=>{
  82. this.updateVisible("splitView", true)
  83. }) */
  84. this.addEventListener("setEnable",(e)=>{
  85. viewer.updateVisible(this, "enable", e.value) //界面开关
  86. })
  87. if(Potree.settings.isOfficial){
  88. viewer.updateVisible(this, "enable", false)
  89. }else{
  90. viewer.updateVisible(this, "measure", false)
  91. viewer.addEventListener("measureMovePoint",()=>{//测量开始
  92. viewer.updateVisible(this, "measure", true)
  93. })
  94. viewer.addEventListener("endMeasureMove",()=>{
  95. viewer.updateVisible(this, "measure", false)
  96. })
  97. }
  98. }
  99. /* updateVisible(reason, ifShow){//当所有加入的条件都不为false时才显示
  100. if(ifShow){
  101. var index = this.unvisibleReasons.indexOf(reason)
  102. index > -1 && this.unvisibleReasons.splice(index, 1)
  103. if(this.unvisibleReasons.length == 0)this.visible = true
  104. }else{
  105. if(!this.unvisibleReasons.includes(reason)) this.unvisibleReasons.push(reason)
  106. this.visible = false
  107. }
  108. } */
  109. update(aimPos){
  110. aimPos = aimPos instanceof THREE.Vector3 ? aimPos : this.aimPos
  111. if(!aimPos || !this.visible)return
  112. //console.log(aimPos)
  113. //相机位置
  114. var playerCamera = viewer.scene.getActiveCamera()
  115. var playerPos = playerCamera.position;//viewer.scene.view.getPivot()
  116. var dis = playerPos.distanceTo(aimPos);
  117. /* var vec = playerPos.clone().sub(aimPos).normalize().multiplyScalar(dis > magDistance_ ? magDistance_ : magDistance_/2)
  118. this.camera.position.copy(aimPos.clone().add(vec))
  119. this.camera.lookAt(aimPos) */
  120. if(dis<magDistance_){
  121. this.camera.fov = maxFov
  122. }else{
  123. this.camera.fov = THREE.Math.radToDeg(Math.atan(radius_ / dis )) * 2 //radius_是能看到的范围半径。当dis大于magDistance_时就放大,否则维持fov为maxFov
  124. }
  125. this.camera.updateProjectionMatrix()
  126. this.camera.position.copy(playerPos)
  127. this.camera.lookAt(aimPos)
  128. this.quaternion.copy(playerCamera.quaternion);
  129. //mesh位置
  130. let screenPos = viewer.inputHandler.mouse.clone();
  131. let clientWidth = viewer.inputHandler.domElement.clientWidth * viewer.mainViewport.width;
  132. let clientHeight = viewer.inputHandler.domElement.clientHeight * viewer.mainViewport.height;
  133. screenPos.x = screenPos.x / clientWidth * 2 - 1;
  134. screenPos.y = -((screenPos.y < 300 ? 200 : -200) + screenPos.y) / clientHeight * 2 + 1;
  135. let newPos = new THREE.Vector3(screenPos.x,screenPos.y,0.8).unproject(playerCamera); //z:-1朝外
  136. let dir = newPos.clone().sub(playerPos).normalize().multiplyScalar(10);//这个数值要大于playerCamera.near
  137. this.position.copy(playerPos.clone().add(dir))
  138. this.aimPos = aimPos
  139. var scale = math.getScaleForConstantSize({//
  140. width2d : width2dPX,
  141. camera:viewer.scene.getActiveCamera(), position: this.getWorldPosition(new THREE.Vector3()),
  142. resolution: viewer.mainViewport.resolution2
  143. })
  144. this.scale.set(scale, scale, scale);
  145. if(!this.dontRender){
  146. this.waitRender = true
  147. }
  148. }//位置需要计算,不仅仅是点云,所以需要深度图
  149. render(){
  150. if(!this.waitRender)return
  151. //this.visible = false;//防止放大镜里有自己
  152. viewer.render({
  153. target : this.renderTarget,
  154. viewports : [this.viewport],
  155. camera : this.camera,
  156. magnifier : true,
  157. rtEDL: this.rtEDL
  158. /* width :this.renderTarget.width,
  159. height: this.renderTarget.height, */
  160. })
  161. //this.visible = true;
  162. this.waitRender = false
  163. }
  164. }