object attach and detach added

This commit is contained in:
Gomathi 2025-05-05 19:05:09 +05:30
parent 19d41a775c
commit cea9a32ce4
9 changed files with 86 additions and 72 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,66 @@
import { useFrame } from '@react-three/fiber';
import React, { useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
import { useLogger } from '../../../../../components/ui/log/LoggerContext';
type MaterialAnimatorProps = {
ikSolver: any;
armBot: any;
currentPhase: string;
};
export default function MaterialAnimator({ ikSolver, armBot, currentPhase }: MaterialAnimatorProps) {
const sphereRef = useRef<THREE.Mesh>(null);
const boneWorldPosition = new THREE.Vector3();
const [isRendered, setIsRendered] = useState<boolean>(false);
useEffect(() => {
if (currentPhase === "start-to-end") {
setIsRendered(true);
} else {
setIsRendered(false);
}
}, [currentPhase]);
useFrame(() => {
if (!ikSolver || !sphereRef.current) return;
const boneTarget = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === "Bone004");
const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === "Effector");
if (!boneTarget || !bone) return;
if (currentPhase === "start-to-end") {
// Get world positions
const boneTargetWorldPos = new THREE.Vector3();
const boneWorldPos = new THREE.Vector3();
boneTarget.getWorldPosition(boneTargetWorldPos);
bone.getWorldPosition(boneWorldPos);
// Calculate direction
const direction = new THREE.Vector3();
direction.subVectors(boneWorldPos, boneTargetWorldPos).normalize();
const downwardDirection = direction.clone().negate();
const adjustedPosition = boneWorldPos.clone().addScaledVector(downwardDirection, -0.25);
//set position
sphereRef.current.position.copy(adjustedPosition);
// Set rotation
const worldQuaternion = new THREE.Quaternion();
bone.getWorldQuaternion(worldQuaternion);
sphereRef.current.quaternion.copy(worldQuaternion);
}
});
return (
<>
{isRendered && (
<mesh ref={sphereRef}>
<boxGeometry args={[0.5, 0.5, 0.5]} />
<meshStandardMaterial color="yellow" />
</mesh>
)}
</>
);
}

View File

