「ユーザーブロマガ」サービスの終了(10月7日を予定)にあたり、残したいユーザーブロマガ記事への投票を受け付けています

  • PMDEプラグインの作り方 ボーン操作編3

    2013-03-12 16:32

    PMDEプラグインの作り方 ボーン操作編3

    プラグインとはいえ普通にC#なので記述の仕方はいろいろありますが、わかりやすくするために記述方法に制限をかけています。必ずこのやり方でないといけないわけではありませんのでご注意ください。

    前回と同様にこのサンプルプラグインプロジェクトファイル(http://bowlroll.net/up/dl15339)を元に説明しますので必ずDLしてください。
    この中にはボーン操作に必要な機能をあらかじめ入れてあります。説明もそれに沿った形で説明します。また、このプロジェクトファイルの内容を流用してプラグインを作成することは問題ありません。
    以下ボーン操作とそのコードを記述します。前回と同様にサンプルプロジェクトファイルにこぴぺすれば動作すると思います。


    1.実際にボーンを操作してみよう
    ・回転ボーンにする
    頭ボーンを回転ボーンにする
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    HeadBone.IsRotation = true;
    HeadBone.IsTranslation = false;

    ・移動ボーンにする
    頭ボーンを移動ボーンにする
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    HeadBone.IsRotation = false;
    HeadBone.IsTranslation = true;

    ・回転移動ボーンにする
    頭ボーンを回転移動ボーンにする

    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    HeadBone.IsRotation = true;
    HeadBone.IsTranslation = true;

    ・表示先をボーンにする。
    頭ボーンの表示先を首ボーンにする(ToOffSetを初期化しないといけません。)
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    IPXBone NeckBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("首")];
    HeadBone.ToBone = NeckBone;
    HeadBone.ToOffset = new V3(0.0f, 0.0f, 0.0f);

    サンプルプロジェクトの機能を利用する場合は
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];

    IPXBone NeckBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("首")];
    this.SetToBone(HeadBone, NeckBone);

    ・表示先を相対にする。
    頭ボーンの表示先を相対位置にする(ToBoneをnullで初期化しないといけません)
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    IPXBone NeckBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("首")];
    HeadBone.ToBone = null;
    HeadBone.ToOffset = new V3(1.0f, 0.0f, 0.0f);

    サンプルプロジェクトの機能を利用する場合は
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    IPXBone NeckBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("首")];
    this.SetToOffset(HeadBone,new V3(1.0f,0.0f,0.0f));

    ・ローカル軸を設定する
    ローカル軸の取得は若干込み入った計算が必要なので機能を利用したほうがいいです。
    (SetLocalAxisの部分のコードはうにさん(http://www.nicovideo.jp/user/7939259)にいただきました。)
    通常はこちら。
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")]; this.SetLocalAxis(HeadBone);

    MMDの場合操作性のために左肩・左腕・左ひじ・左手首・左各指のLocal軸はスタンダードな向きではありません。 そちらにあわせるのがこの機能です。
    IPXBone LeftArmBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("左腕")];
    this.SetLocalAxis4MMDEx(LeftArmBone);

    ・IKの作成
    頭先をIKターゲットにし頭と首をIKで動かします。
    IKの作成の場合はIKLinkの追加順に意味がありますので気をつけてください。

    //ターゲットボーンとして頭先を取得
    IPXBone HeadPointBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭先")];

    //頭・首ボーンを取得
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];

    IPXBone NeckBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("首")];
    //IKボーンを頭先の情報を利用して作成
    IPXBone HeadIKBone = (IPXBone)HeadPointBone.Clone();


    //IKターゲットの設定
    //コード内はラジアンでPMDE上の表記は度数なので気をつけること。
    HeadIKBone.IsIK = true;

    HeadIKBone.IK.Angle = 1.0f;
    HeadIKBone.IK.LoopCount = 20;
    HeadIKBone.IK.Target = HeadPointBone;
    //IK-Linkボーンの設定
    IPXIKLink HeadIKLink = (IPXIKLink)PEStaticBuilder.Pmx.IKLink();
    IPXIKLink NeckIKLink = (IPXIKLink)PEStaticBuilder.Pmx.IKLink();
    HeadIKLink.Bone = HeadBone;
    NeckIKLink.Bone = NeckBone;
    HeadIKBone.IK.Links.Add(NeckIKLink);

    HeadIKBone.IK.Links.Add(HeadIKLink);
    //IKボーンの追加 頭先の一つ上にIKボーンを追加する。
    this.UpperInsertBone(HeadIKBone, HeadPointBone);

    サンプルプロジェクトの機能を利用する場合は
    //ターゲットボーンとして頭先を取得
    IPXBone HeadPointBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭先")];
    //頭・首ボーンを取得
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];

    IPXBone NeckBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("首")];
    //IKボーンを頭先の情報を利用して作成
    IPXBone HeadIKBone = (IPXBone)HeadPointBone.Clone();


    //IKターゲットの設定
    this.AddIK(HeadIKBone, HeadPointBone);
    //IK-Linkボーンの設定(角度制限を行う場合はAddIKLinkLimitを使用します。)
    this.AddIKLink(HeadIKBone, NeckBone);
    this.AddIKLink(HeadIKBone, HeadBone);
    //IKボーンの追加 頭先の一つ上にIKボーンを追加する。

    this.UpperInsertBone(HeadIKBone, HeadPointBone);


    次は腕IK・足IKのサンプルコードを記述します。


  • 広告
  • PMDEプラグインの作り方 ボーン操作編2

    2013-03-10 12:06
    PMDEプラグインの作り方 ボーン操作編2

    プラグインとはいえ普通にC#なので記述の仕方はいろいろありますが、わかりやすくするために記述方法に制限をかけています。必ずこのやり方でないといけないわけではありませんのでご注意ください。

    前回は簡単な操作の説明をしましたが、実際記述していくと「行いたい操作」と「実行する内容」にかなりの感覚的差異ができます。そこを説明するとかなり面倒なのであらかじめボーン操作に必要な機能を入れたサンプルプロジェクトファイルを作成しました。
    まず最初にサンプルプラグインプロジェクトファイル(http://bowlroll.net/up/dl15339)をDLしてください。
    この中にはボーン操作に必要な機能をあらかじめ入れてあります。説明もそれに沿った形で説明します。また、このプロジェクトファイルの内容を流用してプラグインを作成することは問題ありません。

    1.プロジェクトファイルを開く
    DLしたファイルを
    「ドキュメント」→「Visual Studio 2010」→「Projects」
    に解凍して下さい。(解凍の仕方等については説明しません。)

    画面左上の「ファイル」→「プロジェクトを開く」をクリック


    正常にコピーされていればBoneSampleというフォルダがありますのでそこをクリック


    「BoneSample.sln」というファイルがありますのでそれを開いてください。


    プロジェクトが開きます。



    2.ボーンから取得できる情報
    前回は文字だけの説明でしたのでまずPMDEの画面とボーンオブジェクトから取得できる情報の対応を絵に起こしてみました。

    このような値がボーンオブジェクト(this.PMX.Bone[i]と記述されているもの)から取得することが出来ます。
    この中でローカル軸については操作が特殊ですのでこちらも別途説明します。

    3.3次元表記について
    MMDは3Dソフトですので3次元空間表記とは仲良しにならなければなりません。(まだなれてませんけど!!!w)
    まず、ボーンではPosition/ToOffset/FixAxisについては3次元表記となっています。

    3次元表記は
    V3 Position = new V3(0.0f,0.0f,0.0f);
    この様に定義します。
    この中からそれぞれの値を取り出す時は
    Position.X
    Position.Y
    Position.Z
    このようにして取り出す事が出来ます。

    使用方法としては以下のように使います。
    例)ボーンの場所を変更する。
    IPXBone Bone =(IPXBone)this.PMX.Bone[0];
    Bone.Position = new V3(0.0f,0.0f,0.0f);
    もしくは
    IPXBone Bone =(IPXBone)this.PMX.Bone[0];
    V3 NewPosition = new V3(0.0f,0.0f,0.0f);

    Bone.Position = NewPosition;
    この操作でBoneIndex0のボーンの座標を原点にできます。

    4.実際にボーンを操作してみよう
    ここから実際に操作してみます。
    開いたプロジェクトファイルに
    //-------------------------
    //ここから処理開始
    //-------------------------
    ここにサンプルをコピペする
    //-------------------------
    //処理ここまで
    //-------------------------
    と記述されている部分の間に処理をコピペすると動作するようにサンプルは記述していきます。

    なお、プロジェクトからプラグインの作成方法は前々回説明してありますので割愛します。(http://ch.nicovideo.jp/t0r0/blomaga/ar151387

    ・ボーンIndexを取得しよう
    「頭」ボーンのボーンIndexを取得します。(GetBoneIndexという機能でBoneIndexを取得します。)
    MessageBox.Show(this.GetBoneIndex("頭").ToString());

    ・ボーンの名前を変更しよう
    「頭」ボーンの名称を「頭頭」に変更してみます。(RenameBoneという機能で名称を変更します。)
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    HeadBone.Name="頭頭";

    もしくは

    this.RenameBone("頭","頭頭");

    ・ボーンの位置を変更しよう
    「頭」ボーンの位置を原点に変更してみます。
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    HeadBone.Position=new V3(0.0f,0.0f,0.0f);

    ・ボーンを回転連動にしよう
    「頭」ボーンの動きに首を連動させよう(SetAppendRotationという部分が回転連動に必要な設定を一気に行っています。)
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    IPXBone NeckBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("首")];
    NeckBone.AppendParent = HeadBone;
    NeckBone.AppendRatio = 0.3f;
    NeckBone.IsAppendRotation = true;
    NeckBone.IsAppendTranslation = false;

    もしくは
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    IPXBone NeckBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("首")];
    this.SetAppendRotation(NeckBone, HeadBone, 0.3f);


    ・ボーンをコピーしよう(ボーンの親子関係を調整してないので多段にはなりません。)
    頭ボーンのコピーを作成します。(this.CloneBoneという機能がコピーする際に必要な動作を行っています。)
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    IPXBone CloneHeadBone = (IPXBone)HeadBone.Clone();
    this.PMX.Bone.Add(CloneHeadBone);

    もしくは
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    IPXBone CloneHeadBone = (IPXBone)this.CloneBone(HeadBone);
    this.PMX.Bone.Add(CloneHeadBone);

    ・ボーンを非表示にしよう
    頭ボーンを非表示にします
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    HeadBone.Visible= false;
    HeadBone.Controllable=false;

    ・ボーンに軸制限をかけよう
    頭ボーンをX軸方向にしか動かないようにします。(SetFixAxisの部分が軸制限に必要な操作を行っています。)
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    HeadBone.IsFixAxis = true;
    HeadBone.FixAxis = new V3(1.0f, 0.0f, 0.0f);

    もしくは
    IPXBone HeadBone = (IPXBone)this.PMX.Bone[this.GetBoneIndex("頭")];
    this.SetFixAxis(HeadBone, "GX");

    長いので次に続きます。
  • PMDEプラグインの作り方 ボーン操作編1

    2013-03-09 23:317
    PMDEプラグインの作り方 ボーン操作編1

    プラグインとはいえ普通にC#なので記述の仕方はいろいろありますが、わかりやすくするために記述方法に制限をかけています。必ずこのやり方でないといけないわけではありませんのでご注意ください。
    まず最初にサンプルプラグインプロジェクトファイル(http://bowlroll.net/up/dl15315)をDLしてください。
    ここ(BoneSample.cs)に最低限必要な記述を書いてあります。

    その内容を説明します。

    1.PMDEditerを操作するために必要な変数の宣言
    BoneSample.csの中に以下のような記述があります。ここはPMDEditerがもっているモデル情報や画面情報を取り出すための入れ物の定義をしています。
    /// <summary>
    /// PMDEditerを操作するために必要な変数群
    /// </summary>
    //-----------------------------------------------------------
    public IPEPluginHost host;
    public IPEBuilder builder;
    public IPEShortBuilder bd;
    public IPEConnector connect;
    public IPEXPmd pex;
    public IPXPmx PMX;
    public IPEPmd PMD;
    public IPEFormConnector Form;
    public IPXPmxViewConnector PMXView;
    public IPEPMDViewConnector PMDView;
    //-----------------------------------------------------------

    2.定義した変数に実際の値を格納します。
    //-----------------------------------------------------------
    //PMD/PMXファイルを操作するためにおまじない。
    this.host = args.Host;
    this.builder = this.host.Builder;
    this.bd = this.host.Builder.SC;
    this.connect = this.host.Connector;
    this.pex = this.connect.Pmd.GetCurrentStateEx();
    this.PMD = this.connect.Pmd.GetCurrentState();
    this.PMX = this.connect.Pmx.GetCurrentState();
    this.Form = this.connect.Form;
    this.PMDView = this.connect.View.PMDView;
    //-----------------------------------------------------------
    この部分が定義した変数に実際の値を格納しています。
    この値の中からボーン情報等を取得してきます。

    3.ボーン情報の取得
    サンプル内の上の部分がボーン情報の取得サンプルとなります。
    //-----------------------------------------------------------
    //ボーン情報の取得
    //(通常ボーンIndex0はセンターなのでセンターの真下のボーン情報を取得)
    //ウィンドウに文字列を表示します:MessageBox.Show
    //文字列の結合は「+」で表記します。
    //改行の意味:System.Environment.NewLine
    //値を文字列に変換します:ToString()
    //-----------------------------------------------------------
    //以下の様な形でボーンの情報が取得できます。
    文字列「ret」の中にボーン名・ボーン位置・親ボーンの名前を取得してウィンドウに表示しています。

    string ret = "";

    ret += "ボーン名:" + this.PMX.Bone[1].Name + System.Environment.NewLine;

    ret += "ボーン英語名:" + this.PMX.Bone[1].NameE + System.Environment.NewLine;

    ret += "ボーン位置:" + "("
    + this.PMX.Bone[1].Position.X.ToString() + ","
    + this.PMX.Bone[1].Position.Y.ToString() + ","
    + this.PMX.Bone[1].Position.Z.ToString() + ")" + System.Environment.NewLine;

    ret += "親ボーン:" + this.PMX.Bone[1].Parent.Name + System.Environment.NewLine;
    //ウィンドウに文字列「ret」を表示します。
    MessageBox.Show(ret);
    //-----------------------------------------------------------

    4.ボーンIndexの取得
    PMDEditer内ではボーン・モーフ・頂点に番号がついており、またその番号に意味があるためこれを取得する操作が基本になります。
    //-----------------------------------------------------------
    //ボーンIndex番号の取得
    //ボーン数:this.PMX.Bone.Count
    //-----------------------------------------------------------
    //頭という名称のボーンを探してそのボーンIndexを取得する。
    for (int i = 0; i < this.PMX.Bone.Count; i++)
    {
    if (this.PMX.Bone[i].Name == "頭")
    {
    MessageBox.Show("ボーンIndex:" + i.ToString());
    }
    }

    この操作はボーンIndex0からボーン数までボーンの名前が「頭」のものを探して最初に見つかったIndex番号をウィンドウに表示します。
    この操作はよく使うので以下のような関数にしておくと便利です。

    /// <summary>
    /// ボーンIndexを返す関数です。
    /// </summary>
    /// <param name="BoneName">ボーン名</param>
    /// <returns>ボーンIndex</returns>
    public int GetBoneIndex(string BoneName)
    {
    for (int i = 0; i < this.PMX.Bone.Count; i++)
    {
    if (this.PMX.Bone[i].Name == BoneName)
    {
    return i;
    }
    }
    return -1;
    }

    5.ボーンの追加方法
    以下の手続きでボーンを追加します。
    //-----------------------------------------------------------
    //ボーンの追加方法
    //-----------------------------------------------------------
    //ボーンオブジェクトを生成
    IPXBone AddBone = (IPXBone)PEStaticBuilder.Pmx.Bone();
    //ボーンの情報を設定
    AddBone.Name = "追加ボーン";
    AddBone.Position = new V3(0.0f, 1.0f, 0.0f);
    AddBone.Parent = (IPXBone)this.PMX.Bone[0];
    //ボーン追加
    //単純に追加する場合はこちら
    this.PMX.Bone.Add(AddBone);
    //あるボーンIndex(BoneIndex)の上にAddBoneを追加したい場合はこちら
    this.PMX.Bone.Insert(BoneIndex,AddBone)
    //PMXファイルを更新します。
    this.connect.Pmx.Update(this.PMX);
    //-----------------------------------------------------------

    6.ボーン削除方法
    以下の手続きでボーンを削除します。
    //-----------------------------------------------------------
    //ボーンの削除方法(ボーンIndex0のボーン(DelBone)を削除します。)
    //-----------------------------------------------------------
    IPXBone DelBone = (IPXBone)this.PMX.Bone[0];
    this.PMX.Bone.Remove(DelBone);
    //PMXファイルを更新します。
    this.connect.Pmx.Update(this.PMX);
    //-----------------------------------------------------------

    ボーン操作編2に続く・・・。