LoginSignup
2
2

More than 1 year has passed since last update.

カーブ(スプライン)の選択頂点にフックモディファイアを設定する

Posted at

Blenderのカーブオブジェクトに対して動きを付ける場合フックモディファイアを使用することが多いですが
チャットの話題でポイントに対してスクリプトでフックを付けたいという話題があったので
検索結果を参考に作ってみました
23031901.gif

アクティブスプラインの選択頂点のみが対象です

まずはエンプティを作成してフックするスクリプト

import bpy
context = bpy.context
curve = context.active_object
# カーブの変換マトリクス
matrix_ = curve.matrix_world
# アクティブスプラインを対象に
spline = curve.data.splines.active
if spline.type == 'NURBS':
    for i, point in enumerate(spline.points): 
        # 選択頂点のみフック作成
        if point.select:
            hook_mod = curve.modifiers.new(name='scripted hook', type='HOOK')
            # フックのターゲットになるエンプティを作成
            empty = bpy.data.objects.new("empty_%s" % i, None )
            context.scene.collection.objects.link( empty )
            empty.location = matrix_ @ point.co.to_3d()
            # モディファイアを設定
            hook_mod.center = point.co.to_3d()
            hook_mod.vertex_indices_set([i])
            bpy.context.evaluated_depsgraph_get() 
            hook_mod.object = empty
elif spline.type == 'BEZIER':
    for i, point in enumerate(spline.bezier_points): 
        # 選択頂点のみフック作成
        if point.select_control_point:
            hook_mod = curve.modifiers.new(name='scripted hook', type='HOOK')
            # フックのターゲットになるエンプティを作成
            empty = bpy.data.objects.new("empty_%s" % i, None )
            context.scene.collection.objects.link( empty )
            empty.location = matrix_ @ point.co.to_3d()
            # モディファイアを設定
            hook_mod.center = point.co.to_3d()
            hook_mod.vertex_indices_set([i*3, i*3+1, i*3+2])
            bpy.context.evaluated_depsgraph_get() 
            hook_mod.object = empty

さらにこれを元に選択頂点位置にボーンを作成したフックさせるスクリプト

import bpy
from mathutils import Vector

context = bpy.context
curve = context.active_object
# カーブの変換マトリクス
matrix_ = curve.matrix_world
# アクティブスプラインを対象に
spline = curve.data.splines.active

def add_arature(context, arm_name, point_list, pos_list):
    ref_active = context.active_object
    # アーマチュアオブジェクトを作成
    arm = bpy.data.armatures.new(arm_name)
    arm_obj = bpy.data.objects.new(arm_name, arm)
    bpy.context.collection.objects.link(arm_obj)
    # アーマチュアの原点をカーブと合わせる
    arm_obj.location = curve.location
    # アクティブオブジェクトの変更
    context.view_layer.objects.active = arm_obj
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
    edit_bones = arm_obj.data.edit_bones
    bone_list = []
    # 指定位置にボーンを作成
    for i, pos in enumerate(pos_list):
        bone = edit_bones.new('bone_%s' % i )
        bone.head = pos
        bone.tail = pos + Vector((0.0, 0.0, 0.5))
        bone_list.append(bone.name)
    bpy.ops.object.mode_set(mode='OBJECT')
    # アクティブオブジェクトを戻す
    context.view_layer.objects.active = ref_active
    return(arm_obj, bone_list)
# ボーンにフック
def add_hook_mod_bone(obj, arm_obj, bone, hook_center, vertex_indices):
    # モディファイアを付与
    hook_mod = obj.modifiers.new(name = bone, type='HOOK')
    hook_mod.center = hook_center
    # 対象の頂点id
    hook_mod.vertex_indices_set(vertex_indices)
    bpy.context.evaluated_depsgraph_get()
    hook_mod.object = arm_obj
    hook_mod.subtarget = bone

if spline.type == 'NURBS':
    point_list = [ i for i,p in enumerate(spline.points) if p.select ]
    pos_list = [ spline.points[i].co.to_3d() for i in point_list ]
elif spline.type == 'BEZIER':
    point_list = [i for i,p in enumerate(spline.bezier_points) if p.select_control_point]
    pos_list = [ spline.bezier_points[i].co.to_3d() for i in point_list ]

# アーマチュアオブジェクトを作成
arm_name = "Hook"
[arm_obj, bone_list] = add_arature(context, arm_name, point_list, pos_list)

# 選択頂点をボーンにフック
for i, index_ in enumerate(point_list):
    hook_center = pos_list[i]
    if spline.type == 'NURBS':
        vertex_indices = [index_ ]
    elif spline.type == 'BEZIER':
        vertex_indices = [index_ *3, index_ *3+1, index_ *3+2]
    add_hook_mod_bone(curve, arm_obj, bone_list[i], hook_center, vertex_indices)

何かの参考になれば幸いです

2
2
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
2
2