MRが楽しい

MRやVRについて学習したことを書き残す

SDキャラクターの3Dモデルを作成する その43(VRMファイルに表情とリップシンクの設定する)

本日はSDキャラクターの作成枠です。
SDホロラボちゃんの3Dモデル作成を進めていきます。
今回は VRM ファイルに表情とリップシンクの設定する手順を記事にします。

表情とリップシンクの設定

正規化した VRM ファイルに表情とリップシンクの設定を行います。
VRM ファイルを出力したフォルダに展開された prefab をシーンに配置します。

Inspector ビューを開いて[VRM Blend Shape Proxy]コンポーネントに設定されている[BlendShape]の設定をダブルクリックして開きます。

表情とリップシンクの設定欄が開きます。
各設定項目はそれぞれ以下の表情またはリップシンクの状態を表します。

Neutral:通常時の表情
A:「あ」の発音表情
I:「い」の発音表情
U:「う」の発音表情
E:「え」の発音表情
O:「お」の発音表情
Blink:瞬き(両目)の表情
Joy:喜びの表情
Angry:怒りの表情
Sorrow:悲しみの表情
Fun:楽しみの表情
LookUp:上方向の目線表情
LookDown:下方向の目線表情
LookLeft:左方向の目線表情
LookRight:右方向の目線表情
Blink_L:瞬き(左目)の表情
Blink_R:瞬き(右目)の表情

試しに[Fun(楽しみの表情)]を設定してみます。
[Fun]の項目を選択します。

モデルに設定されているブレンドシェイプの値を調整して[Fun]として登録したい表情を作成します。
同じようにすべての項目を設定して、表情とリップシンクを登録します。

全ての設定を行ったら改めて VRM ファイルを再出力します。
これで VRM ファイルに表情とリップシンクの設定ができました。

SDキャラクターの3Dモデルを作成する その42(VRMファイルを作成する)

本日はSDキャラクターの作成枠です。
SDホロラボちゃんの3Dモデル作成を進めていきます。
今回は VRM ファイルを作成する手順を記事にします。

プロジェクトの作成

新規 Unity プロジェクトを作成します。
UniVRM は Unity 2020.3 以降の環境で利用可能です。


UniVRMのインポート

以下のページから UniVRM-0.108.0_e16d.unitypackage を取得します。
github.com

ダウンロードした unitypackage をプロジェクトにドラッグしてインポートします。

インポートが成功するとメニューに[VRM0]項目が追加されます。

3Dモデルの取り込み

次に VRM ファイルに変換したい3Dモデルをプロジェクトに取り込みます。
今回は FBX 形式の3Dモデルファイルと参照するテクスチャファイルを取り込みました。

Humanoidリグへの変換

取り込んだ3Dモデルを Humanoid モデルに変換します。
3Dモデルを選択して Inspector ビューを開き、[Rig]タグにある[Animation Type]で[Humanoid]を選択します。

[Apply]をクリックして変更を反映します。

Humanoid リグへの変換が成功したか[Configure..]をクリックして確認します。

各ボーンが Humanoid の構造に正しく割り当てられている場合は緑色で表示されます。
赤色で表示されている箇所がある場合は手動でボーン割り当てを直す必要があります。

VRM/MToonの設定(オプション)

マテリアル(質感)に VRM/MToon を設定します。
モデルの見た目を確認するため、3Dモデルをシーンにドラッグして配置します。

3Dモデルを選択して Inspector ビューを開き、[Materials]タブを開きます。
[Extract Materials]のボタンを押して任意のフォルダにマテリアルファイルを作成します。

指定したフォルダにマテリアルファイルが出力されるのでこれを選択して Inspector ビューを開きます。

[Sharder]のプルダウンを開き、[VRM -> MToon]を選択します。

影やアウトラインなどの設定を変更して質感を調整できます。


VRMの出力(正規化)

正規化を行うため、一旦この状態でVRMの出力を行います。
出力するモデルの正面方向は Z 軸方向に正である必要があります。

シーン上の3Dモデルを選択し、メニューから[VRM0 -> Export UniVRM-XXX]をクリックしてファイルを出力します。

[VRM Exporter]のダイアログが開きます。
モデル名やバージョン番号、使用許諾の設定を入力して[Export]を実行します。

ファイルの保存先は以降の更新管理を容易にするため、今回は Assets フォルダ内に指定します。

これで VRM ファイルが出力されます。
またプロジェクト内に出力したので同時に展開が行われ、Meta ファイルが表示されます。

次回記事では VRM ファイルに表情とリップシンクの設定を行います。

SDキャラクターの3Dモデルを作成する その41(FBXファイルを出力する)

