added Navmesh Details
This commit is contained in:
140
app/src/modules/builder/agv/pathNavigator.tsx
Normal file
140
app/src/modules/builder/agv/pathNavigator.tsx
Normal file
@@ -0,0 +1,140 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import * as THREE from "three";
|
||||
import { NavMeshQuery } from "@recast-navigation/core";
|
||||
import { NavMesh as RecastNavMesh } from "@recast-navigation/core";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { Line } from "@react-three/drei";
|
||||
interface Pair {
|
||||
x: number;
|
||||
y: number;
|
||||
z: number;
|
||||
}
|
||||
interface PathProps {
|
||||
navMesh: RecastNavMesh | null; // The navigation mesh
|
||||
pathPoints: Pair[] | undefined; // Array of points (or undefined)
|
||||
}
|
||||
const PathNavigator = ({ navMesh, pathPoints }: PathProps) => {
|
||||
const { scene, raycaster, gl } = useThree();
|
||||
|
||||
const [path, setPath] = useState<THREE.Vector3[]>([]); // Path is an array of THREE.Vector3
|
||||
const [points, setSelectedPoints] = useState<THREE.Vector3[]>([]); // Path is an array of THREE.Vector3
|
||||
const progressRef = useRef<number>(0);
|
||||
const meshRef = useRef<THREE.Mesh>(null!);
|
||||
const handleClick = useCallback(() => {
|
||||
if (!navMesh) return;
|
||||
|
||||
const intersects = raycaster.intersectObjects(scene.children, true);
|
||||
if (intersects.length > 0) {
|
||||
const { point } = intersects[0];
|
||||
const newPoint = { x: point.x, y: 0, z: point.z };
|
||||
|
||||
setSelectedPoints((prevPoints: THREE.Vector3[]) => {
|
||||
if (prevPoints.length === 2) {
|
||||
// If two points already exist, replace them with the new point
|
||||
return [new THREE.Vector3(newPoint.x, newPoint.y, newPoint.z)];
|
||||
}
|
||||
// Otherwise, append the new point to the array
|
||||
return [
|
||||
...prevPoints,
|
||||
new THREE.Vector3(newPoint.x, newPoint.y, newPoint.z),
|
||||
];
|
||||
});
|
||||
}
|
||||
}, [navMesh, scene]);
|
||||
React.useEffect(() => {
|
||||
if (points?.length === 2 && navMesh) {
|
||||
const [start, end] = points;
|
||||
console.log("start: ", start);
|
||||
console.log("end: ", end);
|
||||
|
||||
const navMeshQuery = new NavMeshQuery(navMesh);
|
||||
console.log("navMeshQuery: ", navMeshQuery);
|
||||
|
||||
const { path } = navMeshQuery.computePath(start, end);
|
||||
console.log("paths: ", path);
|
||||
|
||||
// if (path.length > 0) {
|
||||
// setPath(
|
||||
// path.map((point) => {
|
||||
// const newY = point.y + 0.1; // Increment the y-coordinate
|
||||
// return new THREE.Vector3(point.x, newY, point.z); // Create a new Vector3
|
||||
// })
|
||||
// );
|
||||
// progressRef.current = 0;
|
||||
// }
|
||||
}
|
||||
}, [points,]);
|
||||
|
||||
useFrame((_, delta) => {
|
||||
if (path.length > 1 && meshRef.current) {
|
||||
const speed = 3;
|
||||
progressRef.current += delta * speed;
|
||||
let totalDistance = 0;
|
||||
const distances = [];
|
||||
for (let i = 0; i < path.length - 1; i++) {
|
||||
const start = new THREE.Vector3(...path[i]);
|
||||
const end = new THREE.Vector3(...path[i + 1]);
|
||||
const segmentDistance = start.distanceTo(end);
|
||||
distances.push(segmentDistance);
|
||||
totalDistance += segmentDistance;
|
||||
}
|
||||
|
||||
let coveredDistance = progressRef.current;
|
||||
let accumulatedDistance = 0;
|
||||
let index = 0;
|
||||
|
||||
while (
|
||||
index < distances.length &&
|
||||
coveredDistance > accumulatedDistance + distances[index]
|
||||
) {
|
||||
accumulatedDistance += distances[index];
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index < distances.length) {
|
||||
const start = new THREE.Vector3(...path[index]);
|
||||
const end = new THREE.Vector3(...path[index + 1]);
|
||||
const segmentDistance = distances[index];
|
||||
|
||||
const t = (coveredDistance - accumulatedDistance) / segmentDistance;
|
||||
const position = start.lerp(end, t);
|
||||
meshRef.current.position.copy(position);
|
||||
|
||||
const direction = new THREE.Vector3()
|
||||
.subVectors(end, start)
|
||||
.normalize();
|
||||
const targetQuaternion = new THREE.Quaternion().setFromUnitVectors(
|
||||
new THREE.Vector3(0, 0, 1),
|
||||
direction
|
||||
);
|
||||
meshRef.current.quaternion.slerp(targetQuaternion, 0.1);
|
||||
} else {
|
||||
progressRef.current = totalDistance;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
gl.domElement.addEventListener("click", handleClick);
|
||||
return () => gl.domElement.removeEventListener("click", handleClick);
|
||||
}, [handleClick]);
|
||||
return (
|
||||
<>
|
||||
{path.length > 0 && <Line points={path} color="blue" lineWidth={3} />}
|
||||
{path.length > 0 && (
|
||||
// <primitive
|
||||
// ref={gltfRef}
|
||||
// object={gltfClone}
|
||||
// position={path.length > 0 ? path[0] : [0, 0.1, 0]}
|
||||
// scale={[0.5, 0.5, 0.5]}
|
||||
// />
|
||||
<mesh ref={meshRef} position={path.length > 0 ? path[0] : [0, 0.1, 0]}>
|
||||
<boxGeometry args={[1, 1, 1]} />
|
||||
<meshNormalMaterial />
|
||||
</mesh>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PathNavigator;
|
||||
Reference in New Issue
Block a user