import * as THREE from "three"; import FloorplanControls from "../controls/FloorplanControls.js"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; import { TrackballControls } from "three/examples/jsm/controls/TrackballControls.js"; import Line from "../box/object/Line"; import LinePoints from "../box/object/LinePoints.js"; import Marker from "../box/object/marker.js"; import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js"; const convertScreenToNDC = function (event, domElement) { let x = (event.offsetX / domElement.clientWidth) * 2 - 1; let y = -(event.offsetY / domElement.clientHeight) * 2 + 1; return new THREE.Vector2(x, y); }; export default class Player { constructor(scene) { this.scene = scene; this.orthCamera = scene.orthCamera; this.floorplanControls = null; this.raycaster = null; this.position = new THREE.Vector3(); this.pointerdown = new THREE.Vector2(); this.pointerup = new THREE.Vector2(); this.pointer = new THREE.Vector2(); this.markPosition = new THREE.Vector3(); this.touchImg = null; this.activeEdge = null; this.drawLine = null; this.startObj = null; this.marker = null; this.allowDrawing = false; this.drawing = false; this.inited = false; this.renderLines = []; this.renderMarkers = []; this.activeEdges = []; this.matLine = null; this.lineColor = 0xe44d54; // 1是画线,2是标方向 this.mode = 0; this.init(); } setMode(mode) { this.mode = mode; if (mode === 1 || mode === 2) { this.reset(); this.setEditMode(); } if (mode === 0) { this.setFreeMode(); } this.scene.emit("mode", this.mode); } // removeMarker() { // if (this.marker) { // this.scene.scene.remove(this.marker); // this.marker = null; // } // } setFreeMode() { this.floorplanControls.enablePan = true; this.floorplanControls.mouseButtons = { LEFT: THREE.MOUSE.PAN, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN, }; this.reset(); } setEditMode() { this.floorplanControls.enablePan = true; this.floorplanControls.mouseButtons = { LEFT: THREE.MOUSE.ROTATE, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.PAN, }; } init = () => { // //floorplanControls // this.floorplanControls = new FloorplanControls( // this.orthCamera, // this.scene.domElement, // this // ); this.floorplanControls = new OrbitControls( this.orthCamera, this.scene.domElement ); this.floorplanControls.enablePan = true; // this.floorplanControls.target.set(0, 1, 0); // this.floorplanControls.rotateSpeed = 0.5; // this.floorplanControls.panSpeed = 0.75 this.floorplanControls.maxDistance = 100; this.floorplanControls.minDistance = 3.5; this.floorplanControls.maxZoom = 500; this.floorplanControls.minZoom = 100; // this.floorplanControls.mouseButtons = { // LEFT: THREE.MOUSE.PAN, // MIDDLE: THREE.MOUSE.DOLLY, // RIGHT: THREE.MOUSE.PAN // } this.setMode(0); this.floorplanControls.enableRotate = false; this.raycaster = new THREE.Raycaster(); this.onBindEvent(); this.inited = true; this.matLine = new LineMaterial({ color: this.lineColor, linewidth: 3, // in world units with size attenuation, pixels otherwise dashed: false, alphaToCoverage: true, }); this.matLine.resolution = new THREE.Vector2( this.scene.width, this.scene.height ); }; onPointerMove = (e) => { if (!this.drawing) return; this.pointermove = convertScreenToNDC(e, this.scene.domElement); if (this.mode === 1) { this.raycaster.setFromCamera(this.pointermove, this.orthCamera); let intersectArr = this.scene.boxManager.imgList; // if(this.startObj) { // let i = intersectArr.indexOf(this.startObj) // intersectArr.splice(i, 1) // } const intersects = this.raycaster.intersectObjects(intersectArr, false); if (intersects[0] && intersects[0].object !== this.startObj) { this.touchImg = intersects[0]; this.setActiveLine(this.touchImg); } } if (this.mode === 2) { if (this.marker) { let pos = new THREE.Vector3(this.pointermove.x, this.pointermove.y, -1); pos.unproject(this.orthCamera); pos.y = 5; // console.log("pos", pos); this.marker.position.copy(pos); } } }; onPointerDown = (e) => { console.log("start draw"); this.pointerdown = convertScreenToNDC(e, this.scene.domElement); if (this.mode === 1) { this.raycaster.setFromCamera(this.pointerdown, this.orthCamera); let intersectArr = this.scene.boxManager.imgList; const intersects = this.raycaster.intersectObjects(intersectArr, false); console.log("intersects", intersects); if (intersects[0]) { this.startObj = intersects[0].object; this.drawing = true; } else { this.startObj = null; this.drawing = false; } } if (this.mode === 2) { if (!this.marker) { let pos = new THREE.Vector3(this.pointerdown.x, this.pointerdown.y, -1); pos.unproject(this.orthCamera); pos.y = 5; this.marker = new Marker(pos); this.scene.scene.add(this.marker); this.drawing = true; } else { // this.drawing = false; this.raycaster.setFromCamera(this.pointerdown, this.orthCamera); let intersectArr = this.scene.boxManager.imgList; const intersects = this.raycaster.intersectObjects(intersectArr, false); console.log("intersects", intersects); if (intersects[0]) { // this.drawing = false; const imageId = intersects[0].object.userData; let lasPos = new THREE.Vector3( this.pointerdown.x, this.pointerdown.y, -1 ); lasPos.unproject(this.orthCamera); lasPos.y = 5; const marker = new Marker(lasPos); const activeMarkeritem = { id: imageId, point: lasPos.toArray(), }; const exist = this.renderMarkers.find((item) => item.id === imageId); if (!exist) { this.scene.scene.add(marker); this.renderMarkers.push(activeMarkeritem); this.scene.scene.remove(this.marker); this.marker = null; } else { this.scene.emit("markerExist"); } console.log("activeMarkeritem", activeMarkeritem); } } } // this.floorplanControls.enabled = false; }; onPointerUp = (e) => { this.pointerup = convertScreenToNDC(e, this.scene.domElement); console.log("onPointerUp", this.pointerup); if (this.mode === 1) { this.drawing = false; this.floorplanControls.enabled = true; this.startObj = null; if (this.drawLine) { const points = this.drawLine.userData.points; const dir = this.drawLine.userData.dir; const finishLine = new LinePoints(points, 0, this.matLine); this.renderLines.push(points); this.scene.scene.add(finishLine); const imageId = this.touchImg.object.userData; const activeLineItem = { id: imageId, dir: [dir], }; console.log("this.touchImg", activeLineItem, points); this.insertActiveEdge(activeLineItem); this.drawLine = null; } } if (this.mode === 2) { // this.drawing = false; } this.syncDrawData(); }; Listener = { onPointerDown: this.onPointerDown.bind(this), onPointerMove: this.onPointerMove.bind(this), onPointerUp: this.onPointerUp.bind(this), }; onBindEvent = () => { this.scene.domElement.addEventListener( "pointerdown", this.Listener.onPointerDown ); this.scene.domElement.addEventListener( "pointermove", this.Listener.onPointerMove, false ); this.scene.domElement.addEventListener( "pointerup", this.Listener.onPointerUp ); }; unbindEvent = () => { this.scene.domElement.removeEventListener( "pointerdown", this.Listener.onPointerDown ); this.scene.domElement.removeEventListener( "pointermove", this.Listener.onPointerMove ); this.scene.domElement.removeEventListener( "pointerup", this.Listener.onPointerUp ); }; buildLine = () => { if (this.drawLine) { this.drawLine.removeFromParent(); } let s = new THREE.Vector3(this.pointerdown.x, this.pointerdown.y, -1); let e = new THREE.Vector3(this.pointermove.x, this.pointermove.y, -1); s.unproject(this.orthCamera); e.unproject(this.orthCamera); s.y = 5; e.y = 5; const matLine = new LineMaterial({ color: this.lineColor, linewidth: 3, // in world units with size attenuation, pixels otherwise dashed: false, alphaToCoverage: true, }); matLine.resolution = new THREE.Vector2(this.scene.width, this.scene.height); this.drawLine = new Line(s, e, this.activeEdge, matLine); this.scene.scene.add(this.drawLine); }; setActiveLine = (obj) => { function getTouchLine(x, y) { // [0 - 1] x -= 0.5; y -= 0.5; // console.log(x, y); if (x >= 0 && y >= 0) { if (x > y) { return 3; } else { return 0; } } else if (x >= 0 && y <= 0) { if (x > Math.abs(y)) { return 3; } else { return 2; } } else if (x <= 0 && y >= 0) { if (Math.abs(x) > y) { return 1; } else { return 0; } } else if (x <= 0 && y <= 0) { if (-x > -y) { return 1; } else { return 2; } } } if (this.activeEdge) { this.activeEdge.visible = false; this.activeEdge = null; } let num = getTouchLine(obj.uv.x, obj.uv.y); this.activeEdge = obj.object.touchLines.getObjectByName(num); this.activeEdge.visible = true; this.buildLine(); }; insertActiveEdge(item) { const exist = this.activeEdges.find((s) => item.id === s.id); if (exist) { exist.dir = [...new Set([...exist.dir, ...item.dir])]; } else { this.activeEdges.push(item); } } insertActiveMarker(item) { const exist = this.activeEdges.find((s) => item.id === s.id); if (exist) { exist.dir = [...new Set([...exist.dir, ...item.dir])]; } else { this.activeEdges.push(item); } } showAllActiveEdges() { if (this.inited) { let imgList = this.scene.boxManager.imgList; this.activeEdges.forEach((edge) => { const exist = imgList.find((item) => item.userData === edge.id); // console.log("exist", exist); if (exist) { edge.dir.forEach((dir) => { exist.touchLines.children[dir].visible = true; }); } }); } } getDrawData() { let data; if (this.scene.sceneType === 1) { data = { hor_lines: this.renderLines, activeEdges: this.activeEdges, vir_lines: [], hor_markers: this.renderMarkers, vir_markers: [], }; } else { data = { hor_lines: [], vir_lines: this.renderLines, activeEdges: this.activeEdges, vir_markers: this.renderMarkers, hor_markers: [], }; } // console.log("sceneType", this.scene.sceneType); return data; } syncDrawData() { const data = this.getDrawData(); this.scene.emit("data", data); } load(type, data) { if (type === 1) { console.log("data1", data); const { activeEdges, hor_lines, hor_markers } = data; activeEdges && (this.activeEdges = activeEdges); if (hor_lines && Array.isArray(hor_lines)) { this.renderLines = hor_lines; hor_lines.forEach((line) => { const finishLine = new LinePoints(line, 0, this.matLine); this.scene.scene.add(finishLine); }); } if (hor_markers && Array.isArray(hor_markers)) { this.renderMarkers = hor_markers; hor_markers.forEach((pos) => { console.log("pos"); const p = new THREE.Vector3().fromArray(pos.point); const marker = new Marker(p); this.scene.scene.add(marker); }); } } if (type === 2) { const { activeEdges, vir_lines, vir_markers } = data; activeEdges && (this.activeEdges = activeEdges); if (vir_lines && Array.isArray(vir_lines)) { this.renderLines = vir_lines; vir_lines.forEach((line) => { const finishLine = new LinePoints(line, 0, this.matLine); this.scene.scene.add(finishLine); }); } if (vir_markers && Array.isArray(vir_markers)) { this.renderMarkers = vir_markers; vir_markers.forEach((pos) => { const p = new THREE.Vector3().fromArray(pos.point); const marker = new Marker(p); this.scene.scene.add(marker); }); } } } reset() { if (this.marker) { this.scene.scene.remove(this.marker); this.marker = null; } if (this.drawLine) { this.scene.scene.remove(this.drawLine); this.drawLine = null; } if (this.touchImg) { this.touchImg = null; } if (this.activeEdge) { this.activeEdge = null; } this.drawing = false; } update = () => { if (this.floorplanControls.enabled) { this.floorplanControls && this.floorplanControls.update(); this.scene.boxManager && this.showAllActiveEdges(); } }; }