Closed4

アニメーション作成記録

masterakmasterak

TODO

  • Next.js プロジェクトの作成
  • アニメーションモデル
  • FBXのロード
  • FBXのアニメーションを実行
  • T-pose モデルに、アニメーションをブレンドする
  • 複数アニメーションを登録する
  • ボタンを追加して、アニメーションの切り替えを行う
  • 段階的にデータをロードする

FIX

  • GET500エラー

参考サイト

masterakmasterak

Three.js

FBXモデルのロード

import { FBXLoader } from 'three/examples/jsm/Addons.js';
...省略...
const fbxloader: FBXLoader = new FBXLoader();
fbxloader_thinking.load('models/example.fbx', (fbx) => {
  fbx_model_thinking = fbx;
  scene.add(fbx_model_thinking);
  fbx_model_thinking.position.set(0, 0, 0);
  fbx_model_thinking.scale.set(1, 1, 1);
});

FBX アニメーションの実行

//model loader
const fbxloader: FBXLoader = new FBXLoader();
let mixer: THREE.AnimationMixer;
fbxloader.load('models/Samba Dancing.fbx', (object) => {
  
  object.position.set(0, 0, 0);
  object.scale.set(.05,.05,.05);
  mixer = new THREE.AnimationMixer(object);
  const action = mixer.clipAction( object.animations[ 0 ] );
  action.play();

  scene.add(object);

});

T-pose モデルにアニメーションをブレンドする。

const fbxloader: FBXLoader = new FBXLoader();
    let mixer: THREE.AnimationMixer;
    fbxloader.load('models/vanguard_t_choonyung.fbx', (object) => {
      
      object.position.set(0, 0, 0);
      object.scale.set(.05,.05,.05);
      const anim = new FBXLoader();
      anim.load('models/Vanguard@Sitting.fbx', (anim) => {
        mixer = new THREE.AnimationMixer(object);
        const action = mixer.clipAction(anim.animations[0]);
        action.play();
      });

      scene.add(object);

公式サンプルを確認すると、すでにアニメーションが登録されているモデルがほとんどっぽい?

複数モーションの登録

const animationActions: THREE.AnimationAction[] = []; // ここにアニメーションを追加していく
const fbxloader: FBXLoader = new FBXLoader();
let mixer: THREE.AnimationMixer;
let activeAction: THREE.AnimationAction;
let lastAction: THREE.AnimationAction;

fbxloader.load('/models/Vanguard.fbx', (object) => {
  
  object.position.set(0, 0, 0);
  object.scale.set(.05,.05,.05);
  mixer = new THREE.AnimationMixer(object);

  const animationAction_tpose = mixer.clipAction(object.animations[0]); //t-pose action
  animationActions.push(animationAction_tpose);
  
  const anim_sitting = new FBXLoader();
  anim_sitting.load('/models/Sitting.fbx', (anim: THREE.Group<THREE.Object3DEventMap>) => {
    const animationAction_Sit = mixer.clipAction(anim.animations[0]); //sitting action
    animationActions.push(animationAction_Sit);

    const anim_running = new FBXLoader();
    anim_running.load('/models/Running.fbx', (anim: THREE.Group<THREE.Object3DEventMap>) => {
      anim.animations[0].tracks.shift(); //走行中にオブジェクトを前進させる特定のトラックを削除する。
      const animationAction_Run = mixer.clipAction(anim.animations[0]); //running action
      animationActions.push(animationAction_Run);

      activeAction = animationActions[0]; 
      lastAction = animationActions[0];
    },
    (error) => {
        console.log(error, 'failed to Load Run');
    });
  },
  (error) => {
      console.log(error, 'failed to Load Sit');
  });
  
  scene.add(object);

},
(error) => {
    console.log(error, 'failed to Load Model');
});

ボタンにアクションを紐づけする

return (
    <main className='h-screen'>
      <canvas ref={ref}/>
      <button onClick={animations.default} className='mx-4 my-2'>TPose</button>
      <button onClick={animations.sit} className='mx-4 my-2'>Sitting</button>
      <button onClick={animations.run} className='mx-4 my-2'>Running</button>
    </main>
  );

const animations = {
  default: function () {
      setAction(animationActions[0])
  },
  sit: function () {
      setAction(animationActions[1])
  },
  run: function () {
      setAction(animationActions[2])
  },
}

const setAction = (toAction: THREE.AnimationAction) => {
  if (toAction != activeAction) {
      lastAction = activeAction
      activeAction = toAction
      lastAction.stop()
      activeAction.reset()
      activeAction.play()
  }
}
masterakmasterak

Next.js+Three.js TypeError: Failed to parse URL from /models/xxx.fbx

 ⨯ TypeError: Failed to parse URL from /models/Vanguard.fbx
    at eval (./app/page.tsx:105:11)
    at (ssr)/./app/page.tsx (/workspaces/typescript-node/model_description/.next/server/app/page.js:140:1)
    at Object.__webpack_require__ [as require] (/workspaces/typescript-node/model_description/.next/server/webpack-runtime.js:33:42)
    at JSON.parse (<anonymous>)
digest: "3080107415"
Cause: TypeError: Invalid URL
    at new URL (node:internal/url:796:36)
    at new Request (node:internal/deps/undici/undici:6108:25)
    at FileLoader.load (webpack-internal:///(ssr)/./node_modules/three/build/three.module.js:43846:15)
    at FBXLoader.load (webpack-internal:///(ssr)/./node_modules/three/examples/jsm/loaders/FBXLoader.js:52:10)
    at eval (webpack-internal:///(ssr)/./app/page.tsx:105:11)
    at (ssr)/./app/page.tsx (/workspaces/typescript-node/model_description/.next/server/app/page.js:140:1)
    at Object.__webpack_require__ [as require] (/workspaces/typescript-node/model_description/.next/server/webpack-runtime.js:33:42)
    at require (/workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:39:19604)
    at /workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:108279
    at eo (/workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:108464)
    at /workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:110693
    at Object._fromJSON (/workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:111249)
    at JSON.parse (<anonymous>)
    at eu (/workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:108958)
    at en (/workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:108026)
    at /workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:115168
    at /workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:115185
    at /workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:115218
    at /workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:115235
    at t (/workspaces/typescript-node/model_description/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:35:115458) {
  code: 'ERR_INVALID_URL',
  input: '/models/Vanguard.fbx'
}
 GET / 500 in 107ms

-> モデルのロードをSSRでレンダリングする際に、発生する模様。
-> Dynamic importなるもので、解決できるらしい?
-> 応急処置として、useEffectの中に、モデルロードを突っ込んでみる。
-> エラーは発生しなくなったが、イベントを起こした時に、表示がバグってしまう。
-> 最近、またNext.jsのキャッシュ周りが変更されるらしいので、この辺りは静観

masterakmasterak

useEffectによるモデルロードの制御

発火タイミング
useEffect(setup, dependencies?)
setup : 処理の内容
dependencies : 監視する値

dependencisに設定できる
レンダリングする際に毎回更新する。

useEffect(() => {
        なんか処理する。
    });

画面生成時に一回だけ実行する。

useEffect(() => {
        なんか処理する。
    }, []);

監視対象の値がレンダリングされた場合に更新される。

useEffect(() => {
        なんか処理する。
    }, [value]);
このスクラップは5ヶ月前にクローズされました