feat: Remove unused GLB models and enhance asset reset functionality
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -4,7 +4,7 @@ import { getFloorAssets } from '../../../services/factoryBuilder/asset/floorAsse
|
|||||||
import { useLoadingProgress, useRenameModeStore, useSelectedFloorItem, useSelectedItem, useSocketStore } from '../../../store/builder/store';
|
import { useLoadingProgress, useRenameModeStore, useSelectedFloorItem, useSelectedItem, useSocketStore } from '../../../store/builder/store';
|
||||||
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
||||||
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
|
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 Models from "./models/models";
|
||||||
import useModuleStore from "../../../store/useModuleStore";
|
import useModuleStore from "../../../store/useModuleStore";
|
||||||
import { useThree } from "@react-three/fiber";
|
import { useThree } from "@react-three/fiber";
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start
|
|||||||
const distances = [];
|
const distances = [];
|
||||||
let accumulatedDistance = 0;
|
let accumulatedDistance = 0;
|
||||||
let index = 0;
|
let index = 0;
|
||||||
const rotationSpeed = 1;
|
const rotationSpeed = 1.5;
|
||||||
|
|
||||||
for (let i = 0; i < currentPath.length - 1; i++) {
|
for (let i = 0; i < currentPath.length - 1; i++) {
|
||||||
const start = new THREE.Vector3(...currentPath[i]);
|
const start = new THREE.Vector3(...currentPath[i]);
|
||||||
@@ -108,7 +108,14 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start
|
|||||||
if (angle < 0.01) {
|
if (angle < 0.01) {
|
||||||
object.quaternion.copy(targetQuaternion);
|
object.quaternion.copy(targetQuaternion);
|
||||||
} else {
|
} 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;
|
const isAligned = angle < 0.01;
|
||||||
@@ -145,7 +152,14 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start
|
|||||||
object.quaternion.copy(targetQuaternion);
|
object.quaternion.copy(targetQuaternion);
|
||||||
setRestingRotation(false);
|
setRestingRotation(false);
|
||||||
} else {
|
} 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) {
|
if (human.currentMaterials.length > 0) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
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 * as THREE from 'three';
|
||||||
import { Line, Text } from '@react-three/drei';
|
import { Line, Text } from '@react-three/drei';
|
||||||
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore';
|
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore';
|
||||||
@@ -10,7 +10,6 @@ type PointWithDegree = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone, armBot, path }: any) {
|
function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone, armBot, path }: any) {
|
||||||
const { scene } = useThree();
|
|
||||||
const progressRef = useRef(0);
|
const progressRef = useRef(0);
|
||||||
const curveRef = useRef<THREE.Vector3[] | null>(null);
|
const curveRef = useRef<THREE.Vector3[] | null>(null);
|
||||||
const totalDistanceRef = useRef(0);
|
const totalDistanceRef = useRef(0);
|
||||||
@@ -202,11 +201,7 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
|
|||||||
}, [circlePoints, currentPath]);
|
}, [circlePoints, currentPath]);
|
||||||
|
|
||||||
// Frame update for animation
|
// Frame update for animation
|
||||||
useFrame((state, delta) => {
|
useFrame((_, delta) => {
|
||||||
const targetMesh = scene?.getObjectByProperty("uuid", armBot.modelUuid);
|
|
||||||
if (targetMesh) {
|
|
||||||
targetMesh.visible = (!isPlaying)
|
|
||||||
}
|
|
||||||
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);
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { useThree } from "@react-three/fiber";
|
|
||||||
import IKInstance from '../ikInstance/ikInstance';
|
import IKInstance from '../ikInstance/ikInstance';
|
||||||
import RoboticArmAnimator from '../animator/roboticArmAnimator';
|
import RoboticArmAnimator from '../animator/roboticArmAnimator';
|
||||||
import MaterialAnimator from '../animator/materialAnimator';
|
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 { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore';
|
||||||
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
|
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
|
||||||
import { useSceneContext } from '../../../../scene/sceneContext';
|
import { useSceneContext } from '../../../../scene/sceneContext';
|
||||||
@@ -14,17 +12,16 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
|
|||||||
const [currentPhase, setCurrentPhase] = useState<(string)>("init");
|
const [currentPhase, setCurrentPhase] = useState<(string)>("init");
|
||||||
const [path, setPath] = useState<[number, number, number][]>([]);
|
const [path, setPath] = useState<[number, number, number][]>([]);
|
||||||
const [ikSolver, setIkSolver] = useState<any>(null);
|
const [ikSolver, setIkSolver] = useState<any>(null);
|
||||||
const { scene } = useThree();
|
|
||||||
const restPosition = new THREE.Vector3(0, 1.75, -1.6);
|
const restPosition = new THREE.Vector3(0, 1.75, -1.6);
|
||||||
const targetBone = "Target";
|
const targetBone = "Target";
|
||||||
const groupRef = useRef<any>(null);
|
|
||||||
const pauseTimeRef = useRef<number | null>(null);
|
const pauseTimeRef = useRef<number | null>(null);
|
||||||
const isPausedRef = useRef<boolean>(false);
|
const isPausedRef = useRef<boolean>(false);
|
||||||
const isSpeedRef = useRef<any>(null);
|
const isSpeedRef = useRef<any>(null);
|
||||||
let startTime: number;
|
let startTime: number;
|
||||||
|
|
||||||
const { selectedProductStore } = useProductContext();
|
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 { setArmBotActive, setArmBotState, removeCurrentAction, incrementActiveTime, incrementIdleTime } = armBotStore();
|
||||||
const { decrementVehicleLoad, removeLastMaterial } = vehicleStore();
|
const { decrementVehicleLoad, removeLastMaterial } = vehicleStore();
|
||||||
const { removeLastMaterial: removeLastStorageMaterial, updateCurrentLoad } = storageUnitStore();
|
const { removeLastMaterial: removeLastStorageMaterial, updateCurrentLoad } = storageUnitStore();
|
||||||
@@ -190,7 +187,8 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
|
|||||||
setCurrentPhase("init");
|
setCurrentPhase("init");
|
||||||
setPath([])
|
setPath([])
|
||||||
setIkSolver(null);
|
setIkSolver(null);
|
||||||
removeCurrentAction(armBot.modelUuid)
|
removeCurrentAction(armBot.modelUuid);
|
||||||
|
resetAsset(armBot.modelUuid);
|
||||||
isPausedRef.current = false
|
isPausedRef.current = false
|
||||||
pauseTimeRef.current = null
|
pauseTimeRef.current = null
|
||||||
startTime = 0
|
startTime = 0
|
||||||
@@ -266,14 +264,9 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}, [armBot.isActive, armBot.state, currentPhase])
|
}, [armBot, currentPhase, isPlaying])
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
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);
|
const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
|
||||||
if (!isReset && isPlaying) {
|
if (!isReset && isPlaying) {
|
||||||
//Moving armBot from initial point to rest position.
|
//Moving armBot from initial point to rest position.
|
||||||
@@ -390,7 +383,7 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
|
|||||||
<>
|
<>
|
||||||
{!isReset && isPlaying && (
|
{!isReset && isPlaying && (
|
||||||
<>
|
<>
|
||||||
<IKInstance modelUrl={armModel} setIkSolver={setIkSolver} armBot={armBot} groupRef={groupRef} />
|
<IKInstance setIkSolver={setIkSolver} armBot={armBot} />
|
||||||
<RoboticArmAnimator
|
<RoboticArmAnimator
|
||||||
HandleCallback={HandleCallback}
|
HandleCallback={HandleCallback}
|
||||||
restPosition={restPosition}
|
restPosition={restPosition}
|
||||||
|
|||||||
@@ -1,83 +1,84 @@
|
|||||||
import { useEffect, useMemo } from 'react'
|
import { useEffect } from 'react'
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
|
import { useThree } from "@react-three/fiber";
|
||||||
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
|
||||||
import { clone } from "three/examples/jsm/utils/SkeletonUtils";
|
|
||||||
import { useLoader } from "@react-three/fiber";
|
|
||||||
import { CCDIKSolver, CCDIKHelper } from "three/examples/jsm/animation/CCDIKSolver";
|
import { CCDIKSolver, CCDIKHelper } from "three/examples/jsm/animation/CCDIKSolver";
|
||||||
|
import { usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore';
|
||||||
|
|
||||||
type IKInstanceProps = {
|
type IKInstanceProps = {
|
||||||
modelUrl: string;
|
|
||||||
setIkSolver: any
|
setIkSolver: any
|
||||||
armBot: ArmBotStatus;
|
armBot: ArmBotStatus;
|
||||||
groupRef: any;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function IKInstance({ modelUrl, setIkSolver, armBot, groupRef }: IKInstanceProps) {
|
function IKInstance({ setIkSolver, armBot }: IKInstanceProps) {
|
||||||
const gltf = useLoader(GLTFLoader, modelUrl, (loader) => {
|
const { scene } = useThree();
|
||||||
const draco = new DRACOLoader();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
draco.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/");
|
const { isReset } = useResetButtonStore();
|
||||||
loader.setDRACOLoader(draco);
|
|
||||||
});
|
|
||||||
const cloned = useMemo(() => clone(gltf?.scene), [gltf]);
|
|
||||||
const targetBoneName = "Target";
|
const targetBoneName = "Target";
|
||||||
const skinnedMeshName = "link_0";
|
const skinnedMeshName = "link_0";
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!gltf) return;
|
let retryId: NodeJS.Timeout | null = null;
|
||||||
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) },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const solver = new CCDIKSolver(OOI.Skinned_Mesh, iks);
|
const trySetup = () => {
|
||||||
setIkSolver(solver);
|
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 (
|
return (
|
||||||
<group ref={groupRef} position={armBot.position} rotation={armBot.rotation}>
|
<>
|
||||||
<primitive
|
</>
|
||||||
uuid={`${armBot.modelUuid}_IK`}
|
|
||||||
object={cloned}
|
|
||||||
scale={[1, 1, 1]}
|
|
||||||
name={armBot.modelName}
|
|
||||||
/>
|
|
||||||
</group>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ interface AssetsStore {
|
|||||||
removeAsset: (modelUuid: string) => void;
|
removeAsset: (modelUuid: string) => void;
|
||||||
updateAsset: (modelUuid: string, updates: Partial<Asset>) => void;
|
updateAsset: (modelUuid: string, updates: Partial<Asset>) => void;
|
||||||
clearAssets: () => void;
|
clearAssets: () => void;
|
||||||
|
resetAsset: (modelUuid: string) => void;
|
||||||
setAssets: (assets: Assets) => void;
|
setAssets: (assets: Assets) => void;
|
||||||
|
|
||||||
// Asset properties
|
// 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) => {
|
setAssets: (assets) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.assets = assets;
|
state.assets = assets;
|
||||||
@@ -185,7 +199,8 @@ export const createAssetStore = () => {
|
|||||||
asset.animationState.current = '';
|
asset.animationState.current = '';
|
||||||
asset.animationState.isPlaying = true;
|
asset.animationState.isPlaying = true;
|
||||||
asset.animationState.loopAnimation = true;
|
asset.animationState.loopAnimation = true;
|
||||||
asset.animationState.isCompleted = true; }
|
asset.animationState.isCompleted = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user