blenderのapiについてです。pythonで行います。
ドキュメントは以下にあります。
https://docs.blender.org/api/current/index.html
実行の方法
コンソールから
ターミナルから実行します。
ファイルから
テキストエディタから実行します。
システムコンソールに出力されます。
pythonファイルとして保存できます。
また読み込みもできます。

VSCODEで変更
外部エディタ(VSCODE)で変更して反映できます。
作成物
pythonスクリプトですが、ほとんどの部分は生成AIで作成しています。
エクスポート
モデルをオブジェクトごとにfbx形式で出します。
import bpy
# エクスポート先のフォルダを指定
output_dir = "C:/work/ 任意のフォルダを指定"
# 選択したオブジェクトを取得
selected_objects = bpy.context.selected_objects
# オブジェクトの数だけ繰り返す
for obj in selected_objects:
# オブジェクトの名前からファイル名を作成
filename = f"{obj.name}.fbx"
filepath = output_dir + filename
# 一時的に他のオブジェクトを非表示にする
for other_obj in selected_objects:
if other_obj != obj:
other_obj.hide_set(True)
# オブジェクトをアクティブにする
bpy.context.view_layer.objects.active = obj
# FBXエクスポート
bpy.ops.export_scene.fbx(
filepath=filepath,
use_selection=True
)
# 一時的に非表示にしたオブジェクトを再び表示する
for other_obj in selected_objects:
if other_obj != obj:
other_obj.hide_set(False)
print("FBXファイルのエクスポートが完了しました。")
ボーン追加
vrmモデルにIKのターゲットボーンを追加します。
import bpy
# アーマチュアの名前
armature_name = "アーマチュア"
# IKターゲットにする新しいボーンの名前(引き出したボーン)
ik_bone_nameArr = ["IK_Bone1", "IK_Bone2", "IK_Bone3", "IK_Bone4"]
# IKの影響を受けるボーン(根本)の名前
chain_root_bone_nameArr = ["lower_arm.L", "lower_arm.R", "lower_leg.L", "lower_leg.R"]
# IK用の新しいボーンを作成して設定する関数
def addTarget(ik_bone_name, chain_root_bone_name):
# アーマチュアオブジェクトを取得
armature = bpy.data.objects.get(armature_name)
if armature and armature.type == 'ARMATURE':
# Editモードで新しいボーン(IK用)を追加
bpy.context.view_layer.objects.active = armature
bpy.ops.object.mode_set(mode='EDIT')
# IK用の新しいボーンを作成して、元のボーンから引き出す
chain_root_bone = armature.data.edit_bones.get(chain_root_bone_name)
if chain_root_bone:
ik_bone = armature.data.edit_bones.new(ik_bone_name)
ik_bone.head = chain_root_bone.tail # 既存ボーンの終端に一致させる
ik_bone.tail = (
chain_root_bone.tail[0],
chain_root_bone.tail[1],
chain_root_bone.tail[2] + 0.5,
)
ik_bone.use_connect = False # 親子関係を持たせない
print(f"'{ik_bone_name}' ボーンを作成しました。")
else:
print(f"ボーン '{chain_root_bone_name}' が見つかりません。")
# オブジェクトモードに戻る
bpy.ops.object.mode_set(mode='OBJECT')
# IKコンストレイントの設定を追加するボーンのPose Boneを取得
pose_bone = armature.pose.bones.get(chain_root_bone_name)
if pose_bone:
# IKコンストレイントを追加
ik_constraint = pose_bone.constraints.new(type="IK")
ik_constraint.target = armature
ik_constraint.subtarget = ik_bone_name
ik_constraint.chain_count = 2 # IKが影響するボーンの数
# Y軸とZ軸をロック(IK制御下で回転できないようにする)
pose_bone.lock_ik_y = True
pose_bone.lock_ik_z = True
# X軸の回転制限を設定(-180度から0度)
pose_bone.use_ik_limit_x = True # IK制限を有効化
pose_bone.ik_min_x = -3.14159 # -180度(ラジアン)
pose_bone.ik_max_x = 0 # 0度
print(f"IKコンストレイントと回転制限を '{chain_root_bone_name}' に設定しました。")
else:
print(f"'{chain_root_bone_name}' のポーズボーンが見つかりません。")
else:
print(f"アーマチュア '{armature_name}' が見つかりません。")
# IKボーンとルートボーンを結びつける処理
for i in range(len(ik_bone_nameArr)):
addTarget(ik_bone_nameArr[i], chain_root_bone_nameArr[i])
人体モデル(骨格)
VRoid studio
VRoid studioのVRMモデルを読み込んだ場合です。