@ -15,7 +15,6 @@ function RoboticArmAnimator({
ikSolver, ikSolver,
targetBone, targetBone,
armBot, armBot,
logStatus,
path path
}: any) { }: any) {
const progressRef = useRef(0); const progressRef = useRef(0);
@ -30,9 +29,11 @@ function RoboticArmAnimator({
// Zustand stores // Zustand stores
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { isPaused } = usePauseButtonStore(); const { isPaused } = usePauseButtonStore();
const { isReset, setReset } = useResetButtonStore(); const { isReset } = useResetButtonStore();
const { speed } = useAnimationPlaySpeed(); const { speed } = useAnimationPlaySpeed();
const CIRCLE_RADIUS = 1.6
// Update path state whenever `path` prop changes // Update path state whenever `path` prop changes
useEffect(() => { useEffect(() => {
setCurrentPath(path); setCurrentPath(path);
@ -40,13 +41,13 @@ function RoboticArmAnimator({
// Handle circle points based on armBot position // Handle circle points based on armBot position
useEffect(() => { useEffect(() => {
const points = generateRingPoints(1.6, 64) const points = generateRingPoints(CIRCLE_RADIUS, 64)
setCirclePoints(points); setCirclePoints(points);
}, [armBot.position]); }, [armBot.position]);
//Handle Reset Animation //Handle Reset Animation
useEffect(() => { useEffect(() => {
if (isReset ) { if (isReset) {
progressRef.current = 0; progressRef.current = 0;
curveRef.current = null; curveRef.current = null;
setCurrentPath([]); setCurrentPath([]);
@ -98,7 +99,7 @@ function RoboticArmAnimator({
return distance < nearestDistance ? point : nearest; return distance < nearestDistance ? point : nearest;
}, circlePoints[0]); }, circlePoints[0]);
}; };
// Handle nearest points and final path (including arc points) // Handle nearest points and final path (including arc points)
useEffect(() => { useEffect(() => {
if (circlePoints.length > 0 && currentPath.length > 0) { if (circlePoints.length > 0 && currentPath.length > 0) {
@ -109,14 +110,6 @@ function RoboticArmAnimator({
const raisedStart = [start[0], start[1] + 0.5, start[2]] as [number, number, number]; const raisedStart = [start[0], start[1] + 0.5, start[2]] as [number, number, number];
const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [number, number, number]; const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [number, number, number];
// const findNearest = (target: [number, number, number]) => {
// return circlePoints.reduce((nearest, point) => {
// const distance = Math.hypot(target[0] - point[0], target[1] - point[1], target[2] - point[2]);
// const nearestDistance = Math.hypot(target[0] - nearest[0], target[1] - nearest[1], target[2] - nearest[2]);
// return distance < nearestDistance ? point : nearest;
// }, circlePoints[0]);
// };
const nearestToStart = findNearest(raisedStart); const nearestToStart = findNearest(raisedStart);
const nearestToEnd = findNearest(raisedEnd); const nearestToEnd = findNearest(raisedEnd);
@ -187,6 +180,7 @@ function RoboticArmAnimator({
if (!ikSolver) return; if (!ikSolver) return;
const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone); const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
if (!bone) return; if (!bone) return;
if (isPlaying) { if (isPlaying) {
@ -252,7 +246,7 @@ function RoboticArmAnimator({
</mesh> </mesh>
)} )}
<mesh position={[armBot.position[0], armBot.position[1] + 1.5, armBot.position[2]]} rotation={[-Math.PI / 2, 0, 0]}> <mesh position={[armBot.position[0], armBot.position[1] + 1.5, armBot.position[2]]} rotation={[-Math.PI / 2, 0, 0]}>
<ringGeometry args={[1.59, 1.61, 64]} /> <ringGeometry args={[CIRCLE_RADIUS, CIRCLE_RADIUS + 0.02, 64]} />
<meshBasicMaterial color="green" side={THREE.DoubleSide} /> <meshBasicMaterial color="green" side={THREE.DoubleSide} />
</mesh> </mesh>
</> </>

View File

@ -3,12 +3,11 @@ import IKInstance from '../ikInstance/ikInstance';
import RoboticArmAnimator from '../animator/roboticArmAnimator'; import RoboticArmAnimator from '../animator/roboticArmAnimator';
import { usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; import { usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore';
import { useArmBotStore } from '../../../../../store/simulation/useArmBotStore'; import { useArmBotStore } from '../../../../../store/simulation/useArmBotStore';
import armModel from "../../../../../assets/gltf-glb/rigged/ik_arm_4.glb"; import armModel from "../../../../../assets/gltf-glb/rigged/ik_arm_1.glb";
import { useThree } from "@react-three/fiber"; import { useThree } from "@react-three/fiber";
import useModuleStore from '../../../../../store/useModuleStore'; import useModuleStore from '../../../../../store/useModuleStore';
import * as THREE from "three"; import * as THREE from "three";
import { useSelectedAction, useSelectedProduct } from '../../../../../store/simulation/useSimulationStore'; import MaterialAnimator from '../animator/materialAnimator';
import { useProductStore } from '../../../../../store/simulation/useProductStore';
function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
@ -25,13 +24,11 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
let startTime: number; let startTime: number;
//zustand //zustand
const { addCurrentAction, setArmBotActive, setArmBotState, removeCurrentAction } = useArmBotStore(); const { addCurrentAction, setArmBotActive, setArmBotState, removeCurrentAction } = useArmBotStore();
const { getActionByUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { isReset, setReset } = useResetButtonStore(); const { isReset, setReset } = useResetButtonStore();
const { isPaused } = usePauseButtonStore(); const { isPaused } = usePauseButtonStore();
const { selectedAction } = useSelectedAction();
function firstFrame() { function firstFrame() {
startTime = performance.now(); startTime = performance.now();
@ -114,7 +111,6 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.") logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.")
} }
} }
// setReset(false);
} }
}, [isReset, isPlaying]) }, [isReset, isPlaying])
@ -123,13 +119,10 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
if (targetMesh) { if (targetMesh) {
targetMesh.visible = activeModule !== "simulation" targetMesh.visible = activeModule !== "simulation"
} }
const targetBones = ikSolver?.mesh.skeleton.bones.find( const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
(b: any) => b.name === targetBone
);
if (isPlaying) { if (isPlaying) {
//Moving armBot from initial point to rest position. //Moving armBot from initial point to rest position.
if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "init") { if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "init") {
setArmBotActive(armBot.modelUuid, true) setArmBotActive(armBot.modelUuid, true)
setArmBotState(armBot.modelUuid, "running") setArmBotState(armBot.modelUuid, "running")
setCurrentPhase("init-to-rest"); setCurrentPhase("init-to-rest");
@ -167,52 +160,10 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
} }
else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "picking" && armBot.currentAction) { else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "picking" && armBot.currentAction) {
requestAnimationFrame(firstFrame); requestAnimationFrame(firstFrame);
// setArmBotActive(armBot.modelUuid, true);
// setArmBotState(armBot.modelUuid, "running");
// setCurrentPhase("start-to-end");
// const startPoint = armBot.point.actions[0].process.startPoint;
// const endPoint = armBot.point.actions[0].process.endPoint;
// if (startPoint && endPoint) {
// let curve = createCurveBetweenTwoPoints(
// new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2]),
// new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]));
// if (curve) {
// setTimeout(() => {
// logStatus(armBot.modelUuid, "picking the object");
// setPath(curve.points.map(point => [point.x, point.y, point.z]));
// }, 1500)
// }
// }
// logStatus(armBot.modelUuid, "Moving armBot from start point to end position.")
} }
else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "dropping" && armBot.currentAction) { else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "dropping" && armBot.currentAction) {
requestAnimationFrame(firstFrame); requestAnimationFrame(firstFrame);
// setArmBotActive(armBot.modelUuid, true);
// setArmBotState(armBot.modelUuid, "running");
// setCurrentPhase("end-to-rest");
// const endPoint = armBot.point.actions[0].process.endPoint;
// if (endPoint) {
// let curve = createCurveBetweenTwoPoints(new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]), restPosition);
// if (curve) {
// setTimeout(() => {
// logStatus(armBot.modelUuid, "dropping the object");
// setPath(curve.points.map(point => [point.x, point.y, point.z]));
// }, 1500)
// }
// }
// logStatus(armBot.modelUuid, "Moving armBot from end point to rest position.")
} }
} else {
// logStatus(armBot.modelUuid, "Simulation Play Exited")
// setArmBotActive(armBot.modelUuid, false)
// setArmBotState(armBot.modelUuid, "idle")
// setCurrentPhase("init");
// setPath([])
// isPausedRef.current = false
// pauseTimeRef.current = null
// isPausedRef.current = false
// startTime = 0
// removeCurrentAction(armBot.modelUuid)
} }
}, [currentPhase, armBot, isPlaying, ikSolver]) }, [currentPhase, armBot, isPlaying, ikSolver])
@ -258,10 +209,6 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
} }
} }
const logStatus = (id: string, status: string) => { const logStatus = (id: string, status: string) => {
//
} }
return ( return (
@ -269,6 +216,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
<IKInstance modelUrl={armModel} setIkSolver={setIkSolver} ikSolver={ikSolver} armBot={armBot} groupRef={groupRef} /> <IKInstance modelUrl={armModel} setIkSolver={setIkSolver} ikSolver={ikSolver} armBot={armBot} groupRef={groupRef} />
<RoboticArmAnimator HandleCallback={HandleCallback} restPosition={restPosition} ikSolver={ikSolver} targetBone={targetBone} armBot={armBot} <RoboticArmAnimator HandleCallback={HandleCallback} restPosition={restPosition} ikSolver={ikSolver} targetBone={targetBone} armBot={armBot}
logStatus={logStatus} path={path} currentPhase={currentPhase} /> logStatus={logStatus} path={path} currentPhase={currentPhase} />
<MaterialAnimator ikSolver={ikSolver} armBot={armBot} currentPhase={currentPhase} />
</> </>
) )
} }

