Magnifier.js 7.4 KB

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