ConvertViews.js 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. import math from './math.js'
  2. let bimViewer
  3. export default class ConvertViews extends THREE.EventDispatcher{
  4. constructor() {
  5. super()
  6. this.sourceApp = null
  7. this.targetApp = null
  8. this.sourceType = null
  9. this.targetPano = null
  10. }
  11. clear(o={}){
  12. this.loaded = false;
  13. this.sourceApp = null;
  14. if(!o.dontClearTarget){
  15. this.targetApp = null
  16. }
  17. this.dispatchEvent({type:'clearBind-sameType'})
  18. window.Log('clear done')
  19. }
  20. /*
  21. laser暂时做成这样: 全景模式时不跟踪pos,跟踪pano变化。点云模式时也跟踪pano变化,但移动时完全跟踪位置变化 ,所以会有左边marker在脚下,右边marker不在脚下的情况。
  22. */
  23. getCameraData(app){
  24. if(app.sceneType == 'laser'){
  25. let camera = app.viewer.mainViewport.camera
  26. return {
  27. position: camera.position.clone(),
  28. quaternion: camera.quaternion.clone(),
  29. fov: camera.fov,
  30. }
  31. }else if(app.sceneType == 'kankan'){
  32. let player = app.app.core.get('Player')
  33. return {
  34. position: player.position.clone(),
  35. quaternion: player.quaternion.clone(),
  36. fov: player.zoomFov,
  37. }
  38. }
  39. }
  40. bindWithSameType(sourceApp,targetApp, isSwitchScene){
  41. this.sourceApp = sourceApp
  42. this.targetApp = targetApp
  43. this.diffLon = this.computeAveDiffLon()
  44. this.diffQuaternion = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), this.diffLon)
  45. this.diffQuaternionInvert = this.diffQuaternion.clone().invert()
  46. sourceApp.sceneName = 'sourceApp'
  47. targetApp.sceneName = 'targetApp'
  48. if(sourceApp.sceneType == 'laser'){
  49. this.computeShift()
  50. //只监听左边
  51. let displayMode = (e)=>{
  52. targetApp.Potree.settings.displayMode = e.mode
  53. }
  54. sourceApp.viewer.images360.addEventListener('endChangeMode', displayMode)
  55. let dispose = ()=>{
  56. if(!sourceApp.viewer || !sourceApp.viewer.images360)return
  57. sourceApp.viewer.images360.removeEventListener('endChangeMode', displayMode)
  58. this.removeEventListener('clearBind-sameType',dispose)
  59. }
  60. this.addEventListener('clearBind-sameType',dispose)
  61. }
  62. let bind = (master, customer)=>{ //相互都能带动对方
  63. if(sourceApp.sceneType == 'laser'){
  64. var flyToPano = (e)=>{//同步点位
  65. if(master != this.masterApp )return
  66. let pano = customer.viewer.images360.panos[e.toPano.pano.id]
  67. if(!pano)return console.error('找不到该e.panoId', e.toPano.pano.id)
  68. customer.viewer.images360.flyToPano({pano} )
  69. }
  70. master.viewer.images360.addEventListener('flyToPano',flyToPano)
  71. var cameraMove = (e)=>{
  72. if(master != this.masterApp || !customer.viewer )return
  73. //console.log('cameraMove')
  74. if(master.viewer.images360.isAtPano() || master.Potree.settings.displayMode == 'showPanos'){ //转换朝向
  75. if(e.changeInfo && e.changeInfo.quaternionChanged){
  76. let data = this.getCameraData(master)
  77. let diffQua = master == this.sourceApp ? this.diffQuaternion : this.diffQuaternionInvert
  78. let quaternion = data.quaternion.premultiply(diffQua)
  79. let rotation = new THREE.Euler().setFromQuaternion(quaternion)
  80. customer.viewer.mainViewport.view.rotation = rotation
  81. //console.log('cameraMove',customer == this.targetApp)
  82. }
  83. if(master.Potree.settings.displayMode == 'showPanos' ){
  84. if(customer.viewer.mainViewport.camera.fov != master.viewer.mainViewport.camera.fov){
  85. customer.viewer.mainViewport.camera.fov = master.viewer.mainViewport.camera.fov
  86. customer.viewer.mainViewport.camera.updateProjectionMatrix()
  87. }
  88. }
  89. }else{//转换朝向和位置
  90. let data = this.getCameraData(master)
  91. this.receive(data, customer )
  92. }
  93. }
  94. master.viewer.addEventListener('camera_changed',cameraMove)
  95. var dragEnd = (e)=>{
  96. if(customer.viewer.inputHandler.drag){
  97. customer.viewer.inputHandler.onMouseUp(e) //从一侧拖拽到另一侧松开时,需要执行原先一侧的mouseup
  98. }
  99. }
  100. master.addEventListener('mouseup',dragEnd)
  101. }else if(sourceApp.sceneType == 'kankan'){
  102. var player1 = master.app.core.get('Player')
  103. var player2 = customer.app.core.get('Player')
  104. let this_ = this
  105. var flyToPano = (e)=>{//同步点位
  106. if(master != this_.masterApp )return
  107. let pano = player2.model.panos.index[e.panoId]
  108. if(!pano)return console.error('找不到该e.panoId',e.panoId)
  109. player2.flyToPano({pano} )
  110. }
  111. player1.on("flying.started",flyToPano)
  112. var cameraMove = (e)=>{//暂时只有漫游模式
  113. if(!e.hasChanged.cameraChanged)return
  114. let diffLon = master == this.sourceApp ? this.diffLon : -this.diffLon
  115. player2.cameraControls.controls.panorama.lon = player1.cameraControls.controls.panorama.lon + diffLon
  116. player2.cameraControls.controls.panorama.lat = player1.cameraControls.controls.panorama.lat
  117. if(player2.zoomLevel != player1.zoomLevel){
  118. player2.zoomTo(player1.zoomLevel)
  119. }
  120. }
  121. player1.on("update",cameraMove)
  122. }
  123. let changeMaster = ()=>{
  124. this.masterApp = master //主控方。只有主控方能控制被控方。鼠标操作过mousedown mousewheel等才能认定为主控方
  125. }
  126. let dom = sourceApp.sceneType == 'laser' ? master.viewer.inputHandler.domElement : master.app.core.get('Player').domElement
  127. dom.addEventListener('pointerdown',changeMaster )
  128. dom.addEventListener('mousewheel',changeMaster )
  129. let dispose = ()=>{
  130. if(master.sceneType == 'laser'){
  131. if(!master.viewer )return //master已替换,不用处理
  132. master.viewer.images360.removeEventListener('flyToPano',flyToPano)
  133. master.viewer.removeEventListener('camera_changed',cameraMove)
  134. }else if(master.sceneType == 'kankan'){
  135. player1.off("flying.started",flyToPano)
  136. player1.off("update",cameraMove)
  137. }
  138. master.removeEventListener('mousedown',changeMaster)
  139. master.removeEventListener('mousewheel',changeMaster)
  140. master.removeEventListener('mouseup',dragEnd)
  141. this.removeEventListener('clearBind-sameType',dispose)
  142. }
  143. this.addEventListener('clearBind-sameType',dispose)
  144. }
  145. bind(sourceApp, targetApp)
  146. bind(targetApp, sourceApp)
  147. //切换其中一个场景后同步初始漫游点
  148. if(isSwitchScene){
  149. setTimeout(()=>{
  150. let master = isSwitchScene == 'target' ? sourceApp : targetApp
  151. let customer = isSwitchScene == 'target' ? targetApp : sourceApp
  152. this.masterApp = master
  153. customer.Potree.settings.displayMode = master.Potree.settings.displayMode
  154. if(master.sceneType == 'laser'){
  155. let pano = master.viewer.images360.nextPano || master.viewer.images360.currentPano
  156. let pano2 = pano && customer.viewer.images360.panos[pano.id]
  157. pano2 && customer.viewer.images360.flyToPano({pano : pano2, duration: 0 })
  158. master.viewer.dispatchEvent({type:'camera_changed',changeInfo:{quaternionChanged:true},viewport:master.viewer.mainViewport }) //朝向位置同步
  159. }else{
  160. master.app.core.get('Player').emit("update")//朝向同步
  161. let pano = master.app.core.get('Player').nextPano || master.app.core.get('Player').currentPano
  162. let pano2 = pano && customer.app.core.get('Player').model.panos.index[pano.id]
  163. pano2 && customer.app.core.get('Player').flyToPano({pano: pano2})
  164. }
  165. },1)//要延迟,否则角度和pano都不成功
  166. }
  167. this.loaded = true
  168. }
  169. bindWithBim(sourceApp, targetApp, sourcePano, targetPano ) {
  170. //if (!this.player1.model.panos.list.length || !this.player2.model.panos.list.length) return
  171. if(this.loaded || !targetApp ) return
  172. let needBindEvent = !this.targetApp // 若targetApp存在表明targetApp的dom未换掉,事件还存在
  173. this.sourceApp = sourceApp
  174. this.targetApp = targetApp
  175. bimViewer = this.bimViewer = targetApp.viewer
  176. this.needConvertAxis = sourceApp.sceneType == 'kankan' && targetApp.sceneType == 'bim'// Y朝上需要转换
  177. this.lastCamStatus = bimViewer.getCameraStatus()
  178. this.computeShift(sourcePano, targetPano)
  179. bimViewer.setNavigationMode(targetApp.Glodon.Bimface.Viewer.NavigationMode3D.Walk)
  180. bimViewer.setFlySpeedRate(5)
  181. bimViewer.getViewer().setTransitionAnimationState(false) //setCameraStatus瞬间变化相机 ,or setCameraAnimation?
  182. bimViewer.addEventListener('Rendered', (e)=>{//反向改变左侧相机
  183. let info = bimViewer.getCameraStatus()
  184. let poseChanged = !math.closeTo(this.lastCamStatus.position, info.position)
  185. || !math.closeTo(this.lastCamStatus.target, info.target)
  186. || !math.closeTo(this.lastCamStatus.fov, info.fov)
  187. if(poseChanged){
  188. if(this.leftCanChangePos()){
  189. this.send(info)
  190. this.lastCamStatus = info
  191. }
  192. }
  193. })
  194. if(sourceApp.sceneType == 'laser'){
  195. this.sourceDom = this.sourceApp.viewer.inputHandler.domElement
  196. sourceApp.viewer.addEventListener('camera_changed', e => {
  197. targetApp && this.receive(this.getCameraData(sourceApp))
  198. })
  199. //master.viewer.images360.isAtPano() || master.Potree.settings.displayMode == 'showPanos'
  200. /* if(this.lastBimStatus){
  201. this.lastBimStatus
  202. let pano
  203. if(this.lastBimStatus.panoId != void 0) pano = this.sourceApp.viewer.images360.panos[this.lastBimStatus.panoId]
  204. this.sourceApp.viewer.dispatchEvent({type:'camera_changed',changeInfo:{quaternionChanged:true},viewport:this.sourceApp.viewer.mainViewport }) //朝向位置同步
  205. pano && customer.viewer.images360.flyToPano({pano, duration: 0 })
  206. } */
  207. }else if(sourceApp.sceneType == 'kankan'){
  208. let player = this.sourceApp.app.core.get('Player')
  209. this.sourceDom = player.domElement
  210. var cameraMove = (e)=>{//暂时只有漫游模式
  211. if(!e.hasChanged.cameraChanged2)return
  212. this.receive(this.getCameraData(sourceApp))
  213. }
  214. player.on("update",cameraMove)
  215. }
  216. /* bimViewer.addEventListener(targetApp.Glodon.Bimface.Viewer.Viewer3DEvent.ViewAdded,
  217. ()=>{
  218. this.loaded = true
  219. if(this.firstData){
  220. this.receive(this.firstData)
  221. }
  222. }
  223. ) */
  224. this.loaded = true
  225. this.receive(this.getCameraData(sourceApp))
  226. needBindEvent && this.bindCamEvent()
  227. }
  228. leftCanChangePos(){
  229. return this.sourceApp.sceneType == 'laser' && this.sourceApp.Potree.settings.displayMode != 'showPanos'
  230. }
  231. bindCamEvent(){//传递到另一边的dom
  232. this.lockCamera(true)
  233. /* this.targetApp.addEventListener(this.targetApp.Glodon.Bimface.Viewer.Viewer3DEvent.MouseClicked,(e)=>{
  234. console.log('MouseClicked',e)
  235. }); */
  236. let dom1 = this.bimViewer.getDomElement()
  237. let getEvent = (type, e)=>{
  238. let clientWidth1 = this.sourceDom.clientWidth
  239. let clientHeight1 = this.sourceDom.clientHeight
  240. let clientWidth2 = dom1.clientWidth
  241. let clientHeight2 = dom1.clientHeight
  242. return new MouseEvent(type, {
  243. bubbles: false,//?
  244. cancelable: true,
  245. view: this.sourceApp,
  246. /* clientX: e.clientX,
  247. clientY: e.clientY, */
  248. clientX: clientWidth1 * e.clientX / clientWidth2 , //鼠标在右屏的比例的左屏的相同,针对右屏全屏等左右不对称的情况
  249. clientY: clientHeight1 * e.clientY / clientHeight2,
  250. button: e.button, buttons: e.buttons, which: e.which,
  251. altKey: e.altKey, ctrlKey: e.ctrlKey, shiftKey:e.shiftKey, metaKey: e.metaKey,
  252. detail:e.detail,
  253. //target : dom2
  254. });
  255. }
  256. //let pointerDownPos = new THREE.Vector2
  257. dom1.addEventListener('mousedown',(e)=>{
  258. let event = getEvent('mousedown', e)
  259. this.sourceApp && this.sourceDom.dispatchEvent(event)
  260. //pointerDownPos.set(e.clientX,e.clientY)
  261. })
  262. dom1.addEventListener('mousemove',(e)=>{
  263. let event = getEvent('mousemove', e)
  264. this.sourceApp && this.sourceDom.dispatchEvent(event)
  265. })
  266. dom1.addEventListener('mouseup',(e)=>{
  267. if(!this.sourceApp)return
  268. let event = getEvent('mouseup', e)
  269. event.unableClick = true //最好禁止右侧点击行走。否则和点击效果冲突
  270. if(this.sourceApp.sceneType == 'laser'){
  271. this.sourceApp.dispatchEvent(event) //mouseup 在laser中加在window上的
  272. }else{
  273. let player = this.sourceApp.app.core.get('Player')
  274. player.mouseCouldBeClickToMove = false //dont click
  275. this.sourceDom.dispatchEvent(event)
  276. }
  277. })
  278. dom1.addEventListener('mousewheel',(e)=>{
  279. let event = getEvent('mousewheel', e)
  280. event.wheelDelta = e.wheelDelta //wheelDelta没法在getEvent参数中赋值
  281. this.sourceApp && this.sourceDom.dispatchEvent(event)
  282. })
  283. let stop = (e)=>{ //drag到另一边时停止旋转, 防止转到另一边
  284. let event = getEvent('mouseup', e)
  285. this.sourceApp && this.sourceApp.dispatchEvent(event)
  286. }
  287. dom1.addEventListener('mouseout',stop)
  288. dom1.addEventListener('mouseover',stop)
  289. }
  290. laserSyncView(app,data){
  291. app.viewer.mainViewport.view.position.copy(data.position)
  292. app.viewer.mainViewport.view.lookAt(data.target)
  293. }
  294. receive(data, customer){
  295. if(!this.loaded){
  296. return this.firstData = data
  297. }
  298. /* if(this.isMaster){
  299. return //正在操作当前,不接收
  300. } */
  301. let position = new THREE.Vector3, target = new THREE.Vector3
  302. if(data.position){
  303. position = new THREE.Vector3().copy(data.position)
  304. }
  305. if(!data.target){
  306. if(data.quaternion){
  307. /* if(this.needConvertAxis){
  308. data.quaternion = math.convertQuaternion.YupToZup(data.quaternion)
  309. } */
  310. let dir = new THREE.Vector3(0, 0, -1).applyQuaternion(data.quaternion)
  311. //dir.applyQuaternion(this.diffQuaternion)/////!
  312. target.copy(position).add(dir)
  313. }
  314. }else{
  315. if(this.needConvertAxis){
  316. target = math.convertVector.YupToZup(target)
  317. }else{
  318. target.copy(data.target)
  319. }
  320. }
  321. if(this.needConvertAxis){
  322. position = math.convertVector.YupToZup(position)
  323. target = math.convertVector.YupToZup(target)
  324. }
  325. position.applyMatrix4(this.convertMatrix)
  326. target.applyMatrix4(this.convertMatrix)
  327. if(customer && customer.sceneType == 'laser'){
  328. this.laserSyncView(customer, {position,target})
  329. }else{
  330. let msg = {
  331. position,
  332. target,
  333. up: new THREE.Vector3(0,0,1),
  334. //前三个缺一不可
  335. fov: data.fov , //fov 用setCameraStatus 无效
  336. }
  337. bimViewer.setCameraStatus(msg)
  338. this.lastCamStatus = msg //记录下来,防止反向传输
  339. let camera = bimViewer.getViewer().camera
  340. if(camera.fov != data.fov){
  341. camera.fov = data.fov
  342. camera.updateProjectionMatrix()
  343. }
  344. //fov, near, far
  345. /* aspect: 0.7879440258342304
  346. coordinateSystem: "world"
  347. far: 11485.989363357028
  348. fov: 45
  349. name: "persp"
  350. near: 1.1852000000072447
  351. position: {x: -1130.0432094639486, y: -6058.569138159733, z: 2265.9284566100446}
  352. target: {x: 310.3968263091223, y: -66.0595010237127, z: 1477.7045866099475}
  353. up: {x: 0, y: 1.534753124827774e-13, z: 1}
  354. version: 1
  355. zoom: 0 */
  356. }
  357. }
  358. send(info){
  359. let camera = this.bimViewer.getViewer().camera
  360. let data = {
  361. position : new THREE.Vector3().copy(info.position).applyMatrix4(this.convertMatrixInvert),
  362. //quaternion : camera.quaternion.clone().applyMatrix4(this.convertMatrix),
  363. target : new THREE.Vector3().copy(info.target).applyMatrix4(this.convertMatrixInvert),
  364. }
  365. if(this.needConvertAxis){
  366. data.position = math.convertVector.ZupToYup(data.position)
  367. data.target = math.convertVector.ZupToYup(data.target)
  368. }
  369. /* this.dispatchEvent({
  370. type: 'sendCameraData',
  371. data
  372. }) */
  373. this.laserSyncView(this.sourceApp, data) //左侧只有laser点云模式才能接收到
  374. }
  375. computeAveDiffLon() {
  376. //获取两个场景的lon偏差值
  377. //需要点的个数>1, 且两个场景点一一对应,位置接近且顺序一致
  378. let diffLonAve = 0, length,
  379. diffLons = [],
  380. panoPos1, panoPos2
  381. if(this.sourceApp.sceneType == 'laser'){
  382. panoPos1 = this.sourceApp.viewer.images360.panos.map(e=>{
  383. return e.position
  384. })
  385. panoPos2 = this.targetApp.viewer.images360.panos.map(e=>{
  386. return e.position
  387. })
  388. }else{
  389. panoPos1 = this.sourceApp.app.core.get('Player').model.panos.list.map(e=>{
  390. return e.position
  391. })
  392. panoPos2 = this.targetApp.app.core.get('Player').model.panos.list.map(e=>{
  393. return e.position
  394. })
  395. }
  396. length = panoPos1.length
  397. //挑选连续的两个点为向量来计算,如有123个漫游点,则选取12 23 31作为向量
  398. let index = 0
  399. while (index < length) {
  400. let pos11 = new THREE.Vector3().copy(panoPos1[index])
  401. let pos12 = new THREE.Vector3().copy(panoPos1[(index + 1) % length])
  402. let pos21 = new THREE.Vector3().copy(panoPos2[index])
  403. let pos22 = new THREE.Vector3().copy(panoPos2[(index + 1) % length])
  404. let vec1 = new THREE.Vector3().subVectors(pos11, pos12).setY(0)
  405. let vec2 = new THREE.Vector3().subVectors(pos21, pos22).setY(0)
  406. let diffLon = math.getAngle(vec1, vec2, 'z')
  407. diffLons.push(diffLon)
  408. diffLonAve += diffLon
  409. index++
  410. }
  411. console.log('diffLons', diffLons)
  412. diffLonAve /= length
  413. console.log('diffLonAve', diffLonAve)
  414. return /* KanKan.THREE.MathUtils.radToDeg( */ diffLonAve /* ) */
  415. }
  416. computeShift(sourcePano, targetPano) { //获取两个场景的旋转和位移偏差值
  417. //需要点的个数>1, 且两个场景点一一对应,位置接近且顺序一致
  418. //pick两个点来计算
  419. let diffLonAve = 0, panoPos1, panoPos2,
  420. diffLons = []
  421. /* let panoPos1 = [//4dkk SS-t-lc5OWhZPaC
  422. new THREE.Vector3( 2.1985836955069153, -0.7253820937020852, -0.01348725),
  423. new THREE.Vector3( 4.07288387528266, 1.8350265362839944, 0.04772775)
  424. ] */
  425. if(this.sourceApp.sceneType == this.targetApp.sceneType){
  426. var angle = this.diffLon;
  427. panoPos1 = this.sourceApp.viewer.images360.panos.map(e=>{
  428. return e.position
  429. })
  430. panoPos2 = this.targetApp.viewer.images360.panos.map(e=>{
  431. return e.position
  432. })
  433. }else{
  434. panoPos1 = sourcePano.map(e=>e.position)
  435. panoPos2 = targetPano.map(e=>e.position)
  436. if(this.needConvertAxis){
  437. panoPos1 = panoPos1.map(e=>math.convertVector.YupToZup(e))
  438. }
  439. var vec1 = new THREE.Vector3().subVectors(panoPos1[0], panoPos1[1]) //旧的向量
  440. var vec2 = new THREE.Vector3().subVectors(panoPos2[0], panoPos2[1])//新的向量
  441. var angle = math.getAngle(vec1, vec2, 'z')
  442. }
  443. //var scale = vec2.length()/vec1.length()
  444. //var scaleMatrix = new THREE.Matrix4().makeScale(scale,scale,scale) //默认为1, 但由于坐标暂时是自己采集的,所以结果会是第一个点附近比较正确,越远偏差越大
  445. var matrix = new THREE.Matrix4().setPosition(panoPos1[0].clone().negate())//先以点0为基准平移到000
  446. //matrix.premultiply(scaleMatrix)//再缩放
  447. var rotateMatrix = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0,0,1), angle );
  448. matrix.premultiply(rotateMatrix)//和旋转
  449. var moveBackMatrix = new THREE.Matrix4().setPosition(panoPos2[0])
  450. matrix.premultiply(moveBackMatrix)//再移动到realPosition的点0处
  451. this.convertMatrix = matrix
  452. this.convertMatrixInvert = matrix.clone().invert()
  453. /* var pos = panoPos1.map(e=>{
  454. return e.clone().applyMatrix4(matrix)
  455. })
  456. console.log(pos) */
  457. //挑选连续的两个点为向量来计算,如有123个漫游点,则选取12 23 31作为向量
  458. /* let index = 0
  459. while (index < length) {
  460. let pos11 = new THREE.Vector3().copy(panoPos1[index])
  461. let pos12 = new THREE.Vector3().copy(panoPos1[(index + 1) % length])
  462. let pos21 = new THREE.Vector3().copy(panoPos2[index])
  463. let pos22 = new THREE.Vector3().copy(panoPos2[(index + 1) % length])
  464. let vec1 = new THREE.Vector3().subVectors(pos11, pos12).setZ(0)
  465. let vec2 = new THREE.Vector3().subVectors(pos21, pos22).setZ(0)
  466. let diffLon = math.getAngle(vec1, vec2, 'z')
  467. diffLons.push(diffLon)
  468. diffLonAve += diffLon
  469. index++
  470. }
  471. console.log('diffLons', diffLons)
  472. diffLonAve /= length
  473. console.log('diffLonAve', diffLonAve)
  474. this.diffQuaternion = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), diffLonAve)
  475. this.diffQuaternionInvert = this.diffQuaternion.clone().invert() */
  476. }
  477. lockCamera(locked){//禁止操作改变相机
  478. this.locked = locked
  479. this.updateCtrlEnable()
  480. }
  481. setPanoMode(state){
  482. this.isPanoMode = state
  483. this.updateCtrlEnable()
  484. }
  485. updateCtrlEnable(){
  486. this.bimViewer.camera3D.enableRotate(this.locked ? false : true)
  487. this.bimViewer.enableShortcutKey((this.locked || this.isPanoMode) ? false : true) //键盘移动
  488. }
  489. /* applyDiff(app) {
  490. //sourcePlayer -> targetPlayer
  491. if (!this.player1 || !this.player2 || this.targetApp.config.num == this.sourceApp.config.num) return //场景码相同的话返回
  492. if (this.player1.mode != this.player2.mode) return
  493. let player1, player2, quaternion //player1为要改变的, player2是参照
  494. if (app == this.sourceApp) {
  495. player1 = this.player1
  496. player2 = this.player2
  497. quaternion = this.diffQuaternion
  498. } else {
  499. player1 = this.player2
  500. player2 = this.player1
  501. quaternion = this.diffQuaternionInvert
  502. }
  503. let control1 = player1.cameraControls.activeControl
  504. let control2 = player2.cameraControls.activeControl
  505. //if(!control1 || !control2)return
  506. player1.quaternion.copy(player2.quaternion).premultiply(quaternion)
  507. if (player1.mode == 'panorama') {
  508. //平移
  509. let dir = new THREE.Vector3().subVectors(control2.target, player2.position)
  510. dir.applyQuaternion(quaternion)
  511. let target1 = new THREE.Vector3().addVectors(player1.position, dir)
  512. control1.lookAt(target1)
  513. control1.target.copy(target1)
  514. } else if (control2) {
  515. //修改target,保证target在panos之间的相对位置一样
  516. //console.log('target', control2.target.clone())
  517. //console.log('position', control2.target.clone())
  518. let vec = new THREE.Vector3().subVectors(control2.target, player2.model.panos.list[0].position)
  519. vec.applyQuaternion(quaternion)
  520. control1.target.addVectors(player1.model.panos.list[0].position, vec)
  521. player1.target.copy(control1.target)
  522. //修改position,保证方向一样
  523. let dir = new THREE.Vector3().subVectors(control2.camera.position , control2.target)
  524. dir.applyQuaternion(quaternion)
  525. player1.position = new THREE.Vector3().addVectors(control1.target, dir)
  526. control1.camera.position.copy(player1.position)
  527. }
  528. control1.camera.quaternion.copy(player1.quaternion)
  529. } */
  530. /* applyDiff(app, data) {
  531. //sourcePlayer -> targetPlayer
  532. let quaternion
  533. if (data.quaternion) {
  534. quaternion = new THREE.Quaternion().copy(data.quaternion)
  535. data.quaternion = quaternion
  536. } else if (data.info && data.info.quaternion) {
  537. //飞出
  538. quaternion = new THREE.Quaternion(data.info.quaternion._x, data.info.quaternion._y, data.info.quaternion._z, data.info.quaternion._w)
  539. data.info.quaternion = quaternion
  540. //let radius = data.info.position.distanceTo(data.info.target)
  541. }
  542. if (!quaternion) return
  543. if (app == this.sourceApp) {
  544. quaternion.premultiply(this.diffQuaternionInvert)
  545. } else {
  546. quaternion.premultiply(this.diffQuaternion)
  547. }
  548. if (data.info && data.info.quaternion) {
  549. //飞出
  550. let dir = new THREE.Vector3().subVectors(data.info.position, data.info.target)
  551. dir.applyQuaternion(app == this.sourceApp ? this.diffQuaternionInvert : this.diffQuaternion)
  552. data.info.position = new THREE.Vector3().addVectors(data.info.target, dir)
  553. }
  554. //先不管飞出后的位置平移
  555. //位置参照第一个漫游点。保持相机相对第一个漫游点的位移和
  556. } */
  557. }
  558. /*
  559. note:
  560. 旋转只能通过target设置, 不能直接改camera.quaternion
  561. 当且仅当发送方相机属性变化后才传递过来,就不在这里判断是否变化了。
  562. (所以只需要实时检测相机是否改变, hasChanged后发送)
  563. */