LoginSignup
19
20

More than 5 years have passed since last update.

FinalIK(VRIK)+LeapMotion Core Assets v4.1.4でMMDの指を動かす

Last updated at Posted at 2016-12-12

前回の記事からしばらく時間がたって、LeapMotionのCoreAssetsもバージョンが上がりこの通りやっても動かない上にFinalIKもVRIKという便利なコンポーネントが追加されましたのでこちらを使ってMMDの指を動かすのをやりたいと思います。

こんな感じに指を動かします。

1.準備

2.LeapHandcontrollerでFinalIKを扱えるスクリプトの作成

前回はFullBodyIKコンポーネントを使いましたが今回はVRIKコンポーネントを使います。

FinalIKOrionLeapHandController.cs
/**
FinalIKを使ったLeapMotion Orion用HandController
 (VRIKバージョン)
Author: MiyuMiyu
*/

using UnityEngine;
using Leap.Unity;
using RootMotion.FinalIK;

public class FinalIKOrionLeapHandController : LeapHandController
{
    [SerializeField]
    private VRIK vrIK;

    public bool ikActive = true;
    public bool leftActive = false;
    public bool rightActive = false;

    public GameObject avatarLeftHand;   //keeps track of the left hand gameobject for IK
    public GameObject avatarRightHand;  //keeps track of the right hand gameobject for IK
    [HideInInspector]
    public HandModel leftHand;
    [HideInInspector]
    public HandModel rightHand;

    protected virtual void Awake()
    {
        if (vrIK == null)
        {
            vrIK = gameObject.transform.root.GetComponent<VRIK>();
        }
        if (vrIK == null)
        {
            Debug.LogError("FinalIKOrionLeapHandController:: no FullBodyBipedIK found on GameObject or any of its parent transforms. ");
        }

        if (leftHand == null && avatarLeftHand != null)
            leftHand = avatarLeftHand.GetComponent<RiggedHand>();
        if (rightHand == null && avatarRightHand != null)
            rightHand = avatarRightHand.GetComponent<RiggedHand>();

        if (leftHand == null)
            Debug.LogError("IKOrionLeapHandController::Awake::No Rigged Hand set for left hand parameter. You have to set this in the inspector.");
        if (rightHand == null)
            Debug.LogError("IKOrionLeapHandController::Awake::No Rigged Hand set for right hand parameter. You have to set this in the inspector.");

        // Physic Handは使用しないのでDisableにする
        physicsEnabled = false;
    }

    //    protected override void Start()
    protected virtual void Start()
    {
        provider = GetComponent<LeapProvider>();
        if (provider == null)
        {
            Debug.LogError("IKOrionLeapHandController::Start::No Leap Provider component was present on " + gameObject.name);
            Debug.Log("Added a Leap Service Provider with default settings.");
            gameObject.AddComponent<LeapServiceProvider>();
        }
    }

    public void FixedUpdate()
    {
        if (graphicsEnabled)
        {
            UpdateHandRepresentations();

            if (ikActive)
            {
                if (leftActive && leftHand != null)
                {
                    RiggedHand l = leftHand as RiggedHand;

                    vrIK.solver.leftArm.IKPosition = leftHand.GetPalmPosition();
                    vrIK.solver.leftArm.IKRotation = leftHand.GetPalmRotation() * l.Reorientation();
                    vrIK.solver.leftArm.positionWeight = 1.0f;
                    vrIK.solver.leftArm.rotationWeight = 1.0f;
                }
                else
                {
                    vrIK.solver.leftArm.positionWeight = 0.0f;
                    vrIK.solver.leftArm.rotationWeight = 0.0f;
                }

                if (rightActive && rightHand != null)
                {
                    RiggedHand r = rightHand as RiggedHand;

                    vrIK.solver.rightArm.IKPosition = rightHand.GetPalmPosition();
                    vrIK.solver.rightArm.IKRotation = rightHand.GetPalmRotation() * r.Reorientation();
                    vrIK.solver.rightArm.positionWeight = 1.0f;
                    vrIK.solver.rightArm.rotationWeight = 1.0f;
                }
                else
                {
                    vrIK.solver.rightArm.positionWeight = 0.0f;
                    vrIK.solver.rightArm.rotationWeight = 0.0f;
                }
            }
        }
    }

    /// <summary>
    /// Tells the hands to update to match the new Leap Motion hand frame data. Also keeps track of
    /// which hands are currently active.
    /// </summary>
    void UpdateHandRepresentations()
    {
        leftActive = false;
        rightActive = false;
        foreach (Leap.Hand curHand in provider.CurrentFrame.Hands)
        {
            if (curHand.IsLeft)
            {
                leftHand.SetLeapHand(curHand);
                leftHand.UpdateHand();
                leftActive = true;
            }
            if (curHand.IsRight)
            {
                rightHand.SetLeapHand(curHand);
                rightHand.UpdateHand();
                rightActive = true;
            }
        }
    }
}

3.モデルにFinalIKのVRIKコンポーネントを入れる

モデルにFinalIKのVRIKを入れます
(コンポーネントをそのままドラック&ドロップでOK)
fa1.png

その際に、手を前に出した時に勝手に歩かれると困るのでLocomotionのWeightを0にするのがよろしいかと
fa2.png

4.モデルにLeapMotion関連のスクリプトを置く

LeapMotion関係のコンポーネントを置いていくのですが
ヘッドマウントディスプレイにLeapMotionを置く → モデルのheadあたり
机の上にLeapMotionを置く → モデルのTorso、Torso2あたり

そのあたりに子オブジェクトしてLeapMotion関連のコンポーネントを作成していきます

※今回は机の上にLeapMotionを置く設定となります。

モデルのTorso2の子オブジェクトになるようの空のゲームオブジェクトを作成
そのゲームオブジェクトの名前を【LeapSpacer】という名前にしてその子供にもう一つ空のゲームオブジェクトを作成し名前を【LeapMotion】として、その中に必要なスクリプトを置きます。
(場所の微調整は【LeapSpacer】で行います)

fa3.png

LeapSpacerのポジションは若干前に出して、ローテションはすべて0です。

fa4.png

LeapMotionに必要なスクリプト
- LeapServiceProvider
- FinalIKOrionLeapHandController(さっき作ったやつ)
- HandPool

を入れます

fa5.png

FinalIKOrionLeapHandControllerの設定は
- IK Activeにチェック
- Avatar Left Hand 、Avatar Right Handにモデルに手(Wrist)を入れる

5.モデルの手と指を地道に設定する

モデルの手にRiggedHand、指それぞれにRiggedFingerを入れて設定していきます

右手(RightWrist)
b65a78d90b6dbb60336f1e841c35c5cd.png

右手の指(親指以外)
9602bdb200e1c78bf3488f4d6adffb62.png
(Jointsはいらない。 FingerTypeとElementは指に合わせて適宜変更)

右手の指(親指)
44adcf584dfda15128a6070b6fc22ff6.png

左手(LeftWrist)
1f38d6c7ff733946118077f5b92088f8.png

左手の指(親指以外)
5fb7d6a4da4af70f4f212f4377bf6986.png
(Jointsはいらない。 FingerTypeとElementは指に合わせて適宜変更)

左手の指(親指)
994df4d5485d12e2dfcabc3d63afbcd0.png

設定完了

これでたぶん動くはず
ちゃんと動けばこんな感じに動きます

この例では、頭の位置や回転をWebcamで取得してVRIKに反映させています。
(ついでに表情も)

VRIK使うと色々便利!

19
20
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
20