added avg paths

This commit is contained in:
2025-04-02 19:12:14 +05:30
parent d1e6b010e9
commit f5f74f35ad
7 changed files with 632 additions and 424 deletions

View File

@@ -5,22 +5,83 @@ import * as THREE from "three";
import * as Types from "../../../types/world/worldTypes";
import PathNavigator from "./pathNavigator";
import NavMeshDetails from "./navMeshDetails";
import {
useSelectedActionSphere,
useSimulationPaths,
} from "../../../store/store";
const Agv = ({ lines, plane }: { lines: Types.RefLines; plane: Types.RefMesh; }) => {
const pathPoints = useMemo(() => [
[
{ x: 8.477161935339709, y: 0, z: 17.41343083550102 },
{ x: 9.175416491482693, y: 0, z: -12.361001232663693 },
],
// [
// { x: 13.508213355232144, y: 0, z: -15.456970649652018 },
// { x: -30.464866520869617, y: 0, z: 9.779806557688929 },
// ],
[
{ x: 16.792040856420844, y: 0, z: 15.86281907549489 },
{ x: -42.77173264503395, y: 0, z: -15.821322764400804 },
],
], []);
const Agv = ({
lines,
plane,
}: {
lines: Types.RefLines;
plane: Types.RefMesh;
}) => {
const [pathPoints, setPathPoints] = useState<
{
uuid: string;
points: { x: number; y: number; z: number }[];
}[]
>([]);
const { simulationPaths } = useSimulationPaths();
const { selectedActionSphere } = useSelectedActionSphere();
useEffect(() => {
if (!Array.isArray(simulationPaths)) {
} else {
let agvModels = simulationPaths.filter(
(val: any) => val.modelName === "agv"
);
let findMesh = agvModels.filter(
(val: any) =>
val.modeluuid === selectedActionSphere?.path?.modeluuid &&
val.type === "Vehicle"
);
const result =
findMesh.length > 0 &&
findMesh[0].type === "Vehicle" &&
typeof findMesh[0].point?.actions.start === "object" &&
typeof findMesh[0].point?.actions.end === "object" &&
"x" in findMesh[0].point.actions.start &&
"y" in findMesh[0].point.actions.start &&
"x" in findMesh[0].point.actions.end &&
"y" in findMesh[0].point.actions.end
? [
{
uuid: findMesh[0].modeluuid, // Ensure it's a number
points: [
{
x: findMesh[0].position[0],
y: findMesh[0].position[1],
z: findMesh[0].position[2],
},
{
x: findMesh[0].point.actions.start.x,
y: 0,
z: findMesh[0].point.actions.start.y,
},
{
x: findMesh[0].point.actions.end.x,
y: 0,
z: findMesh[0].point.actions.end.y,
},
],
},
]
: [];
if (result.length > 0) {
setPathPoints((prev) => {
const existingUUIDs = new Set(prev.map((item) => item.uuid));
const newItems = result.filter(
(item) => !existingUUIDs.has(item.uuid)
);
return [...prev, ...newItems];
});
}
}
}, [simulationPaths, selectedActionSphere]);
let groupRef = useRef() as Types.RefGroup;
const [navMesh, setNavMesh] = useState();
@@ -35,7 +96,12 @@ const Agv = ({ lines, plane }: { lines: Types.RefLines; plane: Types.RefMesh; })
plane={plane}
/>
{pathPoints.map((pair, i) => (
<PathNavigator navMesh={navMesh} selectedPoints={pair} key={i} />
<PathNavigator
navMesh={navMesh}
selectedPoints={pair.points}
id={pair.uuid}
key={i}
/>
))}
<group ref={groupRef} visible={false} name="Meshes"></group>
</>

View File

@@ -35,10 +35,14 @@ export default function NavMeshDetails({
const [positions, indices] = getPositionsAndIndices(meshes);
const cs = 0.25;
const ch = 0.5;
const ch = 0.69;
const walkableRadius = 0.5;
const { success, navMesh } = generateSoloNavMesh(positions, indices, { cs, ch, walkableRadius: Math.round(walkableRadius / ch), });
const { success, navMesh } = generateSoloNavMesh(positions, indices, {
cs,
ch,
walkableRadius: Math.round(walkableRadius / ch),
});
if (!success || !navMesh) {
return;
@@ -49,7 +53,7 @@ export default function NavMeshDetails({
const debugDrawer = new DebugDrawer();
debugDrawer.drawNavMesh(navMesh);
// scene.add(debugDrawer);
} catch (error) { }
} catch (error) {}
};
initializeNavigation();

View File

@@ -1,98 +1,149 @@
import React, { useEffect, useState, useRef } from "react";
import * as THREE from "three";
import { useFrame } from "@react-three/fiber";
import { useFrame, useThree } from "@react-three/fiber";
import { NavMeshQuery } from "@recast-navigation/core";
import { Line } from "@react-three/drei";
import { useTh } from "leva/dist/declarations/src/styles";
import { useActiveTool } from "../../../store/store";
// Define interface for props
interface PathNavigatorProps {
navMesh: any;
selectedPoints: any;
id: string;
}
export default function PathNavigator({
navMesh,
selectedPoints,
id,
}: PathNavigatorProps) {
const [path, setPath] = useState<[number, number, number][]>([]);
const progressRef = useRef(0);
const distancesRef = useRef<number[]>([]);
const totalDistanceRef = useRef(0);
const currentSegmentIndex = useRef(0);
const { scene } = useThree();
const { activeTool } = useActiveTool();
const [startPoint, setStartPoint] = useState(new THREE.Vector3());
const meshRef = useRef<THREE.Mesh | null>(null);
useEffect(() => {
if (selectedPoints.length === 2 && navMesh) {
const [start, end] = selectedPoints;
if (!start || !end) return;
if (!scene || !id || path.length < 2) return;
const navMeshQuery = new NavMeshQuery(navMesh);
const { path: computedPath } = navMeshQuery.computePath(start, end);
if (computedPath.length > 0) {
setPath(computedPath.map(({ x, y, z }) => [x, y + 0.1, z]));
progressRef.current = 0;
}
let totalDistance = 0;
const distances: number[] = [];
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;
}
}, [selectedPoints, navMesh]);
distancesRef.current = distances;
totalDistanceRef.current = totalDistance;
progressRef.current = 0; // Reset progress when the path changes
}, [path]);
useEffect(() => {
if (!navMesh || selectedPoints.length === 0) return;
// Flatten the selectedPoints array into a single list of points
const allPoints = selectedPoints.flat();
// Compute paths between consecutive points
const computedPath: [number, number, number][] = [];
for (let i = 0; i < allPoints.length - 1; i++) {
const start = allPoints[i];
setStartPoint(
new THREE.Vector3(allPoints[0].x, allPoints[0].y, allPoints[0].z)
);
const end = allPoints[i + 1];
try {
const navMeshQuery = new NavMeshQuery(navMesh);
const { path: segmentPath } = navMeshQuery.computePath(start, end);
if (segmentPath && segmentPath.length > 0) {
computedPath.push(
...segmentPath.map(({ x, y, z }): [number, number, number] => [
x,
y + 0.1,
z,
])
);
}
} catch (error) {}
}
// Set the full computed path
if (computedPath.length > 0) {
setPath(computedPath);
currentSegmentIndex.current = 0; // Reset to the first segment
}
}, [selectedPoints, navMesh, path]);
useFrame((_, delta) => {
if (path.length > 1 && meshRef.current) {
const speed = 3;
progressRef.current += delta * speed;
if (!scene || !id || path.length < 2) return;
let totalDistance = 0;
const distances: number[] = [];
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;
}
// Find the object in the scene
const findObject = scene.getObjectByProperty("uuid", id);
if (activeTool === "play") {
if (!findObject) return;
const speed = 5;
progressRef.current += delta * speed;
let coveredDistance = progressRef.current;
let accumulatedDistance = 0;
let index = 0;
// Determine the current segment of the path
while (
index < distances.length &&
coveredDistance > accumulatedDistance + distances[index]
index < distancesRef.current.length &&
coveredDistance > accumulatedDistance + distancesRef.current[index]
) {
accumulatedDistance += distances[index];
accumulatedDistance += distancesRef.current[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
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;
// If the object has reached the end of the path, stop moving
if (index >= distancesRef.current.length) {
progressRef.current = totalDistanceRef.current;
return;
}
// Interpolate position within the current segment
const start = new THREE.Vector3(...path[index]);
const end = new THREE.Vector3(...path[index + 1]);
const segmentDistance = distancesRef.current[index];
const t = (coveredDistance - accumulatedDistance) / segmentDistance;
const position = start.clone().lerp(end, t);
findObject.position.copy(position);
// Rotate the object to face the direction of movement
const direction = new THREE.Vector3().subVectors(end, start).normalize();
const targetQuaternion = new THREE.Quaternion().setFromUnitVectors(
new THREE.Vector3(0, 0, 1), // Assuming forward direction is (0, 0, 1)
direction
);
findObject.quaternion.slerp(targetQuaternion, 0.1); // Smoothly interpolate rotation
} else if (activeTool === "cursor") {
findObject?.position.copy(startPoint);
}
});
return (
<>
{/* {path.length > 0 && <Line points={path} color="blue" lineWidth={3} />} */}
{path.length > 0 && (
{path.length > 0 && <Line points={path} color="blue" lineWidth={3} />}
{/* {path.length > 0 && (
<mesh ref={meshRef} position={path.length > 0 ? path[0] : [0, 0.1, 0]}>
<boxGeometry args={[1, 1, 1]} />
<meshNormalMaterial />
</mesh>
)}
)} */}
</>
);
}