ConvertViews.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. import math from './math.js'
  2. export default class ConvertViews extends THREE.EventDispatcher{
  3. constructor() {
  4. super()
  5. this.sourceApp = null
  6. this.targetApp = null
  7. }
  8. clear(o={}){
  9. this.loaded = false;
  10. this.sourceApp = null;
  11. if(!o.dontClearTarget){
  12. this.targetApp = null
  13. }
  14. }
  15. init(sourceApp, targetApp, sourceDom, sceneType, cameraData, sourcePano) {
  16. //if (!this.player1.model.panos.list.length || !this.player2.model.panos.list.length) return
  17. if(this.loaded || !targetApp ) return
  18. let needBindEvent = !this.targetApp // 若targetApp存在表明targetApp的dom未换掉,事件还存在
  19. this.sourceApp = sourceApp
  20. this.targetApp = targetApp
  21. this.sourceDom = sourceDom
  22. let viewer = this.viewer = targetApp.viewer
  23. this.needConvertAxis = sceneType == '4dkk'
  24. this.lastCamStatus = viewer.getCameraStatus()
  25. this.computeAveDiffLon(sourcePano)
  26. viewer.setNavigationMode(targetApp.Glodon.Bimface.Viewer.NavigationMode3D.Walk)
  27. viewer.setFlySpeedRate(5)
  28. viewer.getViewer().setTransitionAnimationState(false) //setCameraStatus瞬间变化相机
  29. viewer.addEventListener('Rendered', (e)=>{
  30. let info = viewer.getCameraStatus()
  31. let poseChanged = !math.closeTo(this.lastCamStatus.position, info.position)
  32. || !math.closeTo(this.lastCamStatus.target, info.target)
  33. || !math.closeTo(this.lastCamStatus.fov, info.fov)
  34. if(poseChanged){
  35. if(sourceApp.canChangePos()){
  36. this.send(info)
  37. this.lastCamStatus = info
  38. }
  39. }
  40. })
  41. /* viewer.addEventListener(targetApp.Glodon.Bimface.Viewer.Viewer3DEvent.ViewAdded,
  42. ()=>{
  43. this.loaded = true
  44. if(this.firstData){
  45. this.receive(this.firstData)
  46. }
  47. }
  48. ) */
  49. this.loaded = true
  50. this.receive(cameraData)
  51. needBindEvent && this.bindCamEvent()
  52. }
  53. bindCamEvent(){//传递到另一边的dom
  54. this.lockCamera(true)
  55. let getEvent = (type, e)=>{
  56. return new MouseEvent(type, {
  57. bubbles: false,//?
  58. cancelable: true,
  59. view: this.sourceApp,
  60. clientX: e.clientX, clientY: e.clientY,
  61. button: e.button, buttons: e.buttons, which: e.which,
  62. altKey: e.altKey, ctrlKey: e.ctrlKey, shiftKey:e.shiftKey, metaKey: e.metaKey,
  63. detail:e.detail,
  64. //target : dom2
  65. });
  66. }
  67. let dom1 = this.viewer.getDomElement()
  68. dom1.addEventListener('mousedown',(e)=>{
  69. let event = getEvent('mousedown', e)
  70. this.sourceDom.dispatchEvent(event)
  71. })
  72. dom1.addEventListener('mousemove',(e)=>{
  73. let event = getEvent('mousemove', e)
  74. this.sourceDom.dispatchEvent(event)
  75. })
  76. dom1.addEventListener('mouseup',(e)=>{
  77. let event = getEvent('mouseup', e)
  78. this.sourceApp.dispatchEvent(event) //mouseup 在laser中加在window上的
  79. })
  80. dom1.addEventListener('mousewheel',(e)=>{
  81. let event = getEvent('mousewheel', e)
  82. event.wheelDelta = e.wheelDelta //wheelDelta没法在getEvent参数中赋值
  83. this.sourceDom.dispatchEvent(event)
  84. })
  85. let stop = (e)=>{ //drag到另一边时停止旋转, 防止转到另一边
  86. let event = getEvent('mouseup', e)
  87. this.sourceApp.dispatchEvent(event)
  88. }
  89. dom1.addEventListener('mouseout',stop)
  90. dom1.addEventListener('mouseover',stop)
  91. }
  92. receive(data){
  93. if(!this.loaded){
  94. return this.firstData = data
  95. }
  96. /* if(this.isMaster){
  97. return //正在操作当前,不接收
  98. } */
  99. let position = new THREE.Vector3, target = new THREE.Vector3
  100. let currStatus = this.viewer.getCameraStatus()
  101. if(data.position){
  102. position = new THREE.Vector3().copy(data.position)
  103. }
  104. if(!data.target){
  105. if(data.quaternion){
  106. /* if(this.needConvertAxis){
  107. data.quaternion = math.convertQuaternion.YupToZup(data.quaternion)
  108. } */
  109. let dir = new THREE.Vector3(0, 0, -1).applyQuaternion(data.quaternion)
  110. //dir.applyQuaternion(this.diffQuaternion)/////!
  111. target.copy(position).add(dir)
  112. }
  113. }else{
  114. if(this.needConvertAxis){
  115. target = math.convertVector.YupToZup(target)
  116. }else{
  117. target.copy(data.target)
  118. }
  119. }
  120. if(this.needConvertAxis){
  121. position = math.convertVector.YupToZup(position)
  122. target = math.convertVector.YupToZup(target)
  123. }
  124. position.applyMatrix4(this.convertMatrix)
  125. target.applyMatrix4(this.convertMatrix)
  126. let msg = {
  127. position,
  128. target,
  129. up: new THREE.Vector3(0,0,1),
  130. //前三个缺一不可
  131. fov: data.fov , //fov 用setCameraStatus 无效
  132. }
  133. this.viewer.setCameraStatus(msg)
  134. this.lastCamStatus = msg //记录下来,防止反向传输
  135. let camera = this.viewer.getViewer().camera
  136. if(camera.fov != data.fov){
  137. camera.fov = data.fov
  138. camera.updateProjectionMatrix()
  139. }
  140. //fov, near, far
  141. /* aspect: 0.7879440258342304
  142. coordinateSystem: "world"
  143. far: 11485.989363357028
  144. fov: 45
  145. name: "persp"
  146. near: 1.1852000000072447
  147. position: {x: -1130.0432094639486, y: -6058.569138159733, z: 2265.9284566100446}
  148. target: {x: 310.3968263091223, y: -66.0595010237127, z: 1477.7045866099475}
  149. up: {x: 0, y: 1.534753124827774e-13, z: 1}
  150. version: 1
  151. zoom: 0 */
  152. }
  153. send(info){
  154. let camera = this.viewer.getViewer().camera
  155. let data = {
  156. position : new THREE.Vector3().copy(info.position).applyMatrix4(this.convertMatrixInvert),
  157. //quaternion : camera.quaternion.clone().applyMatrix4(this.convertMatrix),
  158. target : new THREE.Vector3().copy(info.target).applyMatrix4(this.convertMatrixInvert),
  159. }
  160. if(this.needConvertAxis){
  161. data.position = math.convertVector.ZupToYup(data.position)
  162. data.target = math.convertVector.ZupToYup(data.target)
  163. }
  164. this.dispatchEvent({
  165. type: 'sendCameraData',
  166. data
  167. })
  168. }
  169. computeAveDiffLon(sourcePano) {
  170. //获取两个场景的lon偏差值
  171. //需要点的个数>1, 且两个场景点一一对应,位置接近且顺序一致
  172. //pick两个点来计算
  173. let diffLonAve = 0,
  174. diffLons = []
  175. /* let panoPos1 = [//4dkk SS-t-lc5OWhZPaC
  176. new THREE.Vector3( 2.1985836955069153, -0.7253820937020852, -0.01348725),
  177. new THREE.Vector3( 4.07288387528266, 1.8350265362839944, 0.04772775)
  178. ] */
  179. let panoPos1 = sourcePano
  180. let panoPos2 = [
  181. new THREE.Vector3( -5.313605730801787, -4.889868407960505, 1.237447893355817),
  182. new THREE.Vector3( -5.337403524084278, -2.5012228235167737, 1.2808838933558175)
  183. ]
  184. let length = panoPos1.length
  185. if(this.needConvertAxis){
  186. panoPos1 = panoPos1.map(e=>math.convertVector.YupToZup(e))
  187. }
  188. var vec1 = new THREE.Vector3().subVectors(panoPos1[0], panoPos1[1]) //旧的向量
  189. var vec2 = new THREE.Vector3().subVectors(panoPos2[0], panoPos2[1])//新的向量
  190. var angle = math.getAngle(vec1, vec2, 'z')
  191. //var scale = vec2.length()/vec1.length()
  192. //var scaleMatrix = new THREE.Matrix4().makeScale(scale,scale,scale) //默认为1, 但由于坐标暂时是自己采集的,所以结果会是第一个点附近比较正确,越远偏差越大
  193. var matrix = new THREE.Matrix4().setPosition(panoPos1[0].clone().negate())//先以点0为基准平移到000
  194. //matrix.premultiply(scaleMatrix)//再缩放
  195. var rotateMatrix = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0,0,1), angle );
  196. matrix.premultiply(rotateMatrix)//和旋转
  197. var moveBackMatrix = new THREE.Matrix4().setPosition(panoPos2[0])
  198. matrix.premultiply(moveBackMatrix)//再移动到realPosition的点0处
  199. this.convertMatrix = matrix
  200. this.convertMatrixInvert = matrix.clone().invert()
  201. /* var pos = panoPos1.map(e=>{
  202. return e.clone().applyMatrix4(matrix)
  203. })
  204. console.log(pos) */
  205. //挑选连续的两个点为向量来计算,如有123个漫游点,则选取12 23 31作为向量
  206. /* let index = 0
  207. while (index < length) {
  208. let pos11 = new THREE.Vector3().copy(panoPos1[index])
  209. let pos12 = new THREE.Vector3().copy(panoPos1[(index + 1) % length])
  210. let pos21 = new THREE.Vector3().copy(panoPos2[index])
  211. let pos22 = new THREE.Vector3().copy(panoPos2[(index + 1) % length])
  212. let vec1 = new THREE.Vector3().subVectors(pos11, pos12).setZ(0)
  213. let vec2 = new THREE.Vector3().subVectors(pos21, pos22).setZ(0)
  214. let diffLon = math.getAngle(vec1, vec2, 'z')
  215. diffLons.push(diffLon)
  216. diffLonAve += diffLon
  217. index++
  218. }
  219. console.log('diffLons', diffLons)
  220. diffLonAve /= length
  221. console.log('diffLonAve', diffLonAve)
  222. this.diffQuaternion = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), diffLonAve)
  223. this.diffQuaternionInvert = this.diffQuaternion.clone().invert() */
  224. }
  225. lockCamera(locked){
  226. this.locked = locked
  227. this.updateCtrlEnable()
  228. }
  229. setPanoMode(state){
  230. this.isPanoMode = state
  231. this.updateCtrlEnable()
  232. }
  233. updateCtrlEnable(){
  234. this.viewer.camera3D.enableRotate(this.locked ? false : true)
  235. this.viewer.enableShortcutKey((this.locked || this.isPanoMode) ? false : true) //键盘移动
  236. }
  237. /* applyDiff(app) {
  238. //sourcePlayer -> targetPlayer
  239. if (!this.player1 || !this.player2 || this.targetApp.config.num == this.sourceApp.config.num) return //场景码相同的话返回
  240. if (this.player1.mode != this.player2.mode) return
  241. let player1, player2, quaternion //player1为要改变的, player2是参照
  242. if (app == this.sourceApp) {
  243. player1 = this.player1
  244. player2 = this.player2
  245. quaternion = this.diffQuaternion
  246. } else {
  247. player1 = this.player2
  248. player2 = this.player1
  249. quaternion = this.diffQuaternionInvert
  250. }
  251. let control1 = player1.cameraControls.activeControl
  252. let control2 = player2.cameraControls.activeControl
  253. //if(!control1 || !control2)return
  254. player1.quaternion.copy(player2.quaternion).premultiply(quaternion)
  255. if (player1.mode == 'panorama') {
  256. //平移
  257. let dir = new this.KanKan.THREE.Vector3().subVectors(control2.target, player2.position)
  258. dir.applyQuaternion(quaternion)
  259. let target1 = new this.KanKan.THREE.Vector3().addVectors(player1.position, dir)
  260. control1.lookAt(target1)
  261. control1.target.copy(target1)
  262. } else if (control2) {
  263. //修改target,保证target在panos之间的相对位置一样
  264. //console.log('target', control2.target.clone())
  265. //console.log('position', control2.target.clone())
  266. let vec = new this.KanKan.THREE.Vector3().subVectors(control2.target, player2.model.panos.list[0].position)
  267. vec.applyQuaternion(quaternion)
  268. control1.target.addVectors(player1.model.panos.list[0].position, vec)
  269. player1.target.copy(control1.target)
  270. //修改position,保证方向一样
  271. let dir = new this.KanKan.THREE.Vector3().subVectors(control2.camera.position , control2.target)
  272. dir.applyQuaternion(quaternion)
  273. player1.position = new this.KanKan.THREE.Vector3().addVectors(control1.target, dir)
  274. control1.camera.position.copy(player1.position)
  275. }
  276. control1.camera.quaternion.copy(player1.quaternion)
  277. } */
  278. /* applyDiff(app, data) {
  279. //sourcePlayer -> targetPlayer
  280. let quaternion
  281. if (data.quaternion) {
  282. quaternion = new this.KanKan.THREE.Quaternion().copy(data.quaternion)
  283. data.quaternion = quaternion
  284. } else if (data.info && data.info.quaternion) {
  285. //飞出
  286. quaternion = new this.KanKan.THREE.Quaternion(data.info.quaternion._x, data.info.quaternion._y, data.info.quaternion._z, data.info.quaternion._w)
  287. data.info.quaternion = quaternion
  288. //let radius = data.info.position.distanceTo(data.info.target)
  289. }
  290. if (!quaternion) return
  291. if (app == this.sourceApp) {
  292. quaternion.premultiply(this.diffQuaternionInvert)
  293. } else {
  294. quaternion.premultiply(this.diffQuaternion)
  295. }
  296. if (data.info && data.info.quaternion) {
  297. //飞出
  298. let dir = new this.KanKan.THREE.Vector3().subVectors(data.info.position, data.info.target)
  299. dir.applyQuaternion(app == this.sourceApp ? this.diffQuaternionInvert : this.diffQuaternion)
  300. data.info.position = new this.KanKan.THREE.Vector3().addVectors(data.info.target, dir)
  301. }
  302. //先不管飞出后的位置平移
  303. //位置参照第一个漫游点。保持相机相对第一个漫游点的位移和
  304. } */
  305. }