diff --git a/src/frontend/src/pages/Components/Drone.js b/src/frontend/src/pages/Components/Drone.js deleted file mode 100644 index dc7e12c..0000000 --- a/src/frontend/src/pages/Components/Drone.js +++ /dev/null @@ -1,80 +0,0 @@ -import * as THREE from 'three'; -import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; - -export class Drone { - constructor() { - this.drone = new THREE.Object3D(); - - // Создаем основное тело дрона (цилиндрическая форма) - const bodyGeometry = new THREE.CylinderGeometry(0.4, 0.6, 1, 32); - const bodyMaterial = new THREE.MeshStandardMaterial({ color: 0x0077ff, metalness: 0.6, roughness: 0.4 }); - const body = new THREE.Mesh(bodyGeometry, bodyMaterial); - body.rotation.z = Math.PI / 2; // Поворачиваем для более аэродинамической формы - this.drone.add(body); - - // Добавляем 4 стойки шасси - const legGeometry = new THREE.CylinderGeometry(0.05, 0.05, 0.6, 16); - const legMaterial = new THREE.MeshBasicMaterial({ color: 0x444444 }); - const legPositions = [ - [-0.4, -0.6, -0.4], - [-0.4, -0.6, 0.4], - [0.4, -0.6, -0.4], - [0.4, -0.6, 0.4], - ]; - legPositions.forEach((position) => { - const leg = new THREE.Mesh(legGeometry, legMaterial); - leg.position.set(...position); - leg.rotation.x = Math.PI / 2; - this.drone.add(leg); - }); - - // Создаем пропеллеры - const propellerGeometry = new THREE.BoxGeometry(0.2, 0.02, 1.2); - const propellerMaterial = new THREE.MeshBasicMaterial({ color: 0x333333 }); - const propellerPositions = [ - [-0.6, 0.4, -0.6], - [-0.6, 0.4, 0.6], - [0.6, 0.4, -0.6], - [0.6, 0.4, 0.6], - ]; - this.propellers = []; - - propellerPositions.forEach((position) => { - const propeller = new THREE.Mesh(propellerGeometry, propellerMaterial); - propeller.position.set(...position); - propeller.rotation.y = Math.PI / 2; - this.propellers.push(propeller); - this.drone.add(propeller); - }); - - // Загрузка более детализированной 3D модели (опционально) - // const loader = new GLTFLoader(); - // loader.load( - // './path_to_your_drone_model.glb', - // (gltf) => { - // this.drone.add(gltf.scene); - // }, - // undefined, - // (error) => { - // console.error('Ошибка при загрузке модели:', error); - // } - // ); - } - - // Метод для вращения пропеллеров - rotatePropellers(speed) { - this.propellers.forEach((propeller) => { - propeller.rotation.z += speed; - }); - } - - // Метод для установки позиции дрона - setPosition(x, y, z) { - this.drone.position.set(x, y, z); - } - - // Получаем объект дрона для добавления в сцену - getObject() { - return this.drone; - } -} diff --git a/src/frontend/src/pages/Dashboard.js b/src/frontend/src/pages/Dashboard.js index d82aff2..e12bf92 100644 --- a/src/frontend/src/pages/Dashboard.js +++ b/src/frontend/src/pages/Dashboard.js @@ -3,40 +3,41 @@ import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; import { FontLoader } from 'three/examples/jsm/loaders/FontLoader'; import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry'; -import { Drone } from './Components/Drone'; -import HeightPoint from './Model/HeightPoint'; - - -const RandomHeightPoint = () => { - let result = []; - for (let i = 0; i < 20; i++) { - for (let j = 0; j < 20; j++) { - result.push(new HeightPoint(i, j, Math.random() * 10 + 1)); - } - } - return result; -}; +import Drone from './model/Drone'; +import HeightPoint from './model/HeightPoint'; +import {RandomHeightPoint} from './helpers/generateRandomHeightPoints' +import { GUI } from 'three/addons/libs/lil-gui.module.min.js'; const Dashboard = () => { - const mountRef = useRef(null); - const sceneRef = useRef(null); - const [heightData, setHeightData] = useState(RandomHeightPoint()); - const [formData, setFormData] = useState({ x: '', y: '', height: '' }); - const [drones, setDrones] = useState([]) - const [mapSettings, setMapSettings] = useState({ + const mountRef = useRef(null); // Указатель монтирования + const sceneRef = useRef(null); // Указатель на сцену + const [heightData, setHeightData] = useState(RandomHeightPoint()); // Высоты + const [formData, setFormData] = useState({ x: '', y: '', height: '' }); // Форма для ввода данных карты + const [mouseState, setMouseState] = useState({ x: 0, y: 0, z: 0 }); // Форма для ввода данных карты + const mouse = new THREE.Vector2(); + + const [drones, setDrones] = useState([]) // Все дроны + const [selectedDrone, setSelectedDrone] = useState(null); // Состояние для выбранного дрона + + const [baseStation, setBaseStation] = useState([]) // Все дроны + const [selectedBaseStation, setSelectedBaseStation] = useState(null); // Состояние для выбранного дрона + + const [mapSettings, setMapSettings] = useState({ maxHeight: 20, coordX: 0, coordY: 0, - }); - const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 }); - + }); // Настройки карты + + const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 }); // контекстное меню сцены useEffect(() => { if (!mountRef.current) return; let width = mountRef.current.clientWidth; let height = mountRef.current.clientHeight; - + // Создаем объект сцены const scene = new THREE.Scene(); - sceneRef.current = scene; // Сохраняем ссылку на сцену + // Сохраняем ссылку на сцену + sceneRef.current = scene; + // Создаем камеру const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000); camera.position.set(0, 20, 30); @@ -90,6 +91,44 @@ const Dashboard = () => { light.position.set(0, 50, 50).normalize(); scene.add(light); + // Обработка кликов на сцене + const handleClick = (event) => { + mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; + mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; + console.log('Mouse coordinates:', mouse); + const raycaster = new THREE.Raycaster(); + raycaster.setFromCamera(mouse, camera); + + const intersects = raycaster.intersectObjects(drones.map(drone => drone.getObject()), true); + console.log('Intersections:', intersects) + console.log('Drones:', drones.map(drone => [drone.getObject(), drone.getObject().position, drone.name])) + if (intersects.length > 0) { + const selected = intersects[0].object; + console.log('Clicked on:', selected); // Лог для проверки объекта + const drone = drones.find(drone => drone.getObject().children[0] === selected); + if (drone) { + if (selectedDrone) { + selectedDrone.getObject().children[0].material.color.set(0xff0000); + } + drone.getObject().children[0].material.color.set(0xff1111); + setSelectedDrone(drone); + } + } else { + if (selectedDrone) { + selectedDrone.getObject().children[0].material.color.set(0xff0000); + setSelectedDrone(null); + } + } + }; + + + + renderer.domElement.addEventListener('click', handleClick); + renderer.domElement.addEventListener('mousemove', (event) => { + let x = event.x; + let y = event.y; + setMouseState({x: x, y: y, z: 0}); + }) const animate = () => { requestAnimationFrame(animate); controls.update(); @@ -103,6 +142,7 @@ const Dashboard = () => { // drone.setPosition(droneData.x, droneData.y, droneData.z); scene.add(droneData.getObject()); //drone.getObject() }); + // Обработка нажатия ПКМ renderer.domElement.addEventListener('contextmenu', (event) => { event.preventDefault(); @@ -112,23 +152,31 @@ const Dashboard = () => { y: event.clientY, }); }); - + // const gui = new GUI(); + // gui.add( effectController, 'focalLength', 1, 135, 0.01 ).onChange( matChanger ); return () => { if (mountRef.current) { mountRef.current.removeChild(renderer.domElement); } }; - }, [heightData, mapSettings]); + }, [drones,heightData, mapSettings]); + // Добавление дрона в сцену const handleAddDrone = () => { if (sceneRef.current) { - const drone = new Drone(); - drone.setPosition(Math.random() * 20 - 10, 0.5, Math.random() * 20 - 10); + const current = Date.now(); + const drone = new Drone(current/1000); + // Создаем новый материал для каждого дрона + const droneMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 }); + drone.getObject().children[0].material = droneMaterial; + drone.setPosition(Math.random() * 20 - 10, 3, Math.random() * 20 - 10); setDrones((prevDrones) => [...prevDrones, drone]); + console.log(drones.map(drone => drone.getObject().children[0])); sceneRef.current.add(drone.getObject()); } }; - + + // const handleInputChange = (event) => { const { name, value } = event.target; setFormData({ @@ -136,7 +184,7 @@ const Dashboard = () => { [name]: value, }); }; - + // Добавление элемента карты высот (высоты) const handleAddHeight = (event) => { event.preventDefault(); @@ -147,7 +195,7 @@ const Dashboard = () => { setHeightData((prevData) => [...prevData, newPoint]); setFormData({ x: '', y: '', height: '' }); }; - + // Изменение настроек const handleSettingsChange = (event) => { const { name, value } = event.target; setMapSettings({ @@ -155,7 +203,7 @@ const Dashboard = () => { [name]: value, }); }; - + // Открытие контекстного меню const handleContextMenuClick = (action) => { if (action === 'add') { handleAddDrone(); @@ -172,37 +220,23 @@ const Dashboard = () => { - -
- +
+
+

x: {mouseState.x} y: {mouseState.y} z: {mouseState.z}

+
+
+
{/* Контекстное меню */} {contextMenu.visible && (