Skip to content

Commit

Permalink
extract useAnimation from motion-file-mode of camera
Browse files Browse the repository at this point in the history
  • Loading branch information
culdo committed Jan 5, 2025
1 parent 5e107b6 commit f3262b8
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 46 deletions.
36 changes: 36 additions & 0 deletions app/components/three-world/animation/useAnimation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import useGlobalStore from "@/app/stores/useGlobalStore";
import usePresetStore from "@/app/stores/usePresetStore";
import { onProgress } from "@/app/utils/base";
import { useFrame } from "@react-three/fiber";
import { use, useEffect } from "react";
import { AnimationMixer, Camera, SkinnedMesh } from "three";

function useAnimation(target: Camera | SkinnedMesh, mixer: AnimationMixer, vmdFile: string, callback?: Function) {
const loader = useGlobalStore(state => state.loader)
const clip = use(loader.loadAnimation(vmdFile, target, onProgress))

const player = useGlobalStore(state => state.player)
const isMotionUpdating = useGlobalStore(state => state.isMotionUpdating)

const setTime = (currentTime: number) => {
mixer.setTime(currentTime)
callback(currentTime)
}
useEffect(() => {
const savedCurrentTime = usePresetStore.getState().currentTime

const action = mixer.clipAction(clip)
action.play()
if(callback) setTime(savedCurrentTime)
return () => {
mixer.stopAllAction()
mixer.uncacheRoot(target)
}
}, [target, vmdFile, callback])

useFrame(() => {
if (isMotionUpdating.current) setTime(player.currentTime)
}, 1)
}

export default useAnimation;
56 changes: 11 additions & 45 deletions app/components/three-world/camera/helper/motion-file-mode/index.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,23 @@
import useGlobalStore from "@/app/stores/useGlobalStore";
import usePresetStore from "@/app/stores/usePresetStore";
import { onProgress } from "@/app/utils/base";
import { useFrame, useThree } from "@react-three/fiber";
import { Suspense, use, useEffect, useMemo } from "react";
import { AnimationClip, AnimationMixer } from "three";
import { useThree } from "@react-three/fiber";
import { useCallback, useMemo } from "react";
import { AnimationMixer } from "three";
import useAnimation from "../../../animation/useAnimation";
import WithSuspense from "@/app/components/suspense";


function MotionFileMode({ animationPromise }: { animationPromise: Promise<AnimationClip> }) {
const cameraName = usePresetStore(state => state.camera)

const clip = use(animationPromise)

const player = useGlobalStore(state => state.player)
const isMotionUpdating = useGlobalStore(state => state.isMotionUpdating)

function MotionFileMode() {
const camera = useThree(state => state.camera)
const cameraMixer = useMemo(() => new AnimationMixer(camera), [camera])

const setTime = (time: number) => {
cameraMixer.setTime(time)

const cameraFile = usePresetStore(state => state.cameraFile)
const setTimeCb = useCallback(() => {
camera.up.set(0, 1, 0);
camera.up.applyQuaternion(camera.quaternion);
camera.lookAt(camera.getObjectByName("target").position);
camera.updateProjectionMatrix();
}

useEffect(() => {
const savedCurrentTime = usePresetStore.getState().currentTime

const action = cameraMixer.clipAction(clip)
action.play()
setTime(savedCurrentTime)
return () => cameraMixer.stopAllAction() && cameraMixer.uncacheRoot(camera)
}, [camera, cameraName])

useFrame(() => {
if (isMotionUpdating.current) setTime(player.currentTime)
}, 1)
}, [camera, cameraMixer])
useAnimation(camera, cameraMixer, cameraFile, setTimeCb)
return <></>;
}

function SetupMotionFile() {
const cameraFile = usePresetStore(state => state.cameraFile)
const loader = useGlobalStore(state => state.loader)
const camera = useThree(state => state.camera)

const animationPromise = loader.loadAnimation(cameraFile, camera, onProgress)
return (
<Suspense fallback={null}>
<MotionFileMode animationPromise={animationPromise}></MotionFileMode>
</Suspense>
);
}

export default SetupMotionFile;
export default WithSuspense(MotionFileMode);
2 changes: 1 addition & 1 deletion app/components/three-world/camera/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function Camera() {
return (
<>
<PerspectiveCamera ref={cameraRef} fov={fov} near={near} zoom={zoom} position={[0, 10, 50]} makeDefault>
<object3D name="target" userData={{ frameNum: 0 }} />
<object3D name="target" />
</PerspectiveCamera>
<CameraWorkHelper></CameraWorkHelper>
</>
Expand Down

0 comments on commit f3262b8

Please sign in to comment.