Sprite.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. import * as THREE from "../../../libs/three.js/build/three.module.js";
  2. import DepthBasicMaterial from "../materials/DepthBasicMaterial.js";
  3. import math from "../utils/math.js";
  4. const geo = new THREE.PlaneBufferGeometry(1,1)
  5. export default class Sprite extends THREE.Mesh{
  6. constructor(options={}){
  7. super(geo, options.mat || new DepthBasicMaterial(options))/* ({map:options.map, useDepth:options.useDepth})) */
  8. this.root = options.root || this;
  9. this.renderOrder = options.renderOrder != void 0 ? options.renderOrder : 4;
  10. this.pickOrder = options.pickOrder || 0
  11. this.sizeInfo = options.sizeInfo
  12. this.dontFixOrient = options.dontFixOrient
  13. this.options = options
  14. this.lineDir = options.lineDir
  15. this.root.matrixAutoUpdate = false;
  16. this.matrixMap = new Map()
  17. this.name = options.name || 'sprite'
  18. this.useViewport = null
  19. this.viewports = options.viewports//指定更新的viewports
  20. this.visible_ = true
  21. let update = (e)=>{
  22. //this.update(e)
  23. this.needsUpdate = true
  24. }
  25. viewer.mapViewer && viewer.mapViewer.addEventListener("camera_changed", update)
  26. viewer.addEventListener("camera_changed", update)
  27. /* if(viewer.viewports.length == 1){//直接更新。如果有多个不在这更新,在"render.begin"
  28. this.update(e)
  29. } */
  30. let applyMatrix = (e)=>{
  31. if(this.needsUpdate) this.update(e)
  32. else this.applyMatrix(e)
  33. }
  34. viewer.addEventListener("raycaster", applyMatrix) //before render
  35. viewer.addEventListener("render.begin", applyMatrix) //before render //magnifier时要禁止吗
  36. this.addEventListener('dispose', ()=>{
  37. viewer.mapViewer && viewer.mapViewer.removeEventListener("camera_changed", update)
  38. viewer.removeEventListener("camera_changed", update)
  39. viewer.removeEventListener("raycaster", applyMatrix) //before render
  40. viewer.removeEventListener("render.begin", applyMatrix)
  41. this.dispose()
  42. })
  43. }
  44. set visible(v){
  45. this.visible_ = v
  46. if(v){
  47. this.update()
  48. }
  49. }
  50. get visible(){
  51. return this.visible_
  52. }
  53. realVisible(){
  54. let v = true
  55. let parent = this
  56. let lastParent
  57. while(parent){
  58. if(parent.visible === false){
  59. v = false
  60. break;
  61. }
  62. lastParent = parent
  63. parent = parent.parent
  64. }
  65. if(v && !(lastParent instanceof THREE.Scene)){//已被删除
  66. v = false
  67. }
  68. /* if(!this.latestRealVisi && v){//变为可见后先update
  69. this.latestRealVisi = true
  70. setTimeout(()=>{
  71. this.update() -----删掉是因为更新时返回false导致无法立即更新
  72. },1)//延迟 防止无限调用
  73. return false
  74. }
  75. this.latestRealVisi = v*/
  76. return v;
  77. }
  78. update(e={}){
  79. if(!e.viewport){
  80. let viewports = this.viewports || viewer.viewports
  81. if(!viewports)return
  82. viewports.forEach(view=>{
  83. this.update({viewport:view})
  84. })
  85. return;
  86. }
  87. if(!this.root || ! this.realVisible() /* this.visible */ )return
  88. if(this.viewports && !this.viewports.includes(e.viewport) )return
  89. if(e.viewport.name == 'magnifier')return
  90. let camera = e.viewport.camera
  91. //rotation
  92. if(!this.dontFixOrient){ //orthoCamera一般要加dontFixOrient
  93. let orient2d
  94. if(this.lineDir){
  95. this.root.updateMatrix();//先更新,getWorldPosition才能得到正确的
  96. this.root.updateMatrixWorld(true)
  97. let center = this.root.getWorldPosition(new THREE.Vector3())
  98. //由于两个端点容易在屏幕外,所以使用center和center加dir
  99. let lineDir = this.lineDir.clone();
  100. let r1 = Potree.Utils.getPos2d(center, camera, viewer.renderArea, e.viewport);
  101. if(!r1.trueSide)return //Potree.Utils.updateVisible(this, 'notTrueSide', false); 但这句会使realVisible为false从而无法更新//console.error('!r1.trueSide') //中心点如果在背面直接不渲染了
  102. let r2, point2
  103. let p2State = '', len=1, p2StateHistory = []
  104. while(p2State != 'got' && p2StateHistory.length<10){
  105. point2 = center.clone().add(lineDir.multiplyScalar(len));
  106. r2 = Potree.Utils.getPos2d(point2, camera, viewer.renderArea, e.viewport);
  107. if(!r2.trueSide){ //很少遇到点2在背面的
  108. if(!p2StateHistory.includes('tooLong-reverse')){
  109. p2State = 'tooLong-reverse' //先尝试反向
  110. len = -len
  111. }else{
  112. p2State = 'tooLong'
  113. len = len / 2
  114. }
  115. }else{
  116. let dis = r2.pos.distanceTo(r1.pos)
  117. if(dis<10 && !p2StateHistory.includes('tooLong')){//和r1的屏幕距离太近,要加长,否则精度过低
  118. p2State = 'tooShort'
  119. len = 100/dis * len
  120. }else{
  121. p2State = 'got'; break;
  122. }
  123. }
  124. p2StateHistory.push(p2State)
  125. }
  126. //console.log(p2StateHistory,len)
  127. if(!r2.trueSide){
  128. return //Potree.Utils.updateVisible(this, 'notTrueSide', false), console.log(' !r2.trueSide', )
  129. }
  130. //Potree.Utils.updateVisible(this, 'notTrueSide', true)
  131. let p1 = r1.pos, p2 = r2.pos
  132. let vec = new THREE.Vector2().subVectors(p1,p2);
  133. let angle = -vec.angle() //根据测量线在屏幕上的角度在旋转label,使之和屏幕上的二维线平行。
  134. if(p1.x < p2.x) angle += Math.PI //避免字是倒着的情况
  135. orient2d = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), angle)
  136. //console.log(this.parent.text, THREE.Math.radToDeg(angle), p1.x < p2.x )
  137. }
  138. let parentQua = this.root.parent.getWorldQuaternion(new THREE.Quaternion)
  139. this.root.quaternion.multiplyQuaternions(parentQua.invert(),camera.quaternion) //乘上parentQua.invert()是为了中和掉父结点的qua,使只剩下camera.quaternion
  140. if(this.lineDir){
  141. this.root.quaternion.multiply(orient2d)
  142. }
  143. }
  144. //scale
  145. var info = this.sizeInfo
  146. if(info){
  147. this.root.updateMatrix();//先更新,getWorldPosition才能得到正确的
  148. this.root.updateMatrixWorld(true)
  149. var scale
  150. if(info.nearBound == void 0 && info.farBound != void 0 || info.nearBound != void 0 && info.farBound == void 0){//仅限制最大或最小的话,不判断像素大小,直接限制mesh的scale
  151. //这个判断也可以写到getScaleForConstantSize里,可以更严谨控制像素宽度,这里只简单计算大小
  152. var dis = camera.position.distanceTo(this.root.getWorldPosition(new THREE.Vector3()))
  153. if(info.farBound == void 0 && dis < info.nearBound){
  154. scale = info.scale * dis / info.nearBound
  155. }else if(info.nearBound == void 0 && dis > info.farBound){
  156. scale = info.scale * dis / info.farBound
  157. }else{
  158. scale = info.scale
  159. }
  160. }else{
  161. scale = math.getScaleForConstantSize($.extend(info,{//规定下最小最大像素
  162. camera , position:this.root.getWorldPosition(new THREE.Vector3()) ,
  163. resolution: e.viewport.resolution//2
  164. }))
  165. }
  166. if(!isNaN(scale)){
  167. this.root.scale.set(scale, scale, scale);
  168. }
  169. }
  170. this.root.updateMatrix();
  171. this.root.updateMatrixWorld(true)
  172. this.matrixMap.set(e.viewport, this.root.matrix.clone())
  173. this.useViewport = e.viewport
  174. }
  175. applyMatrix(e){
  176. if(!e)e = {viewport:viewer.mainViewport}//随便写一个viewport
  177. if(e.viewport.name == 'magnifier')return
  178. /* if(this.name == 'measure_point'){
  179. console.log(1)
  180. } */
  181. if(this.viewports && !this.viewports.includes(e.viewport) )return
  182. if( !this.root || !this.realVisible() )return
  183. var matrix = this.matrixMap.get(e.viewport);
  184. if(!matrix){
  185. this.update(e)
  186. matrix = this.matrixMap.get(e.viewport);
  187. if(!matrix)return
  188. }
  189. if(e.viewport == this.useViewport){
  190. return
  191. }
  192. this.useViewport = e.viewport
  193. this.root.matrix.copy(matrix)
  194. this.root.updateMatrixWorld(true)
  195. //console.log(this.root.name + e.viewport.name + " : "+this.root.matrixWorld.elements)
  196. }
  197. setUniforms(name,value){
  198. this.material.setUniforms(name,value)
  199. }
  200. dispose(){
  201. this.removeAllListeners()
  202. this.parent && this.parent.remove(this)
  203. }
  204. }