Player.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. import * as THREE from "three";
  2. import FloorplanControls from "../controls/FloorplanControls.js";
  3. import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
  4. import { TrackballControls } from "three/examples/jsm/controls/TrackballControls.js";
  5. import Line from "../box/object/Line";
  6. import LinePoints from "../box/object/LinePoints.js";
  7. import Marker from "../box/object/marker.js";
  8. import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
  9. const convertScreenToNDC = function (event, domElement) {
  10. let x = (event.offsetX / domElement.clientWidth) * 2 - 1;
  11. let y = -(event.offsetY / domElement.clientHeight) * 2 + 1;
  12. return new THREE.Vector2(x, y);
  13. };
  14. export default class Player {
  15. constructor(scene) {
  16. this.scene = scene;
  17. this.orthCamera = scene.orthCamera;
  18. this.floorplanControls = null;
  19. this.raycaster = null;
  20. this.position = new THREE.Vector3();
  21. this.pointerdown = new THREE.Vector2();
  22. this.pointerup = new THREE.Vector2();
  23. this.pointer = new THREE.Vector2();
  24. this.markPosition = new THREE.Vector3();
  25. this.touchImg = null;
  26. this.activeEdge = null;
  27. this.drawLine = null;
  28. this.startObj = null;
  29. this.marker = null;
  30. this.allowDrawing = false;
  31. this.drawing = false;
  32. this.inited = false;
  33. this.renderLines = [];
  34. this.renderMarkers = [];
  35. this.activeEdges = [];
  36. this.matLine = null;
  37. this.lineColor = 0xe44d54;
  38. // 1是画线,2是标方向
  39. this.mode = 0;
  40. this.init();
  41. }
  42. setMode(mode) {
  43. this.mode = mode;
  44. if (mode === 1 || mode === 2) {
  45. this.reset();
  46. this.setEditMode();
  47. }
  48. if (mode === 0) {
  49. this.setFreeMode();
  50. }
  51. this.scene.emit("mode", this.mode);
  52. }
  53. // removeMarker() {
  54. // if (this.marker) {
  55. // this.scene.scene.remove(this.marker);
  56. // this.marker = null;
  57. // }
  58. // }
  59. setFreeMode() {
  60. this.floorplanControls.enablePan = true;
  61. this.floorplanControls.mouseButtons = {
  62. LEFT: THREE.MOUSE.PAN,
  63. MIDDLE: THREE.MOUSE.DOLLY,
  64. RIGHT: THREE.MOUSE.PAN,
  65. };
  66. this.reset();
  67. }
  68. setEditMode() {
  69. this.floorplanControls.enablePan = true;
  70. this.floorplanControls.mouseButtons = {
  71. LEFT: THREE.MOUSE.ROTATE,
  72. MIDDLE: THREE.MOUSE.DOLLY,
  73. RIGHT: THREE.MOUSE.PAN,
  74. };
  75. }
  76. init = () => {
  77. // //floorplanControls
  78. // this.floorplanControls = new FloorplanControls(
  79. // this.orthCamera,
  80. // this.scene.domElement,
  81. // this
  82. // );
  83. this.floorplanControls = new OrbitControls(
  84. this.orthCamera,
  85. this.scene.domElement
  86. );
  87. this.floorplanControls.enablePan = true;
  88. // this.floorplanControls.target.set(0, 1, 0);
  89. // this.floorplanControls.rotateSpeed = 0.5;
  90. // this.floorplanControls.panSpeed = 0.75
  91. this.floorplanControls.maxDistance = 100;
  92. this.floorplanControls.minDistance = 3.5;
  93. this.floorplanControls.maxZoom = 500;
  94. this.floorplanControls.minZoom = 100;
  95. // this.floorplanControls.mouseButtons = {
  96. // LEFT: THREE.MOUSE.PAN,
  97. // MIDDLE: THREE.MOUSE.DOLLY,
  98. // RIGHT: THREE.MOUSE.PAN
  99. // }
  100. this.setMode(0);
  101. this.floorplanControls.enableRotate = false;
  102. this.raycaster = new THREE.Raycaster();
  103. this.onBindEvent();
  104. this.inited = true;
  105. this.matLine = new LineMaterial({
  106. color: this.lineColor,
  107. linewidth: 3, // in world units with size attenuation, pixels otherwise
  108. dashed: false,
  109. alphaToCoverage: true,
  110. });
  111. this.matLine.resolution = new THREE.Vector2(
  112. this.scene.width,
  113. this.scene.height
  114. );
  115. };
  116. onPointerMove = (e) => {
  117. if (!this.drawing) return;
  118. this.pointermove = convertScreenToNDC(e, this.scene.domElement);
  119. if (this.mode === 1) {
  120. this.raycaster.setFromCamera(this.pointermove, this.orthCamera);
  121. let intersectArr = this.scene.boxManager.imgList;
  122. // if(this.startObj) {
  123. // let i = intersectArr.indexOf(this.startObj)
  124. // intersectArr.splice(i, 1)
  125. // }
  126. const intersects = this.raycaster.intersectObjects(intersectArr, false);
  127. if (intersects[0] && intersects[0].object !== this.startObj) {
  128. this.touchImg = intersects[0];
  129. this.setActiveLine(this.touchImg);
  130. }
  131. }
  132. if (this.mode === 2) {
  133. if (this.marker) {
  134. let pos = new THREE.Vector3(this.pointermove.x, this.pointermove.y, -1);
  135. pos.unproject(this.orthCamera);
  136. pos.y = 5;
  137. // console.log("pos", pos);
  138. this.marker.position.copy(pos);
  139. }
  140. }
  141. };
  142. onPointerDown = (e) => {
  143. console.log("start draw");
  144. this.pointerdown = convertScreenToNDC(e, this.scene.domElement);
  145. if (this.mode === 1) {
  146. this.raycaster.setFromCamera(this.pointerdown, this.orthCamera);
  147. let intersectArr = this.scene.boxManager.imgList;
  148. const intersects = this.raycaster.intersectObjects(intersectArr, false);
  149. console.log("intersects", intersects);
  150. if (intersects[0]) {
  151. this.startObj = intersects[0].object;
  152. this.drawing = true;
  153. } else {
  154. this.startObj = null;
  155. this.drawing = false;
  156. }
  157. }
  158. if (this.mode === 2) {
  159. if (!this.marker) {
  160. let pos = new THREE.Vector3(this.pointerdown.x, this.pointerdown.y, -1);
  161. pos.unproject(this.orthCamera);
  162. pos.y = 5;
  163. this.marker = new Marker(pos);
  164. this.scene.scene.add(this.marker);
  165. this.drawing = true;
  166. } else {
  167. // this.drawing = false;
  168. this.raycaster.setFromCamera(this.pointerdown, this.orthCamera);
  169. let intersectArr = this.scene.boxManager.imgList;
  170. const intersects = this.raycaster.intersectObjects(intersectArr, false);
  171. console.log("intersects", intersects);
  172. if (intersects[0]) {
  173. // this.drawing = false;
  174. const imageId = intersects[0].object.userData;
  175. let lasPos = new THREE.Vector3(
  176. this.pointerdown.x,
  177. this.pointerdown.y,
  178. -1
  179. );
  180. lasPos.unproject(this.orthCamera);
  181. lasPos.y = 5;
  182. const marker = new Marker(lasPos);
  183. const activeMarkeritem = {
  184. id: imageId,
  185. point: lasPos.toArray(),
  186. };
  187. const exist = this.renderMarkers.find((item) => item.id === imageId);
  188. if (!exist) {
  189. this.scene.scene.add(marker);
  190. this.renderMarkers.push(activeMarkeritem);
  191. this.scene.scene.remove(this.marker);
  192. this.marker = null;
  193. } else {
  194. this.scene.emit("markerExist");
  195. }
  196. console.log("activeMarkeritem", activeMarkeritem);
  197. }
  198. }
  199. }
  200. // this.floorplanControls.enabled = false;
  201. };
  202. onPointerUp = (e) => {
  203. this.pointerup = convertScreenToNDC(e, this.scene.domElement);
  204. console.log("onPointerUp", this.pointerup);
  205. if (this.mode === 1) {
  206. this.drawing = false;
  207. this.floorplanControls.enabled = true;
  208. this.startObj = null;
  209. if (this.drawLine) {
  210. const points = this.drawLine.userData.points;
  211. const dir = this.drawLine.userData.dir;
  212. const finishLine = new LinePoints(points, 0, this.matLine);
  213. this.renderLines.push(points);
  214. this.scene.scene.add(finishLine);
  215. const imageId = this.touchImg.object.userData;
  216. const activeLineItem = {
  217. id: imageId,
  218. dir: [dir],
  219. };
  220. console.log("this.touchImg", activeLineItem, points);
  221. this.insertActiveEdge(activeLineItem);
  222. this.drawLine = null;
  223. }
  224. }
  225. if (this.mode === 2) {
  226. // this.drawing = false;
  227. }
  228. this.syncDrawData();
  229. };
  230. Listener = {
  231. onPointerDown: this.onPointerDown.bind(this),
  232. onPointerMove: this.onPointerMove.bind(this),
  233. onPointerUp: this.onPointerUp.bind(this),
  234. };
  235. onBindEvent = () => {
  236. this.scene.domElement.addEventListener(
  237. "pointerdown",
  238. this.Listener.onPointerDown
  239. );
  240. this.scene.domElement.addEventListener(
  241. "pointermove",
  242. this.Listener.onPointerMove,
  243. false
  244. );
  245. this.scene.domElement.addEventListener(
  246. "pointerup",
  247. this.Listener.onPointerUp
  248. );
  249. };
  250. unbindEvent = () => {
  251. this.scene.domElement.removeEventListener(
  252. "pointerdown",
  253. this.Listener.onPointerDown
  254. );
  255. this.scene.domElement.removeEventListener(
  256. "pointermove",
  257. this.Listener.onPointerMove
  258. );
  259. this.scene.domElement.removeEventListener(
  260. "pointerup",
  261. this.Listener.onPointerUp
  262. );
  263. };
  264. buildLine = () => {
  265. if (this.drawLine) {
  266. this.drawLine.removeFromParent();
  267. }
  268. let s = new THREE.Vector3(this.pointerdown.x, this.pointerdown.y, -1);
  269. let e = new THREE.Vector3(this.pointermove.x, this.pointermove.y, -1);
  270. s.unproject(this.orthCamera);
  271. e.unproject(this.orthCamera);
  272. s.y = 5;
  273. e.y = 5;
  274. const matLine = new LineMaterial({
  275. color: this.lineColor,
  276. linewidth: 3, // in world units with size attenuation, pixels otherwise
  277. dashed: false,
  278. alphaToCoverage: true,
  279. });
  280. matLine.resolution = new THREE.Vector2(this.scene.width, this.scene.height);
  281. this.drawLine = new Line(s, e, this.activeEdge, matLine);
  282. this.scene.scene.add(this.drawLine);
  283. };
  284. setActiveLine = (obj) => {
  285. function getTouchLine(x, y) {
  286. // [0 - 1]
  287. x -= 0.5;
  288. y -= 0.5;
  289. // console.log(x, y);
  290. if (x >= 0 && y >= 0) {
  291. if (x > y) {
  292. return 3;
  293. } else {
  294. return 0;
  295. }
  296. } else if (x >= 0 && y <= 0) {
  297. if (x > Math.abs(y)) {
  298. return 3;
  299. } else {
  300. return 2;
  301. }
  302. } else if (x <= 0 && y >= 0) {
  303. if (Math.abs(x) > y) {
  304. return 1;
  305. } else {
  306. return 0;
  307. }
  308. } else if (x <= 0 && y <= 0) {
  309. if (-x > -y) {
  310. return 1;
  311. } else {
  312. return 2;
  313. }
  314. }
  315. }
  316. if (this.activeEdge) {
  317. this.activeEdge.visible = false;
  318. this.activeEdge = null;
  319. }
  320. let num = getTouchLine(obj.uv.x, obj.uv.y);
  321. this.activeEdge = obj.object.touchLines.getObjectByName(num);
  322. this.activeEdge.visible = true;
  323. this.buildLine();
  324. };
  325. insertActiveEdge(item) {
  326. const exist = this.activeEdges.find((s) => item.id === s.id);
  327. if (exist) {
  328. exist.dir = [...new Set([...exist.dir, ...item.dir])];
  329. } else {
  330. this.activeEdges.push(item);
  331. }
  332. }
  333. insertActiveMarker(item) {
  334. const exist = this.activeEdges.find((s) => item.id === s.id);
  335. if (exist) {
  336. exist.dir = [...new Set([...exist.dir, ...item.dir])];
  337. } else {
  338. this.activeEdges.push(item);
  339. }
  340. }
  341. showAllActiveEdges() {
  342. if (this.inited) {
  343. let imgList = this.scene.boxManager.imgList;
  344. this.activeEdges.forEach((edge) => {
  345. const exist = imgList.find((item) => item.userData === edge.id);
  346. // console.log("exist", exist);
  347. if (exist) {
  348. edge.dir.forEach((dir) => {
  349. exist.touchLines.children[dir].visible = true;
  350. });
  351. }
  352. });
  353. }
  354. }
  355. getDrawData() {
  356. let data;
  357. if (this.scene.sceneType === 1) {
  358. data = {
  359. hor_lines: this.renderLines,
  360. activeEdges: this.activeEdges,
  361. vir_lines: [],
  362. hor_markers: this.renderMarkers,
  363. vir_markers: [],
  364. };
  365. } else {
  366. data = {
  367. hor_lines: [],
  368. vir_lines: this.renderLines,
  369. activeEdges: this.activeEdges,
  370. vir_markers: this.renderMarkers,
  371. hor_markers: [],
  372. };
  373. }
  374. // console.log("sceneType", this.scene.sceneType);
  375. return data;
  376. }
  377. syncDrawData() {
  378. const data = this.getDrawData();
  379. this.scene.emit("data", data);
  380. }
  381. load(type, data) {
  382. if (type === 1) {
  383. console.log("data1", data);
  384. const { activeEdges, hor_lines, hor_markers } = data;
  385. activeEdges && (this.activeEdges = activeEdges);
  386. if (hor_lines && Array.isArray(hor_lines)) {
  387. this.renderLines = hor_lines;
  388. hor_lines.forEach((line) => {
  389. const finishLine = new LinePoints(line, 0, this.matLine);
  390. this.scene.scene.add(finishLine);
  391. });
  392. }
  393. if (hor_markers && Array.isArray(hor_markers)) {
  394. this.renderMarkers = hor_markers;
  395. hor_markers.forEach((pos) => {
  396. console.log("pos");
  397. const p = new THREE.Vector3().fromArray(pos.point);
  398. const marker = new Marker(p);
  399. this.scene.scene.add(marker);
  400. });
  401. }
  402. }
  403. if (type === 2) {
  404. const { activeEdges, vir_lines, vir_markers } = data;
  405. activeEdges && (this.activeEdges = activeEdges);
  406. if (vir_lines && Array.isArray(vir_lines)) {
  407. this.renderLines = vir_lines;
  408. vir_lines.forEach((line) => {
  409. const finishLine = new LinePoints(line, 0, this.matLine);
  410. this.scene.scene.add(finishLine);
  411. });
  412. }
  413. if (vir_markers && Array.isArray(vir_markers)) {
  414. this.renderMarkers = vir_markers;
  415. vir_markers.forEach((pos) => {
  416. const p = new THREE.Vector3().fromArray(pos.point);
  417. const marker = new Marker(p);
  418. this.scene.scene.add(marker);
  419. });
  420. }
  421. }
  422. }
  423. reset() {
  424. if (this.marker) {
  425. this.scene.scene.remove(this.marker);
  426. this.marker = null;
  427. }
  428. if (this.drawLine) {
  429. this.scene.scene.remove(this.drawLine);
  430. this.drawLine = null;
  431. }
  432. if (this.touchImg) {
  433. this.touchImg = null;
  434. }
  435. if (this.activeEdge) {
  436. this.activeEdge = null;
  437. }
  438. this.drawing = false;
  439. }
  440. update = () => {
  441. if (this.floorplanControls.enabled) {
  442. this.floorplanControls && this.floorplanControls.update();
  443. this.scene.boxManager && this.showAllActiveEdges();
  444. }
  445. };
  446. }