MRが楽しい

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

SDキャラクターの3Dモデルを作成する その44(VRMファイルに一人称視点の設定する)

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

一人称視点の設定

VRM ではモデルをアバターとして利用しているとき、司会の邪魔にならないように自身の視点から頭部のメッシュを不可視にできます。
この機能を有効にするには VRMFirstPerson を設定します。
vrm.dev

本設定を行う際は非表示にするメッシュと表示するメッシュを別オブジェクトとして分割しておく必要があります。
以前作成した python スクリプトBlender プロジェクトを修正して頭部オブジェクトと身体オブジェクトを分けた3Dモデルを作成しました。
・finishing_sdhololabchan.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_Head_~)とオブジェクト名が一致したオブジェクトを処理対象にする
targetobj_list = select_object_patternmatch(r"Joint_Head_.*")

# 処理対象のオブジェクトのジオメトリ系モディファイアを適用する
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("Head")

for check_obj in bpy.context.scene.objects:
    # 一旦すべてのオブジェクトを非選択状態にする
    check_obj.select_set(False)

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

# 処理対象のオブジェクトのジオメトリ系モディファイアを適用する
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("Body")

for check_obj in bpy.context.scene.objects:
    # 一旦すべてのオブジェクトを非選択状態にする
    check_obj.select_set(False)

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

# 処理対象のオブジェクトを削除する
for target_obj in targetobj_list:
    # オブジェクトが存在する場合は削除を行う
    bpy.data.objects.remove(target_obj)

3Dモデルを変更したので改めて以下の手順を実施して VRM ファイルを再作成します。
bluebirdofoz.hatenablog.com

以下の通り、頭部と身体でオブジェクトを分離した VRM ファイルを再作成できました。
ここから VRMFirstPerson の設定を行います。

取り込んだ VRM ファイルの prefab を開きます。

ルートオブジェクトに設定されている VRMFirstPerson の[Renderers]設定を以下の通り変更します。

一人称でも三人称でも表示するオブジェクト(身体オブジェクト):Both(どちらでも表示)
一人称表示しないオブジェクト(頭部オブジェクト):ThirdPersonOnly(三人称でのみ表示)

これで設定は完了です。
メニューから[VRM -> Export to VRM]を実行して VRM ファイルを出力します。