View File

@ -57,6 +57,12 @@ function IKInstance({ modelUrl, setIkSolver, ikSolver, armBot, groupRef }: IKIns
rotationMin: new THREE.Vector3(0, 0, 0), rotationMin: new THREE.Vector3(0, 0, 0),
rotationMax: new THREE.Vector3(2, 0, 0), rotationMax: new THREE.Vector3(2, 0, 0),
}, },
// {
// index: 1,
// enabled: true,
// rotationMin: new THREE.Vector3(0, -Math.PI, 0),
// rotationMax: new THREE.Vector3(0, Math.PI, 0),
// },
{ index: 1, enabled: true, limitation: new THREE.Vector3(0, 1, 0) }, { index: 1, enabled: true, limitation: new THREE.Vector3(0, 1, 0) },
{ index: 0, enabled: false, limitation: new THREE.Vector3(0, 0, 0) }, { index: 0, enabled: false, limitation: new THREE.Vector3(0, 0, 0) },
], ],

View File

@ -138,7 +138,7 @@ export default function useDraggableGLTF(onUpdate: OnUpdateCallback) {
targetPosition.x = centerX + Math.cos(angle) * clampedDistance; targetPosition.x = centerX + Math.cos(angle) * clampedDistance;
targetPosition.z = centerZ + Math.sin(angle) * clampedDistance; targetPosition.z = centerZ + Math.sin(angle) * clampedDistance;
} }
targetPosition.y = Math.min(Math.max(targetPosition.y, 0.6), 1.5); targetPosition.y = Math.min(Math.max(targetPosition.y, 0.6), 1.9);
// Convert world position to local if object is nested inside a parent // Convert world position to local if object is nested inside a parent
if (parent) { if (parent) {
parent.worldToLocal(targetPosition); parent.worldToLocal(targetPosition);