3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FinalIK+LeapMotion Core Assets v4.1.1でMMDの指を動かす

Posted at

FinalIK+LeapMotion Core Assets v4.1.1でMMDの指を動かす

えぇ afjkさんの真似です。
LeapMotionのCore Assets v4.1.1になってからなんか色々とnamespaceや関数が微妙に変わってる気がするのですが如何でしょうか?
(気のせいかなぁ。。。ちゃんと調べろと。。。)
めんどくさいのでFinalIKを直接叩いて動かしてしまえーってのが趣旨です。
指を動かす時の手順やパラメータが複雑なのでメモ書きも兼ねてこの記事です。

1.準備

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

こんな感じで継承して作成(かなり適当)

FinalIKOrionLeapHandController.cs
/**
FinalIKを使ったLeapMotion Orion用HandController

Author: MiyuMiyu
*/

using UnityEngine;
using Leap.Unity;
using Leap;
using System.Collections.Generic;
using RootMotion.FinalIK;

public class FinalIKOrionLeapHandController : LeapHandController
{

    [SerializeField]
    private FullBodyBipedIK fullbodyIK;

    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(fullbodyIK == null)
        {
            fullbodyIK = gameObject.transform.root.GetComponent<FullBodyBipedIK>();
        }
        if(fullbodyIK == 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()
    {
        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>();
        }

    }

    void Update()
    {
        if (graphicsEnabled)
        {
            UpdateHandRepresentations();

            if (ikActive)
            {

                if (leftActive && leftHand != null)
                {

                    RiggedHand l = leftHand as RiggedHand;

                    fullbodyIK.solver.leftArmMapping.weight = 1.0f;
                    fullbodyIK.solver.leftArmMapping.maintainRotationWeight = 1.0f;

                    fullbodyIK.solver.leftHandEffector.positionWeight = 1.0f;
                    fullbodyIK.solver.leftHandEffector.rotationWeight = 1.0f;
                    fullbodyIK.solver.leftHandEffector.position = leftHand.GetPalmPosition();
                    fullbodyIK.solver.leftHandEffector.rotation = leftHand.GetPalmRotation() * l.Reorientation();
                    fullbodyIK.solver.leftArmChain.bendConstraint.weight = 1.0f;

                }
                else
                {
                    fullbodyIK.solver.leftArmMapping.weight = 0.0f;
                    fullbodyIK.solver.leftArmMapping.maintainRotationWeight = 0.0f;
                    fullbodyIK.solver.leftHandEffector.positionWeight = 0.0f;
                    fullbodyIK.solver.leftHandEffector.rotationWeight = 0.0f;
                    fullbodyIK.solver.leftArmChain.bendConstraint.weight = 0.0f;
                }

                if (rightActive && rightHand != null)
                {

                    RiggedHand r = rightHand as RiggedHand;

                    fullbodyIK.solver.rightArmMapping.weight = 1.0f;
                    fullbodyIK.solver.rightArmMapping.maintainRotationWeight = 1.0f;
                    fullbodyIK.solver.rightHandEffector.positionWeight = 1.0f;
                    fullbodyIK.solver.rightHandEffector.rotationWeight = 1.0f;
                    fullbodyIK.solver.rightHandEffector.position = rightHand.GetPalmPosition();
                    fullbodyIK.solver.rightHandEffector.rotation = rightHand.GetPalmRotation() * r.Reorientation();
                    fullbodyIK.solver.rightArmChain.bendConstraint.weight = 1.0f;

                }
                else
                {
                    fullbodyIK.solver.rightArmMapping.weight = 0.0f;
                    fullbodyIK.solver.rightArmMapping.maintainRotationWeight = 0.0f;
                    fullbodyIK.solver.rightHandEffector.positionWeight = 0.0f;
                    fullbodyIK.solver.rightHandEffector.rotationWeight = 0.0f;
                    fullbodyIK.solver.rightArmChain.bendConstraint.weight = 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を入れる

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

4.モデルの目(頭のあたり)にLeapMotion関連のスクリプトを置く

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

648a4d1c839e072451c481d406241e5a.png

LeapSpacerのポジションは若干前に出して、ローテションは図の通りになります。
2c2ee76790c5f8fbc553bc1e545a31a7.png

LeapMotionに必要なスクリプト

  • LeapServiceProvider
  • FinalIKOrionLeapHandController(さっき作ったやつ)
    を入れます

63316525f003b5a69476deb0f11f76ae.png

FinalIKOrionLeapHandControllerのAvater Left Hand 、Avatar Right HandにモデルのWristを入れます。

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

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

右手(RightWrist)
b65a78d90b6dbb60336f1e841c35c5cd.png

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

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

左手(RightWrist)
1f38d6c7ff733946118077f5b92088f8.png

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

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

設定完了

これでたぶん動くはず
(アニメーションとかそのあたりの兼ね合いもありますので、動かなかったらごめんなさい)

3
5
0

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
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?