Sprite.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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.position.y = options.disToLine || 0 //离线距离
  15. this.matrixAutoUpdate = false;
  16. this.matrixMap = new Map()
  17. if(this.root != this){
  18. this.matrixMapRoot = new Map()
  19. this.root.matrixAutoUpdate = false;
  20. }
  21. this.visiMap = new Map()
  22. this.name = options.name || 'sprite'
  23. this.useViewport = null
  24. this.viewports = options.viewports//指定更新的viewports
  25. this.visible_ = true
  26. let clear = (e)=>{
  27. this.matrixMap.clear()//清空后在所有viewport上都必须更新才能渲染 //this.needsUpdate = true
  28. }
  29. viewer.mapViewer && viewer.mapViewer.addEventListener("camera_changed", clear)
  30. viewer.addEventListener("camera_changed", clear)
  31. /* if(viewer.viewports.length == 1){//直接更新。如果有多个不在这更新,在"render.begin"
  32. this.update(e)
  33. } */
  34. let applyMatrix = (e)=>{
  35. this.applyMatrix(e)
  36. }
  37. viewer.addEventListener("raycaster", applyMatrix) //before render
  38. viewer.addEventListener("render.begin", applyMatrix) //before render
  39. viewer.addEventListener("render.begin2", applyMatrix)
  40. viewer.addEventListener("cameraSetLayers", applyMatrix)
  41. this.addEventListener('dispose', ()=>{
  42. viewer.mapViewer && viewer.mapViewer.removeEventListener("camera_changed", clear)
  43. viewer.removeEventListener("camera_changed", clear)
  44. viewer.removeEventListener("raycaster", applyMatrix) //before render
  45. viewer.removeEventListener("render.begin", applyMatrix)
  46. viewer.removeEventListener("render.begin2", applyMatrix)
  47. })
  48. }
  49. set visible(v){
  50. let oldV = this.visible_
  51. this.visible_ = v
  52. if(v && !oldV){
  53. this.matrixMap && this.matrixMap.clear() //this.update() //update内有unableCompute会无限回调
  54. }
  55. }
  56. get visible(){
  57. return this.visible_
  58. }
  59. realVisible(viewport, interactables/* , raycaster */){
  60. if(interactables){
  61. if(!interactables.some((object)=>{//interactables中是否能找到this
  62. let finded
  63. object.traverse((object)=>{
  64. if(object == this){
  65. finded = true
  66. return {stopContinue:true}
  67. }
  68. })
  69. return finded
  70. }))return
  71. }
  72. /* if(interactables && viewport.name == 'mapViewport'){
  73. console.log(this)
  74. } */
  75. if(!(/* raycaster || */viewport.camera).layers.test(this.layers)){//如地图上一般不可见测量线
  76. return false
  77. }
  78. if(!this.visible && this.unvisibleReasons && this.unvisibleReasons.some(e=>e.reason != 'unableCompute')){
  79. return false
  80. }
  81. let v = true
  82. let parent = this.parent
  83. let lastParent = this
  84. while(parent){
  85. if(parent.visible === false){
  86. v = false
  87. break;
  88. }
  89. lastParent = parent
  90. parent = parent.parent
  91. }
  92. if(v && !(lastParent instanceof THREE.Scene)){//已被删除
  93. v = false
  94. }
  95. /* if(!this.latestRealVisi && v){//变为可见后先update
  96. this.latestRealVisi = true
  97. setTimeout(()=>{
  98. this.update()
  99. },1)//延迟 防止无限调用
  100. return false
  101. }
  102. this.latestRealVisi = v */
  103. return v;
  104. }
  105. waitUpdate(){
  106. this.matrixMap.clear()//清空后在所有viewport上都必须更新才能渲染
  107. //viewer.dispatchEvent('content_changed')
  108. }
  109. update(e={}){
  110. if(!e.viewport){
  111. let viewports = this.viewports || viewer.viewports
  112. if(!viewports)return
  113. viewports.forEach(view=>{
  114. this.update({viewport:view})
  115. })
  116. return;
  117. }
  118. if(!this.root || ! this.realVisible(e.viewport, e.interactables) /* this.visible */ )return
  119. if(this.viewports && !this.viewports.includes(e.viewport) )return
  120. if(e.viewport.name == 'magnifier')return
  121. let camera = e.viewport.camera
  122. //rotation
  123. if(!this.dontFixOrient){ //orthoCamera一般要加dontFixOrient
  124. let orient2dAngle
  125. if(this.root.lineDir){
  126. this.root.updateMatrix();//先更新,getWorldPosition才能得到正确的
  127. this.root.updateMatrixWorld(true)
  128. let center = this.root.getWorldPosition(new THREE.Vector3())
  129. //由于两个端点容易在屏幕外,所以使用center和center加dir
  130. let setVisi = (state)=>{
  131. this.visiMap.set(e.viewport, state)
  132. Potree.Utils.updateVisible(this, 'unableCompute', !!state)
  133. }
  134. let r1 = Potree.Utils.getPos2d(center, e.viewport, viewer.renderArea, viewer.renderer);
  135. if(!r1.trueSide)return setVisi(false);// 但这句会使realVisible为false从而无法更新//console.error('!r1.trueSide') //中心点如果在背面直接不渲染了
  136. let r2, point2
  137. let p2State = '', len=1, p2StateHistory = []
  138. while(p2State != 'got' && p2StateHistory.length<10){
  139. point2 = center.clone().add(this.root.lineDir.clone().multiplyScalar(len));
  140. r2 = Potree.Utils.getPos2d(point2, e.viewport , viewer.renderArea, viewer.renderer );
  141. if(!r2.trueSide){ //很少遇到点2在背面的
  142. if(!p2StateHistory.includes('tooLong-reverse')){
  143. p2State = 'tooLong-reverse' //先尝试反向
  144. len = -len
  145. }else{
  146. p2State = 'tooLong'
  147. len = len / 2
  148. }
  149. }else{
  150. let dis = r2.pos.distanceTo(r1.pos)
  151. if(math.closeTo(dis,0)){
  152. //console.log('dis == 0')
  153. setVisi(false)
  154. return
  155. break
  156. }
  157. if(dis<10 && !p2StateHistory.includes('tooLong')){//和r1的屏幕距离太近,要加长,否则精度过低
  158. p2State = 'tooShort'
  159. len = 100/dis * len
  160. }else{
  161. p2State = 'got'; break;
  162. }
  163. }
  164. p2StateHistory.push(p2State)
  165. }
  166. //console.log(p2StateHistory,len)
  167. if(!r2.trueSide){
  168. return setVisi(false)//, console.log(' !r2.trueSide', )
  169. }
  170. let p1 = r1.pos, p2 = r2.pos
  171. if(p2StateHistory.filter(e=>e == 'tooLong-reverse').length%2 == 1){//反,for marker
  172. p2 = r1.pos, p1 = r2.pos
  173. }
  174. let vec = new THREE.Vector2().subVectors(p1,p2);
  175. orient2dAngle = -vec.angle() //根据测量线在屏幕上的角度在旋转label,使之和屏幕上的二维线平行。
  176. let y = Math.abs(this.position.y)
  177. let facePlane = this.root.measure && this.root.measure.facePlane
  178. let eyeDir = new THREE.Vector3().subVectors(center,camera.position)
  179. let clockWise = facePlane && facePlane.normal.dot(eyeDir/* e.viewport.view.direction */) < 0
  180. if(p1.x < p2.x){
  181. orient2dAngle += Math.PI //避免字是倒着的情况。(使字一直在线的下方)
  182. clockWise != void 0 && (this.position.y = clockWise ? y : -y)
  183. }else{
  184. clockWise != void 0 && (this.position.y = clockWise ? -y : y) //使area类型的edgeLabel都在外侧
  185. }
  186. //this.parent.text && console.log(this.parent.text, clockWise, this.position.y, e.viewport.name /* THREE.Math.radToDeg(angle), p1.x < p2.x */ )
  187. setVisi(true)
  188. }
  189. let parentQua = this.root.parent.getWorldQuaternion(new THREE.Quaternion)
  190. this.root.quaternion.multiplyQuaternions(parentQua.invert(),camera.quaternion) //乘上parentQua.invert()是为了中和掉父结点的qua,使只剩下camera.quaternion
  191. if(orient2dAngle){
  192. let qua = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), orient2dAngle)
  193. this.root.quaternion.multiply(qua)
  194. }
  195. }
  196. //scale
  197. var info = this.sizeInfo
  198. if(info){
  199. this.root.updateMatrix();//先更新,getWorldPosition才能得到正确的
  200. this.root.updateMatrixWorld(true)
  201. var scale
  202. if(info.nearBound == void 0 && info.farBound != void 0 || info.nearBound != void 0 && info.farBound == void 0){//仅限制最大或最小的话,不判断像素大小,直接限制mesh的scale
  203. //这个判断也可以写到getScaleForConstantSize里,可以更严谨控制像素宽度,这里只简单计算大小
  204. var dis = camera.position.distanceTo(this.root.getWorldPosition(new THREE.Vector3()))
  205. if(info.farBound == void 0 && dis < info.nearBound){
  206. scale = info.scale * dis / info.nearBound
  207. }else if(info.nearBound == void 0 && dis > info.farBound){
  208. scale = info.scale * dis / info.farBound
  209. }else{
  210. scale = info.scale
  211. }
  212. }else{
  213. scale = math.getScaleForConstantSize($.extend(info,{//规定下最小最大像素
  214. camera , position:this.root.getWorldPosition(new THREE.Vector3()) ,
  215. resolution: e.viewport.resolution//2
  216. }))
  217. }
  218. if(!isNaN(scale)){
  219. this.root.scale.set(scale, scale, scale);
  220. }
  221. }
  222. this.updateMatrix();
  223. //this.root.updateMatrixWorld(true)
  224. //console.log(this.root.text, this.root.matrix.elements)
  225. this.matrixMap.set(e.viewport, this.matrix.clone())
  226. if(this.root != this){
  227. this.root.updateMatrix(); //因this.position可能在两个viewport不同
  228. this.matrixMapRoot.set(e.viewport, this.root.matrix.clone())
  229. }
  230. this.needsUpdate = false
  231. this.useViewport = e.viewport
  232. }
  233. applyMatrix(e){
  234. if(!e)e = {viewport:viewer.mainViewport}//随便写一个viewport
  235. let visi = this.visiMap.get(e.viewport) //还原可见性
  236. Potree.Utils.updateVisible(this, 'unableCompute', visi == false ? false : true );
  237. /* if(e.viewport.name == 'mapViewport' && visi && this.visiMap.get(viewer.mainViewport) == false){
  238. console.log(1)
  239. } */
  240. if(e.viewport.name == 'magnifier')return
  241. if(this.viewports && !this.viewports.includes(e.viewport) )return
  242. if( !this.root || !this.realVisible(e.viewport, e.interactables) )return
  243. var matrix = this.matrixMap.get(e.viewport);
  244. if(!matrix){
  245. this.update(e)
  246. matrix = this.matrixMap.get(e.viewport);
  247. if(!matrix)return
  248. }
  249. if(e.viewport == this.useViewport){
  250. return
  251. }
  252. this.useViewport = e.viewport
  253. this.matrix.copy(matrix)
  254. if(this.root != this){
  255. var matrix2 = this.matrixMapRoot.get(e.viewport);
  256. this.root.matrix.copy(matrix2)
  257. }
  258. e.raycaster && this.root.updateMatrixWorld(true)//渲染前会自动updateMatrixWorld,但raycaster不会
  259. //console.log(this.root.name + e.viewport.name + " : "+this.root.matrixWorld.elements)
  260. }
  261. setUniforms(name,value){
  262. this.material.setUniforms(name,value)
  263. }
  264. dispose(){
  265. this.removeAllListeners()
  266. this.parent && this.parent.remove(this)
  267. this.dispatchEvent('dispose')
  268. }
  269. }
  270. /*
  271. let orient2d
  272. if(this.lineDir){
  273. this.root.updateMatrix();//先更新,getWorldPosition才能得到正确的
  274. this.root.updateMatrixWorld(true)
  275. let center = this.root.getWorldPosition(new THREE.Vector3())
  276. //由于两个端点容易在屏幕外,所以使用center和center加dir
  277. let lineDir = this.lineDir.clone();
  278. let r1 = Potree.Utils.getPos2d(center, camera, viewer.renderArea, e.viewport);
  279. if(!r1.trueSide)return Potree.Utils.updateVisible(this, 'unableCompute', false);// 但这句会使realVisible为false从而无法更新//console.error('!r1.trueSide') //中心点如果在背面直接不渲染了
  280. let r2, point2
  281. let p2State = '', len=1, p2StateHistory = []
  282. while(p2State != 'got' && p2StateHistory.length<10){
  283. point2 = center.clone().add(lineDir.multiplyScalar(len));
  284. r2 = Potree.Utils.getPos2d(point2, camera, viewer.renderArea, e.viewport);
  285. if(!r2.trueSide){ //很少遇到点2在背面的
  286. if(!p2StateHistory.includes('tooLong-reverse')){
  287. p2State = 'tooLong-reverse' //先尝试反向
  288. len = -len
  289. }else{
  290. p2State = 'tooLong'
  291. len = len / 2
  292. }
  293. }else{
  294. let dis = r2.pos.distanceTo(r1.pos)
  295. if(dis == 0){
  296. //console.log('dis == 0')
  297. Potree.Utils.updateVisible(this, 'unableCompute', false)
  298. return
  299. break
  300. }
  301. if(dis<10 && !p2StateHistory.includes('tooLong')){//和r1的屏幕距离太近,要加长,否则精度过低
  302. p2State = 'tooShort'
  303. len = 100/dis * len
  304. }else{
  305. p2State = 'got'; break;
  306. }
  307. }
  308. p2StateHistory.push(p2State)
  309. }
  310. //console.log(p2StateHistory,len)
  311. if(!r2.trueSide){
  312. return Potree.Utils.updateVisible(this, 'unableCompute', false)//, console.log(' !r2.trueSide', )
  313. }
  314. Potree.Utils.updateVisible(this, 'unableCompute', true)
  315. let p1 = r1.pos, p2 = r2.pos
  316. let vec = new THREE.Vector2().subVectors(p1,p2);
  317. let angle = -vec.angle() //根据测量线在屏幕上的角度在旋转label,使之和屏幕上的二维线平行。
  318. if(p1.x < p2.x) angle += Math.PI //避免字是倒着的情况
  319. orient2d = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0,0,1), angle)
  320. //console.log(this.parent.text, THREE.Math.radToDeg(angle), p1.x < p2.x )
  321. }
  322. let parentQua = this.root.parent.getWorldQuaternion(new THREE.Quaternion)
  323. this.root.quaternion.multiplyQuaternions(parentQua.invert(),camera.quaternion) //乘上parentQua.invert()是为了中和掉父结点的qua,使只剩下camera.quaternion
  324. if(this.lineDir){
  325. this.root.quaternion.multiply(orient2d)
  326. }
  327. */