import * as THREE from "three"; import { useEffect, useMemo, useRef, useState } from "react"; import { useLoader } from "@react-three/fiber"; import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; import { clone } from "three/examples/jsm/utils/SkeletonUtils"; import { CCDIKSolver, CCDIKHelper, } from "three/examples/jsm/animation/CCDIKSolver"; import IKAnimationController from "./IKAnimationController"; const IkInstances = ({ modelUrl, position, rotation }: { modelUrl: string; position: [number, number, number]; rotation: [number, number, number]; }) => { const [ikSolver, setIkSolver] = useState(null); const [selectedTrigger, setSelectedTrigger] = useState("idle"); const gltf = useLoader(GLTFLoader, modelUrl, (loader) => { 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]); const groupRef = useRef(null); const [selectedArm, setSelectedArm] = useState(); const targetBoneName = "Target"; const skinnedMeshName = "link_0"; const process = useMemo(() => [ { trigger: "Trigger1", start: new THREE.Vector3(-0.75, 1.5, -2.2), end: new THREE.Vector3(0, 1.2, 2.2), speed: 0.25, }, { trigger: "Trigger2", start: new THREE.Vector3(0, 1.2, 2.2), end: new THREE.Vector3(0.75, 1.5, -2.2), speed: 0.22, } ], []); 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) }, ], }, ]; const solver = new CCDIKSolver(OOI.Skinned_Mesh, iks); setIkSolver(solver); const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05); // groupRef.current.add(helper); }, [gltf]); useEffect(() => { const triggers = ['Trigger1', 'Trigger2']; let index = 0; const cycleTriggers = setInterval(() => { setSelectedTrigger(triggers[index]); index = (index + 1) % triggers.length; }, 10000); return () => clearInterval(cycleTriggers); }, []); return ( <> { e.stopPropagation(); setSelectedArm(groupRef.current?.getObjectByName(targetBoneName)) }} > {/* {selectedArm && } */} ); }; export default IkInstances;