本日はSDキャラクターの作成枠です。
SDホロラボちゃんの3Dモデル作成を進めていきます。
今回はFBXファイルを出力します。

FBXファイルを出力する

今回のモデルは最終的に VRM ファイルと UnityPackage を作りたいので Unity に取り込み可能な FBX ファイルで出力します。

モデルデータを FBX ファイルで出力する場合はメニューから[ファイル -> エクスポート -> FBX(.fbx)]を選択します。

ファイルビューが開くので以下の設定を行って[FBXをエクスポート]を実行します。
・オブジェクトタイプの[アーマチュア]と[メッシュ]を選択
・[トランスフォームを適用]をチェック

出力時、メッシュオブジェクトにジオメトリ系のモディファイアが残っていると出力ファイルにシェイプキーが含まれません。
詳細は以下の記事を参照ください。
bluebirdofoz.hatenablog.com

Tips

今回はポリゴン数が少ないので一つのメッシュオブジェクトにオブジェクトを結合しましたが、シェイプキーはオブジェクト内の頂点の位置情報を記録するため、メッシュの頂点数に比例してデータ容量が増加します。
ポリゴン数が大きくなったり、表情のシェイプキーの数が増えた場合は顔メッシュのみ分離するなどしてデータサイズの考慮が必要です。

BlenderでFBX出力したときにシェイプキーが出力されない問題

本日は Blender の小ネタ枠です。
Blender で FBX 出力したときにシェイプキーが出力されないことがあったので記事に残します。

BlenderでFBX出力したときにシェイプキーが出力されない

以下のようなメッシュに幾つかのシェイプキーを登録したモデルを FBX 出力します。

出力したモデルを Unity 上で確認すると BlendShapes の項目が表示されておらず、シェイプキーが出力できていないことが分かります。

原因

シェイプキーを登録したメッシュオブジェクトにジオメトリ操作系のモディファイアが設定されていることが原因でした。

以下のアドオンを利用するなどしてモディファイアを適用した上で FBX 出力を行うと解決します。
bluebirdofoz.hatenablog.com

モディファイアを適用のチェック項目

因みに FBX 出力時に[モディファイアを適用]というチェック項目がありますが、筆者環境ではこのチェックを外しても問題が発生しました。


一方で、ジオメトリ操作系のモディファイアが設定されていなければ本項目がチェックされていてもいなくてもシェイプキーは問題なく出力されます。

SDキャラクターの3Dモデルを作成する その40(メッシュオブジェクトを結合する)

本日はSDキャラクターの作成枠です。
SDホロラボちゃんの3Dモデル作成を進めていきます。
今回はモデル作成の仕上げとしてメッシュオブジェクトを結合します。

メッシュオブジェクトを結合する

オブジェクトが分割されていると描画負荷の原因になるので結合して問題ないオブジェクトは出力前に全て結合しておきます。
各オブジェクトの[モディファイア]タブを開き、ジオメトリ系のモディファイアを適用します。

その後、結合したいオブジェクトを全て選択した状態でメニューから[オブジェクト -> 結合]を実行してオブジェクトを結合します。

仕上げ処理を自動化する

ただしこの作業は不可逆なので保存データは仕上げ処理の前のものを保存しておきたいです。
手直しをするごとに仕上げを手作業で行うのは面倒なので python スクリプトで自動化してみました。
・finishing_sdhololabcha.py

# bpyインポート
import bpy
# 正規表現を利用するためインポート
import re

def apply_modifier_targettype(arg_object:bpy.types.Object, arg_modifier_type:str) -> bool:
    """指定オブジェクトの指定タイプのモディファイアを適用する

    Keyword Arguments:
        arg_object (bpy.types.Object): 指定オブジェクト
        arg_modifier_type {str} -- 指定のモディファイアタイプ

    Returns:
        bool -- 実行成否
    """
    
    # 対象のオブジェクトをアクティブオブジェクトにする
    bpy.context.view_layer.objects.active = arg_object

    # オブジェクト内の全てのモディファイアを走査する
    for check_modifier in arg_object.modifiers:
        # モディファイアの種類が指定のものであるか確認する
        if check_modifier.type == arg_modifier_type:
            # 指定モディファイアなら適用する
            # (https://docs.blender.org/api/current/bpy.ops.object.html#bpy.ops.object.modifier_add)
            bpy.ops.object.modifier_apply(modifier=check_modifier.name)

    # 実行成否を返却する
    return True

