diff --git a/app/src/assets/gltf-glb/rigged/ik_arm.glb b/app/src/assets/gltf-glb/rigged/ik_arm.glb deleted file mode 100644 index 22e26a8..0000000 Binary files a/app/src/assets/gltf-glb/rigged/ik_arm.glb and /dev/null differ diff --git a/app/src/assets/gltf-glb/rigged/ik_arm_1.glb b/app/src/assets/gltf-glb/rigged/ik_arm_1.glb deleted file mode 100644 index 326efad..0000000 Binary files a/app/src/assets/gltf-glb/rigged/ik_arm_1.glb and /dev/null differ diff --git a/app/src/assets/gltf-glb/rigged/ik_arm_4.glb b/app/src/assets/gltf-glb/rigged/ik_arm_4.glb deleted file mode 100644 index 92ea5f6..0000000 Binary files a/app/src/assets/gltf-glb/rigged/ik_arm_4.glb and /dev/null differ diff --git a/app/src/modules/builder/asset/assetsGroup.tsx b/app/src/modules/builder/asset/assetsGroup.tsx index 547445e..f51edf1 100644 --- a/app/src/modules/builder/asset/assetsGroup.tsx +++ b/app/src/modules/builder/asset/assetsGroup.tsx @@ -4,7 +4,7 @@ import { getFloorAssets } from '../../../services/factoryBuilder/asset/floorAsse import { useLoadingProgress, useRenameModeStore, useSelectedFloorItem, useSelectedItem, useSocketStore } from '../../../store/builder/store'; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; -import { FloorItems, RefGroup, RefMesh } from "../../../types/world/worldTypes"; +import { FloorItems, RefMesh } from "../../../types/world/worldTypes"; import Models from "./models/models"; import useModuleStore from "../../../store/useModuleStore"; import { useThree } from "@react-three/fiber"; diff --git a/app/src/modules/simulation/human/instances/animator/humanAnimator.tsx b/app/src/modules/simulation/human/instances/animator/humanAnimator.tsx index 89d7a82..bb944f6 100644 --- a/app/src/modules/simulation/human/instances/animator/humanAnimator.tsx +++ b/app/src/modules/simulation/human/instances/animator/humanAnimator.tsx @@ -80,7 +80,7 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start const distances = []; let accumulatedDistance = 0; let index = 0; - const rotationSpeed = 1; + const rotationSpeed = 1.5; for (let i = 0; i < currentPath.length - 1; i++) { const start = new THREE.Vector3(...currentPath[i]); @@ -108,7 +108,14 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start if (angle < 0.01) { object.quaternion.copy(targetQuaternion); } else { - object.quaternion.slerp(targetQuaternion, delta * rotationSpeed * speed * human.speed * 5); + const step = rotationSpeed * delta * speed * human.speed; + const angle = object.quaternion.angleTo(targetQuaternion); + + if (angle < step) { + object.quaternion.copy(targetQuaternion); + } else { + object.quaternion.rotateTowards(targetQuaternion, step); + } } const isAligned = angle < 0.01; @@ -145,7 +152,14 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start object.quaternion.copy(targetQuaternion); setRestingRotation(false); } else { - object.quaternion.slerp(targetQuaternion, delta * rotationSpeed * speed * human.speed * 4); + const step = rotationSpeed * delta * speed * human.speed; + const angle = object.quaternion.angleTo(targetQuaternion); + + if (angle < step) { + object.quaternion.copy(targetQuaternion); + } else { + object.quaternion.rotateTowards(targetQuaternion, step); + } } if (human.currentMaterials.length > 0) { diff --git a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx index a9681d6..c382230 100644 --- a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx +++ b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from 'react'; -import { useFrame, useThree } from '@react-three/fiber'; +import { useFrame } from '@react-three/fiber'; import * as THREE from 'three'; import { Line, Text } from '@react-three/drei'; import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; @@ -10,7 +10,6 @@ type PointWithDegree = { }; function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone, armBot, path }: any) { - const { scene } = useThree(); const progressRef = useRef(0); const curveRef = useRef(null); const totalDistanceRef = useRef(0); @@ -202,11 +201,7 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone }, [circlePoints, currentPath]); // Frame update for animation - useFrame((state, delta) => { - const targetMesh = scene?.getObjectByProperty("uuid", armBot.modelUuid); - if (targetMesh) { - targetMesh.visible = (!isPlaying) - } + useFrame((_, delta) => { if (!ikSolver) return; const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone); diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx index 5a2d724..db8cda2 100644 --- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx @@ -1,10 +1,8 @@ import { useEffect, useRef, useState } from 'react' import * as THREE from "three"; -import { useThree } from "@react-three/fiber"; import IKInstance from '../ikInstance/ikInstance'; import RoboticArmAnimator from '../animator/roboticArmAnimator'; import MaterialAnimator from '../animator/materialAnimator'; -import armModel from "../../../../../assets/gltf-glb/rigged/ik_arm_1.glb"; import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler'; import { useSceneContext } from '../../../../scene/sceneContext'; @@ -14,17 +12,16 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) { const [currentPhase, setCurrentPhase] = useState<(string)>("init"); const [path, setPath] = useState<[number, number, number][]>([]); const [ikSolver, setIkSolver] = useState(null); - const { scene } = useThree(); const restPosition = new THREE.Vector3(0, 1.75, -1.6); const targetBone = "Target"; - const groupRef = useRef(null); const pauseTimeRef = useRef(null); const isPausedRef = useRef(false); const isSpeedRef = useRef(null); let startTime: number; const { selectedProductStore } = useProductContext(); - const { materialStore, armBotStore, vehicleStore, storageUnitStore, productStore } = useSceneContext(); + const { materialStore, armBotStore, vehicleStore, storageUnitStore, productStore, assetStore } = useSceneContext(); + const { resetAsset } = assetStore(); const { setArmBotActive, setArmBotState, removeCurrentAction, incrementActiveTime, incrementIdleTime } = armBotStore(); const { decrementVehicleLoad, removeLastMaterial } = vehicleStore(); const { removeLastMaterial: removeLastStorageMaterial, updateCurrentLoad } = storageUnitStore(); @@ -190,7 +187,8 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) { setCurrentPhase("init"); setPath([]) setIkSolver(null); - removeCurrentAction(armBot.modelUuid) + removeCurrentAction(armBot.modelUuid); + resetAsset(armBot.modelUuid); isPausedRef.current = false pauseTimeRef.current = null startTime = 0 @@ -266,14 +264,9 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) { } }; - }, [armBot.isActive, armBot.state, currentPhase]) - + }, [armBot, currentPhase, isPlaying]) useEffect(() => { - const targetMesh = scene?.getObjectByProperty("uuid", armBot.modelUuid); - if (targetMesh) { - targetMesh.visible = (!isPlaying) - } const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone); if (!isReset && isPlaying) { //Moving armBot from initial point to rest position. @@ -390,7 +383,7 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) { <> {!isReset && isPlaying && ( <> - + { - const draco = new DRACOLoader(); - draco.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/"); - loader.setDRACOLoader(draco); - }); - const cloned = useMemo(() => clone(gltf?.scene), [gltf]); +function IKInstance({ setIkSolver, armBot }: IKInstanceProps) { + const { scene } = useThree(); + const { isPlaying } = usePlayButtonStore(); + const { isReset } = useResetButtonStore(); const targetBoneName = "Target"; const skinnedMeshName = "link_0"; useEffect(() => { - if (!gltf) return; - const OOI: any = {}; - cloned.traverse((n: any) => { - if (n.name === targetBoneName) OOI.Target_Bone = n; - if (n.name === skinnedMeshName) OOI.Skinned_Mesh = n; - }); - if (!OOI.Target_Bone || !OOI.Skinned_Mesh) return; - const iks = [ - { - target: 7, - effector: 6, - links: [ - { - index: 5, - enabled: true, - rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0), - rotationMax: new THREE.Vector3(Math.PI / 2, 0, 0), - }, - { - index: 4, - enabled: true, - rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0), - rotationMax: new THREE.Vector3(0, 0, 0), - }, - { - index: 3, - enabled: true, - rotationMin: new THREE.Vector3(0, 0, 0), - rotationMax: new THREE.Vector3(2, 0, 0), - }, - { index: 1, enabled: true, limitation: new THREE.Vector3(0, 1, 0) }, - { index: 0, enabled: false, limitation: new THREE.Vector3(0, 0, 0) }, - ], - }, - ]; + let retryId: NodeJS.Timeout | null = null; - const solver = new CCDIKSolver(OOI.Skinned_Mesh, iks); - setIkSolver(solver); + const trySetup = () => { + const targetMesh = scene?.getObjectByProperty("uuid", armBot.modelUuid); - // const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05) + if (!targetMesh) { + retryId = setTimeout(trySetup, 100); + return; + } - // scene.add(helper); + const OOI: any = {}; + targetMesh.traverse((n: any) => { + if (n.name === targetBoneName) OOI.Target_Bone = n; + if (n.name === skinnedMeshName) OOI.Skinned_Mesh = n; + }); + if (!OOI.Target_Bone || !OOI.Skinned_Mesh) return; + const iks = [ + { + target: 7, + effector: 6, + links: [ + { + index: 5, + enabled: true, + rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0), + rotationMax: new THREE.Vector3(Math.PI / 2, 0, 0), + }, + { + index: 4, + enabled: true, + rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0), + rotationMax: new THREE.Vector3(0, 0, 0), + }, + { + index: 3, + enabled: true, + rotationMin: new THREE.Vector3(0, 0, 0), + rotationMax: new THREE.Vector3(2, 0, 0), + }, + { index: 1, enabled: true, limitation: new THREE.Vector3(0, 1, 0) }, + { index: 0, enabled: false, limitation: new THREE.Vector3(0, 0, 0) }, + ], + }, + ]; - }, [cloned, gltf]); + const solver = new CCDIKSolver(OOI.Skinned_Mesh, iks); + setIkSolver(solver); + + // const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05) + // scene.add(helper); + }; + + trySetup(); + + return () => { + if (retryId) clearTimeout(retryId); + }; + }, [isPlaying, isReset]); return ( - - - + <> + ) } diff --git a/app/src/store/builder/useAssetStore.ts b/app/src/store/builder/useAssetStore.ts index 2223d0a..a72f1e2 100644 --- a/app/src/store/builder/useAssetStore.ts +++ b/app/src/store/builder/useAssetStore.ts @@ -9,6 +9,7 @@ interface AssetsStore { removeAsset: (modelUuid: string) => void; updateAsset: (modelUuid: string, updates: Partial) => void; clearAssets: () => void; + resetAsset: (modelUuid: string) => void; setAssets: (assets: Assets) => void; // Asset properties @@ -74,6 +75,19 @@ export const createAssetStore = () => { }); }, + resetAsset: (modelUuid) => { + const asset = get().assets.find(a => a.modelUuid === modelUuid); + if (asset) { + const clonedAsset = JSON.parse(JSON.stringify(asset)); + setTimeout(() => { + get().removeAsset(asset.modelUuid); + setTimeout(() => { + get().addAsset(clonedAsset); + }, 0); + }, 0); + } + }, + setAssets: (assets) => { set((state) => { state.assets = assets; @@ -185,7 +199,8 @@ export const createAssetStore = () => { asset.animationState.current = ''; asset.animationState.isPlaying = true; asset.animationState.loopAnimation = true; - asset.animationState.isCompleted = true; } + asset.animationState.isCompleted = true; + } }); },