move.service.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. import { Injectable } from '@nestjs/common';
  2. import { CacheService } from 'src/cache/cache.service';
  3. import { RotateService } from 'src/rotate/rotate.service';
  4. // import { SceneService } from 'src/scene/scene.service';
  5. @Injectable()
  6. export class MoveService {
  7. constructor(
  8. private cacheService: CacheService,
  9. private rotateService: RotateService,
  10. ) {}
  11. private Actions = {
  12. Clicking: 1,
  13. Rotation: 1014,
  14. Joystick: 15,
  15. };
  16. public users = this.rotateService.users;
  17. private reply = {
  18. traceIds: [],
  19. vehicle: null,
  20. mediaSrc: null,
  21. newUserStates: [
  22. {
  23. userId: 'dcff36ae4fc1d',
  24. playerState: {
  25. roomTypeId: '',
  26. person: 0,
  27. avatarId: '',
  28. skinId: '',
  29. roomId: '',
  30. isHost: false,
  31. isFollowHost: false,
  32. skinDataVersion: '',
  33. avatarComponents: '',
  34. nickName: '',
  35. movingMode: 0,
  36. attitude: '',
  37. areaName: '',
  38. pathName: '',
  39. pathId: '',
  40. avatarSize: 1,
  41. extra: '',
  42. prioritySync: false,
  43. player: {
  44. position: { x: -700, y: 0, z: 0 },
  45. angle: {
  46. pitch: 0,
  47. yaw: 0,
  48. roll: 0,
  49. },
  50. },
  51. camera: {
  52. position: { x: -1145, y: 0, z: 160 },
  53. angle: {
  54. pitch: 0,
  55. yaw: 0,
  56. roll: 0,
  57. },
  58. },
  59. cameraCenter: { x: -700, y: 0, z: 0 },
  60. },
  61. renderInfo: {
  62. renderType: 0,
  63. videoFrame: null,
  64. cameraStateType: 3,
  65. isMoving: 1,
  66. needIfr: 0,
  67. isVideo: 0,
  68. stillFrame: 0,
  69. isRotating: 0,
  70. isFollowing: 0,
  71. clientPanoTitlesBitmap: [],
  72. clientPanoTreceId: '',
  73. prefetchVideoId: '',
  74. noMedia: false,
  75. },
  76. event: null,
  77. relation: 1,
  78. },
  79. ],
  80. actionResponses: [
  81. {
  82. actionType: 1,
  83. pointType: 100,
  84. extra: '',
  85. traceId: '',
  86. packetId: '',
  87. nps: [],
  88. peopleNum: 0,
  89. zoneId: '',
  90. echoMsg: '',
  91. reserveDetail: null,
  92. userWithAvatarList: [],
  93. newUserStates: [],
  94. code: 0,
  95. msg: '',
  96. },
  97. ],
  98. getStateType: 0,
  99. code: 0,
  100. msg: 'OK',
  101. };
  102. init(app_id, userId) {
  103. const user = {
  104. appId: null,
  105. userId: null,
  106. breakPointId: null,
  107. roomId: null,
  108. player: {
  109. position: { x: -700, y: 0, z: 0 },
  110. angle: {
  111. pitch: 0,
  112. yaw: 0,
  113. roll: 0,
  114. },
  115. },
  116. camera: {
  117. position: { x: -1145, y: 0, z: 160 },
  118. angle: {
  119. pitch: 0,
  120. yaw: 0,
  121. roll: 0,
  122. },
  123. },
  124. rotateInfo: {
  125. frameIndex: 0,
  126. horizontal_move: 0,
  127. mediaSrc: null,
  128. },
  129. moveInfo: {},
  130. // traceIds: [],
  131. // actionResponses:[]
  132. };
  133. user.appId = app_id;
  134. user.userId = userId;
  135. user.breakPointId = 100;
  136. this.users[userId] = user;
  137. }
  138. async move(pathArray, actionRequest) {
  139. try {
  140. const userId = actionRequest['user_id'];
  141. const traceId = actionRequest['trace_id'];
  142. const actionType = actionRequest['action_type'];
  143. const user = this.users[userId];
  144. const appId = user.appId;
  145. const path = pathArray || [100, 101, 102]; //需要计算路径
  146. const angle = user.camera.angle.yaw % 44; //纠正需要
  147. console.log('矫正前-相机:' + user.camera.angle.yaw);
  148. const replys = {};
  149. const traceIds = [];
  150. traceIds.push(traceId);
  151. //纠正,旋转传到缓存里
  152. const checkReplys = [];
  153. // console.log('矫正: ' + angle + ' 度');
  154. for (let i = 0; i < angle; ++i) {
  155. // console.warn('矫正一次:' + i);
  156. const reply = await this.rotateService.rotateForAngle(userId, 1);
  157. // console.warn(
  158. // '矫正:' + reply.newUserStates[0].playerState.camera.angle.yaw,
  159. // );
  160. reply.traceIds = [];
  161. reply.traceIds.push(traceId);
  162. const actionResponse = this.rotateService.createActionResponse(
  163. actionType,
  164. traceId,
  165. );
  166. reply.actionResponses = [];
  167. reply.actionResponses.push(actionResponse);
  168. checkReplys.push(reply);
  169. }
  170. replys['P' + user.breakPointId + 'T' + user.breakPointId] = checkReplys;
  171. //replys.push(checkReplys);
  172. //过渡传到缓存里
  173. this.reply.traceIds = traceIds;
  174. this.reply['newUserStates'][0].userId = userId;
  175. this.reply['actionResponses'][0].traceId = traceId;
  176. console.log('矫正后-相机:' + user.camera.angle.yaw);
  177. const index = Math.round(user.camera.angle.yaw / 44); //过渡需要
  178. for (let i = 0; i < path.length - 1; ++i) {
  179. let pathReplys = [];
  180. const start_break_point_id = path[i];
  181. const end_break_point_id = path[i + 1];
  182. //读redis里的数据,按照frame_index的大小排序
  183. const key =
  184. 'moveframe:app_id:' +
  185. appId +
  186. ':start_break_point_id:' +
  187. start_break_point_id +
  188. ':end_break_point_id:' +
  189. end_break_point_id +
  190. ':angle:' +
  191. index;
  192. const moveFramesRes = await this.cacheService.get(key);
  193. if (moveFramesRes == null) {
  194. return replys;
  195. }
  196. const moveFrames = JSON.parse(moveFramesRes);
  197. //读redis里的数据
  198. const startBreakPointRes = await this.cacheService.get(
  199. 'breakpoints:app_id:' +
  200. appId +
  201. ':break_point_id:' +
  202. start_break_point_id,
  203. );
  204. const startBreakPoint = JSON.parse(startBreakPointRes);
  205. const endBreakPointRes = await this.cacheService.get(
  206. 'breakpoints:app_id:' +
  207. appId +
  208. ':break_point_id:' +
  209. end_break_point_id,
  210. );
  211. const endBreakPoint = JSON.parse(endBreakPointRes);
  212. pathReplys = this.createCacheReplys(
  213. moveFrames,
  214. traceId,
  215. userId,
  216. start_break_point_id,
  217. startBreakPoint.position,
  218. endBreakPoint.position,
  219. );
  220. if (i == path.length - 2) {
  221. pathReplys[pathReplys.length - 1][
  222. 'newUserStates'
  223. ][0].renderInfo.isMoving = 0;
  224. }
  225. //replys.push(pathReplys);
  226. replys['P' + start_break_point_id + 'T' + end_break_point_id] =
  227. pathReplys;
  228. }
  229. return replys;
  230. } catch (error) {
  231. console.log('MoveService', error);
  232. }
  233. }
  234. createCacheReplys(
  235. moveFrames,
  236. traceId,
  237. userId,
  238. breakPointId,
  239. startPosition,
  240. endPosition,
  241. ) {
  242. const replys = [];
  243. const angle =
  244. -1 *
  245. this.getAngle(
  246. startPosition,
  247. {
  248. x: startPosition.x + 1,
  249. y: startPosition.y,
  250. },
  251. endPosition,
  252. );
  253. for (let i = 1; i < moveFrames.length; i += 5) {
  254. const moveFrame = moveFrames[i];
  255. const reply = JSON.parse(JSON.stringify(this.reply));
  256. reply.traceIds.push(traceId);
  257. reply['newUserStates'][0].userId = userId;
  258. reply['newUserStates'][0].playerState.player.position = {
  259. x:
  260. startPosition.x +
  261. ((endPosition.x - startPosition.x) / moveFrames.length) * i,
  262. y:
  263. startPosition.y +
  264. ((endPosition.y - startPosition.y) / moveFrames.length) * i,
  265. z:
  266. startPosition.z +
  267. ((endPosition.z - startPosition.z) / moveFrames.length) * i,
  268. };
  269. reply['newUserStates'][0].playerState.player.angle.yaw = angle;
  270. reply['newUserStates'][0].playerState.camera.position =
  271. moveFrame.camera_position;
  272. reply['newUserStates'][0].playerState.camera.angle =
  273. moveFrame.camera_angle;
  274. reply['newUserStates'][0].playerState.cameraCenter =
  275. reply['newUserStates'][0].playerState.player.position;
  276. reply['actionResponses'][0].traceId = traceId;
  277. reply.mediaSrc =
  278. '/' +
  279. '0000000001' +
  280. '/' +
  281. breakPointId +
  282. '/' +
  283. moveFrame.file_name.substring(0, moveFrame.file_name.indexOf('.')) +
  284. '/' +
  285. moveFrame.file_name +
  286. '?m=' +
  287. new Date().getTime();
  288. replys.push(reply);
  289. }
  290. return replys;
  291. }
  292. //需要通知user,人物和相机走到哪一个呼吸点位了
  293. updateUser(userId, breakPointId, lastReply) {
  294. const user = this.users[userId];
  295. user.breakPointId = breakPointId;
  296. // debugger;
  297. user.player.position =
  298. lastReply['newUserStates'][0].playerState.player.position;
  299. user.player.angle = lastReply['newUserStates'][0].playerState.player.angle;
  300. user.camera.position =
  301. lastReply['newUserStates'][0].playerState.camera.position;
  302. user.camera.angle = lastReply['newUserStates'][0].playerState.camera.angle;
  303. }
  304. async getBreakPoints(actionRequest) {
  305. const userId = actionRequest['user_id'];
  306. const traceId = actionRequest['trace_id'];
  307. const actionType = actionRequest['action_type'];
  308. const user = this.users[userId];
  309. const appId = user.appId;
  310. const breakPointId = user.breakPointId;
  311. const reply = {
  312. actionType: actionType,
  313. pointType: 100,
  314. extra: '',
  315. traceId: traceId,
  316. packetId: '',
  317. nps: [],
  318. peopleNum: 0,
  319. zoneId: '',
  320. echoMsg: '',
  321. reserveDetail: null,
  322. userWithAvatarList: [],
  323. newUserStates: [],
  324. code: 0,
  325. msg: '',
  326. };
  327. //const breakPoints = await this.cacheService.get('breakpoints:app_id:'+appId+':break_point_id:'+breakPointId);
  328. //获取redis表全部元素,'breakpoints:app_id:'+appId+':break_point_id:'开头的
  329. const keys = await this.cacheService.keys(`breakpoints:app_id:${appId}*`);
  330. for (let i = 0; i < keys.length; ++i) {
  331. const breakPointRes = await this.cacheService.get(keys[i]);
  332. const breakPoint = JSON.parse(breakPointRes);
  333. const position = breakPoint.position;
  334. reply['nps'].push({
  335. position: position,
  336. breakPointId: breakPoint.breakPointId,
  337. });
  338. }
  339. return reply;
  340. }
  341. getAngle(point, point1, point2) {
  342. const x1 = point1.x - point.x;
  343. const y1 = point1.y - point.y;
  344. const x2 = point2.x - point.x;
  345. const y2 = point2.y - point.y;
  346. const dot = x1 * x2 + y1 * y2;
  347. const det = x1 * y2 - y1 * x2;
  348. const angle = (Math.atan2(det, dot) / Math.PI) * 180;
  349. return (angle + 360) % 360;
  350. }
  351. async stop(traceId, userId, movePointIds, cameraAngle, playerAngle) {
  352. const breakPointId = movePointIds.substring(movePointIds.indexOf('-') + 1);
  353. const user = this.users[userId];
  354. user.breakPointId = breakPointId;
  355. const appId = user.appId;
  356. const breakPointRes = await this.cacheService.get(
  357. 'breakpoints:app_id:' + appId + ':break_point_id:' + breakPointId,
  358. );
  359. const breakPoint = JSON.parse(breakPointRes);
  360. user.player.position = breakPoint.position;
  361. user.player.angle = playerAngle;
  362. const rotateKey =
  363. 'rotateframe:app_id:' +
  364. appId +
  365. ':frame_index:' +
  366. cameraAngle.yaw +
  367. ':break_point_id:' +
  368. breakPointId;
  369. const rotateDataRes = await this.cacheService.get(rotateKey);
  370. const rotateData = JSON.parse(rotateDataRes);
  371. user.camera.position = rotateData.cameraPosition;
  372. user.camera.angle = rotateData.cameraAngle;
  373. const reply = JSON.parse(JSON.stringify(this.reply));
  374. reply.traceIds.push(traceId);
  375. reply['newUserStates'][0].userId = userId;
  376. reply['newUserStates'][0].playerState.player.position = breakPoint.position;
  377. reply['newUserStates'][0].playerState.player.angle = playerAngle;
  378. reply['newUserStates'][0].playerState.camera.position =
  379. rotateData.cameraPosition;
  380. reply['newUserStates'][0].playerState.camera.angle = rotateData.cameraAngle;
  381. reply['newUserStates'][0].playerState.cameraCenter = breakPoint.position;
  382. reply['actionResponses'][0].traceId = traceId;
  383. reply.mediaSrc =
  384. '/' +
  385. '0000000001' +
  386. '/' +
  387. breakPointId +
  388. '/' +
  389. rotateData.directory +
  390. '/' +
  391. rotateData.fileName +
  392. '?m=' +
  393. new Date().getTime();
  394. reply['newUserStates'][0].renderInfo.isMoving = 0;
  395. return reply;
  396. }
  397. async joystick(actionRequest) {
  398. try {
  399. const userId = actionRequest['user_id'];
  400. const traceId = actionRequest['trace_id'];
  401. const dir_action = actionRequest['dir_action'];
  402. const actionType = actionRequest['action_type'];
  403. const user = this.users[userId];
  404. const appId = user.appId;
  405. //只是移动人物
  406. if (dir_action.speed_level < 7) {
  407. user.player.angle.yaw = dir_action.move_angle;
  408. this.reply['newUserStates'][0]['userId'] = userId;
  409. this.reply['newUserStates'][0].playerState.player.position =
  410. user.player.position;
  411. this.reply['newUserStates'][0].playerState.player.angle.yaw =
  412. dir_action.move_angle;
  413. this.reply['newUserStates'][0].playerState.camera.position =
  414. user.camera.position;
  415. this.reply['newUserStates'][0].playerState.camera.angle =
  416. user.camera.angle;
  417. this.reply['newUserStates'][0].playerState.cameraCenter =
  418. user.camera.position;
  419. this.reply['actionResponses'][0].traceId = traceId;
  420. return this.reply;
  421. }
  422. //选择过渡
  423. else {
  424. const breakPointId = user.breakPointId;
  425. //先矫正
  426. const breakPointRes = await this.cacheService.get(
  427. 'breakpoints:app_id:' + appId + ':break_point_id:' + breakPointId,
  428. );
  429. if (breakPointRes == null) {
  430. return null;
  431. }
  432. const breakPoint = JSON.parse(breakPointRes);
  433. const contact = breakPoint.contact;
  434. let chooseBreakPointId = null;
  435. let minOffsetAngle = null;
  436. let neighPoint = null;
  437. let angle = 0;
  438. for (let i = 0; i < contact.length; ++i) {
  439. neighPoint = await this.cacheService.get(
  440. 'breakpoints:app_id:' + appId + ':break_point_id:' + contact[i],
  441. ); //通过contact[i],去redis里找
  442. //通过user.player.position;neighPoint.position获得角度
  443. neighPoint = JSON.parse(neighPoint);
  444. angle = this.getAngle(
  445. user.player.position,
  446. { x: user.player.position.x + 1, y: user.player.position.y },
  447. neighPoint.position,
  448. );
  449. if (
  450. Math.abs(angle - dir_action.move_angle) < 45 &&
  451. (minOffsetAngle == null ||
  452. Math.abs(angle - dir_action.move_angle) < minOffsetAngle)
  453. ) {
  454. chooseBreakPointId = contact[i];
  455. minOffsetAngle = Math.abs(angle - dir_action.move_angle);
  456. }
  457. }
  458. if (chooseBreakPointId == null) {
  459. return null;
  460. } else {
  461. //人物矫正
  462. user.player.angle.yaw = angle;
  463. //相机纠正
  464. const replys = [];
  465. const traceIds = [];
  466. traceIds.push(traceId);
  467. const checkReplys = [];
  468. angle = user.camera.angle.yaw % 44; //纠正需要
  469. for (let i = 0; i < angle; ++i) {
  470. const reply = await this.rotateService.rotateForAngle(userId, 1);
  471. reply.traceIds = [];
  472. reply.traceIds.push(traceId);
  473. const actionResponse = this.rotateService.createActionResponse(
  474. actionType,
  475. traceId,
  476. );
  477. reply.actionResponses = [];
  478. reply.actionResponses.push(actionResponse);
  479. checkReplys.push(reply);
  480. }
  481. replys.push(checkReplys);
  482. //过渡
  483. //读redis里的数据,按照frame_index的大小排序
  484. const key =
  485. 'moveframe:app_id:' +
  486. appId +
  487. ':start_break_point_id:' +
  488. breakPointId +
  489. ':end_break_point_id:' +
  490. chooseBreakPointId +
  491. ':angle:' +
  492. (user.camera.angle.yaw % 44);
  493. const moveFramesRes = await this.cacheService.get(key);
  494. if (moveFramesRes == null) {
  495. return replys;
  496. }
  497. const moveFrames = JSON.parse(moveFramesRes);
  498. //读redis里的数据
  499. const startBreakPointRes = await this.cacheService.get(
  500. 'breakpoints:app_id:' + appId + ':break_point_id:' + breakPointId,
  501. );
  502. const startBreakPoint = JSON.parse(startBreakPointRes);
  503. const endBreakPointRes = await this.cacheService.get(
  504. 'breakpoints:app_id:' +
  505. appId +
  506. ':break_point_id:' +
  507. chooseBreakPointId,
  508. );
  509. const endBreakPoint = JSON.parse(endBreakPointRes);
  510. const pathReplys = this.createCacheReplys(
  511. moveFrames,
  512. traceId,
  513. userId,
  514. breakPointId,
  515. startBreakPoint.position,
  516. endBreakPoint.position,
  517. );
  518. replys.push(pathReplys);
  519. return replys;
  520. }
  521. }
  522. } catch (error) {
  523. console.log('MoveService', error);
  524. }
  525. }
  526. }