# 指定の正規表現とオブジェクト名が一致したオブジェクトの参照リストを返す
def select_object_patternmatch(arg_pattern:str) -> list:
    """指定の正規表現とオブジェクト名が一致したオブジェクトの参照リストを返す

    Keyword Arguments:
        arg_pattern {str} -- 指定文字列

    Returns:
        list -- オブジェクトの参照リスト
    """
    
    # 処理対象のオブジェクトリストを作成する
    targetobject_list = []

    # シーン内の全オブジェクトを走査する
    for check_obj in bpy.context.scene.objects:
        # オブジェクト名が指定の正規表現と一致するか
        if re.fullmatch(arg_pattern, check_obj.name):
            # 一致すれば対象とする
            targetobject_list.append(check_obj)

    # リストを返却する
    return targetobject_list

# 選択中オブジェクトを結合する
def join_objects_selected(arg_objectname="") -> bool:
    """選択中オブジェクトを結合する
    
    Keyword Arguments:
        arg_objectname {str} -- 結合オブジェクト名 (default: {""})

    Returns:
        bool -- 実行の正否
    """

    # オブジェクトの結合を実行する
    bpy.ops.object.join()
    
    # 結合オブジェクト名が設定されているか
    if len(arg_objectname):
        # オブジェクト名が設定されていれば名前を変更する
        bpy.context.view_layer.objects.active.name = arg_objectname
  
    return True

# 関数の実行例
# シーン内の全オブジェクトを走査する
for check_obj in bpy.context.scene.objects:
    # 一旦すべてのオブジェクトを非選択状態にする
    check_obj.select_set(False)

# 指定の正規表現(Joint_~)とオブジェクト名が一致したオブジェクトを処理対象にする
targetobj_list = select_object_patternmatch(r"Joint_.*")

# 処理対象のオブジェクトのジオメトリ系モディファイアを適用する
for target_obj in targetobj_list:
    # ミラーモディファイアを適用する
    apply_modifier_targettype(target_obj, 'MIRROR')
    # 辺分離モディファイアを適用する
    apply_modifier_targettype(target_obj, 'EDGE_SPLIT')
    # 対象のオブジェクトを選択状態にする
    target_obj.select_set(True)

# オブジェクトを結合する
if len(targetobj_list) > 0:
    # アクティブオブジェクトを指定する
    bpy.context.view_layer.objects.active = targetobj_list[0]
    # オブジェクトを結合する
    join_objects_selected("JoinedObject")

スクリプトを実行するだけで自動でジオメトリ系のモディファイアの適用とオブジェクトの結合が行われるようにできました。

HoloLens Meetup vol.32での発表資料

HoloLens Meetup vol.32 での発表資料です。
発表内容は「SDホロラボちゃん作ってみた HoloLens向けモデリングの知見」です。

www.slideshare.net

イベント情報

イベント情報は以下になります。
hololens.connpass.com

Blender3.0で利用可能なpythonスクリプトを作る その137(指定のタイプのモディファイアを適用する)

本日は Blender の技術調査枠です。
Blender3.0で利用可能なpythonスクリプトを作ります。

指定のタイプのモディファイアを適用する

モディファイアを適用するには 関数を利用します。
docs.blender.org
モディファイアが指定のタイプからは type 変数を確認することで確認できます。
docs.blender.org

サンプルスクリプト

以下のサンプルスクリプトを作成しました。
指定オブジェクトに含まれる指定タイプのモディファイアを全て適用します。
・Script_apply_modifier_targettype.py

# bpyインポート
import bpy

def apply_modifier_targettype(arg_object:bpy.types.Object, arg_modifier_type:str) -> bool:
    """指定オブジェクトの指定タイプのモディファイアを適用する

    Keyword Arguments:
        arg_object (bpy.types.Object): 指定オブジェクト
        arg_modifier_type {str} -- 指定のモディファイアタイプ

    Returns:
        bool -- 実行成否
    """
    
    # 対象のオブジェクトをアクティブオブジェクトにする
    bpy.context.view_layer.objects.active = arg_object

    # オブジェクト内の全てのモディファイアを走査する
    for check_modifier in arg_object.modifiers:
        # モディファイアの種類が指定のものであるか確認する
        if check_modifier.type == arg_modifier_type:
            # 指定モディファイアなら適用する
            # (https://docs.blender.org/api/current/bpy.ops.object.html#bpy.ops.object.modifier_add)
            bpy.ops.object.modifier_apply(modifier=check_modifier.name)

    # 実行成否を返却する
    return True

# 関数の実行例
# ミラーモディファイアを適用する
# モディファイアの種類のマニュアル
# (https://docs.blender.org/api/current/bpy_types_enum_items/object_modifier_type_items.html#rna-enum-object-modifier-type-items)
apply_modifier_targettype(bpy.context.scene.objects.get('Cube'), 'MIRROR')

・実行前

・実行後