Dwinzo_dev/app/src/modules/builder/agv/pathNavigator.tsx

99 lines
3.0 KiB
TypeScript
Raw Normal View History

import React, { useEffect, useState, useRef } from "react";
2025-03-26 12:58:14 +00:00
import * as THREE from "three";
import { useFrame } from "@react-three/fiber";
2025-03-26 12:58:14 +00:00
import { NavMeshQuery } from "@recast-navigation/core";
import { Line } from "@react-three/drei";
// Define interface for props
interface PathNavigatorProps {
navMesh: any;
selectedPoints: any;
}
2025-03-26 12:58:14 +00:00
export default function PathNavigator({
navMesh,
selectedPoints,
}: PathNavigatorProps) {
const [path, setPath] = useState<[number, number, number][]>([]);
const progressRef = useRef(0);
const meshRef = useRef<THREE.Mesh | null>(null);
2025-03-26 12:58:14 +00:00
useEffect(() => {
if (selectedPoints.length === 2 && navMesh) {
const [start, end] = selectedPoints;
if (!start || !end) return;
2025-03-26 12:58:14 +00:00
const navMeshQuery = new NavMeshQuery(navMesh);
const { path: computedPath } = navMeshQuery.computePath(start, end);
2025-03-26 12:58:14 +00:00
if (computedPath.length > 0) {
setPath(computedPath.map(({ x, y, z }) => [x, y + 0.1, z]));
progressRef.current = 0;
}
2025-03-26 12:58:14 +00:00
}
}, [selectedPoints, navMesh]);
2025-03-26 12:58:14 +00:00
useFrame((_, delta) => {
if (path.length > 1 && meshRef.current) {
const speed = 3;
progressRef.current += delta * speed;
2025-03-26 12:58:14 +00:00
let totalDistance = 0;
const distances: number[] = [];
2025-03-26 12:58:14 +00:00
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.clone().lerp(end, t); // Use clone() to avoid mutating the original vector
2025-03-26 12:58:14 +00:00
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;
}
}
});
return (
<>
{/* {path.length > 0 && <Line points={path} color="blue" lineWidth={3} />} */}
2025-03-26 12:58:14 +00:00
{path.length > 0 && (
<mesh ref={meshRef} position={path.length > 0 ? path[0] : [0, 0.1, 0]}>
<boxGeometry args={[1, 1, 1]} />
<meshNormalMaterial />
</mesh>
)}
</>
);
}