import bpy
# アーマチュアの名前
armature_name = "Armature"
# IKターゲットにする新しいボーンの名前(引き出したボーン)
ik_bone_nameArr = ["IK_Bone1", "IK_Bone2", "IK_Bone3", "IK_Bone4"]
# IKの影響を受けるボーン(根本)の名前
chain_root_bone_nameArr = ["J_Bip_L_LowerArm", "J_Bip_R_LowerArm", "J_Bip_L_LowerLeg", "J_Bip_R_LowerLeg"]
# IK用の新しいボーンを作成して設定する関数
def addTarget(ik_bone_name, chain_root_bone_name):
# アーマチュアオブジェクトを取得
armature = bpy.data.objects.get(armature_name)
if armature and armature.type == 'ARMATURE':
# Editモードで新しいボーン(IK用)を追加
bpy.context.view_layer.objects.active = armature
bpy.ops.object.mode_set(mode='EDIT')
# IK用の新しいボーンを作成して、元のボーンから引き出す
chain_root_bone = armature.data.edit_bones.get(chain_root_bone_name)
if chain_root_bone:
ik_bone = armature.data.edit_bones.new(ik_bone_name)
ik_bone.head = chain_root_bone.tail # 既存ボーンの終端に一致させる
ik_bone.tail = (
chain_root_bone.tail[0],
chain_root_bone.tail[1],
chain_root_bone.tail[2] + 0.5,
)
ik_bone.use_connect = False # 親子関係を持たせない
print(f"'{ik_bone_name}' ボーンを作成しました。")
else:
print(f"ボーン '{chain_root_bone_name}' が見つかりません。")
# オブジェクトモードに戻る
bpy.ops.object.mode_set(mode='OBJECT')
# IKコンストレイントの設定を追加するボーンのPose Boneを取得
pose_bone = armature.pose.bones.get(chain_root_bone_name)
if pose_bone:
# IKコンストレイントを追加
ik_constraint = pose_bone.constraints.new(type="IK")
ik_constraint.target = armature
ik_constraint.subtarget = ik_bone_name
ik_constraint.chain_count = 2 # IKが影響するボーンの数
# Y軸とZ軸をロック(IK制御下で回転できないようにする)
pose_bone.lock_ik_y = True
pose_bone.lock_ik_z = True
# X軸の回転制限を設定(-180度から0度)
pose_bone.use_ik_limit_x = True # IK制限を有効化
# pose_bone.ik_min_x = -3.14159 # -180度(ラジアン)
# pose_bone.ik_max_x = 0 # 0度
pose_bone.ik_min_x = 0 # 0度(ラジアン)
pose_bone.ik_max_x = 3.14159 # 180度
print(f"IKコンストレイントと回転制限を '{chain_root_bone_name}' に設定しました。")
else:
print(f"'{chain_root_bone_name}' のポーズボーンが見つかりません。")
else:
print(f"アーマチュア '{armature_name}' が見つかりません。")
# IKボーンとルートボーンを結びつける処理
for i in range(len(ik_bone_nameArr)):
addTarget(ik_bone_nameArr[i], chain_root_bone_nameArr[i])
変更箇所:
armature_name = "Armature"
chain_root_bone_nameArr = ["J_Bip_L_LowerArm", "J_Bip_R_LowerArm", "J_Bip_L_LowerLeg", "J_Bip_R_LowerLeg"]
IKの回転角度は適宜変更します。
pose_bone.ik_min_x = 0 # 0度(ラジアン)
pose_bone.ik_max_x = 3.14159 # 180度
脚と腕だと変更する必要があります。
コメント