広告
広告

シェイプキーまとめ

カテゴリ:blender

目次

絶対と相対

ワークフロー

パーツの分離

モディフィアの適用

Basis の変更

シェイプに反映

シェイプキーの一部をコピー・任意の頂点のシェイプキーを削除

複製したメッシュからシェイプキーを作成

シェイプキーをミラー反転

シェイプキーのミラー

Python

頂点数の異なるオブジェクト間でのシェイプキーの転送

絶対と相対

相対は、変更した頂点のインデックスとその頂点の位置差分ベクトルとのみを保存している。なので頂点数やインデックスを変更していなければ、基準の対象(Relative to)を変更しても機能する。頂点を結合したり面を分離したりすると頂点のインデックスがずれるので注意する必要がある。

絶対は全頂点の頂点座標を保存してる。絶対は順次オブジェクトを変形させるときに使う。通常は相対で問題ない。

ワークフロー

ミラーモディフィアを適用して、Xミラーでシェイプキーを作成する方法と、Apply Modifier アドオンを利用する方法とがある。Apply Modifier を利用する方法では左右対称が崩れることがないメリットがある。

シェイプキーを作成した後はポリゴン数を変更できないので、シェイプキーの作成はモデル作成工程の一番最後になる。部分的に変更したい場合はパーツの分離を参照。頂点数の異なるオブジェクト間でシェイプキーを転送するには頂点数の異なるオブジェクト間でのシェイプキーの転送を参照。

パーツの分離

シェイプキーを作成した後でポリゴン数を変更したい場合は以下の手順でシェイプキーの破壊を低減できる。

  1. 変更が必要な個所を分離「メッシュ > 分離(P)」して別オブジェクトにする
  2. 分離したオブジェクトのシェイプキーを削除(必要ならば)
  3. 分離したオブジェクトを編集
  4. 統合「オブジェクト > 統合(Ctrl + J)」する

この方法では壊れるシェイプキーを分離した部分に限定できる。不要部分の削除は不要部分を分離した後で、分離したオブジェクトを削除する。

ミラーモディフィアの適用

Apply Modifier アドオンを使う。

Basis の変更

基準の対象(Relative to)を変更する。2.79 では基本形状となるシェイプキー。

relative to
Basis の変更

シェイプに反映

「頂点 > シェイプに反映(Propagate to Shapes)」は選択した頂点を現在の状態で固定し、その状態をほかのシェイプキーにも適用する。Basis を変更した後だけでなく、Basis でないシェイプキーを変更してそれを Basis に反映するのにも使える。

シェイプキーの一部をコピー・任意の頂点のシェイプキーを削除

対象の頂点を選択して「頂点 > 任意のシェイプキーを選択部に合成(Blend From Shapes)」を実行すると、ほかのシェイプキーからデータをコピーできる。「追加」のチェックを外すのを忘れないようにする。シェイプキーを削除する場合は基準の対象(通常は Basis)からデータをコピーする。

2.79 では「メッシュ > 頂点 > 任意のシェイプキーを選択部に合成」。

delete any shapekey
任意の頂点のシェイプキーを削除

選択している頂点のシェイプキーを削除するスクリプト

import bpy

active = bpy.context.active_object

# get basis
basis_name = active.active_shape_key.relative_key.name

# delete selected vertices shapekeys
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.blend_from_shape(shape=basis_name, blend=1.0, add=False)

複製したメッシュからシェイプキーを作成

複製したメッシュ群を選択した後、最後にシェイプキーを追加するメッシュを選択し、「シェイプとして統合(Join as Shapes)」を実行する。

join as shapes
シェイプとして統合

シェイプキーをミラー反転

トポロジーバージョンはメッシュのトポロジーに基づいて計算するので、メッシュの頂点位置が厳密なミラーでなくてもよい。しかしうまくいかないことが多い。

mirror
ミラー反転

シェイプキーのミラー

手順

  1. 空のシェイプキーを作成
  2. 「頂点 > 任意のシェイプキーを選択部に合成(Blend From Shapes)」を実行してシェイプキーを複製
  3. 複製したシェイプキーをミラー反転
  4. 元のシェイプキーに「頂点 > 任意のシェイプキーを選択部に合成(Blend From Shapes)」を「追加」にチェックを入れて実行
  5. 複製したシェイプキーを削除

選択されているシェイプキーをミラーするスクリプト

import bpy

bpy.ops.object.mode_set(mode='OBJECT')
active = bpy.context.active_object
src_shapekey_name = active.active_shape_key.name
src_shapekey_index = active.active_shape_key_index

# create empty shapekey
bpy.ops.object.shape_key_add(from_mix=False)
new_shapekey_name = active.active_shape_key.name
new_shapekey_index = active.active_shape_key_index

# copy from shapekey
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action = 'SELECT')
bpy.ops.mesh.blend_from_shape(shape=src_shapekey_name, blend=1.0, add=False)

# mirror
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.shape_key_mirror(use_topology=False)

# join
active.active_shape_key_index = src_shapekey_index
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action = 'SELECT')
bpy.ops.mesh.blend_from_shape(shape=new_shapekey_name, blend=1.0, add=True)

# delete copied shape key
bpy.ops.object.mode_set(mode='OBJECT')
active.active_shape_key_index = new_shapekey_index
bpy.ops.object.shape_key_remove(all=False)

Python

シェイプキーのリスト

bpy.context.active_object.data.shape_keys.key_blocks

アクティブなシェイプキー

bpy.context.active_object.active_shape_key

アクティブなシェイプキーのインデックス

bpy.context.active_object.active_shape_key_index

アクティブなシェイプキーを変更

bpy.context.active_object.active_shape_key_index = # 任意のインデックス

シェイプキー適用後の頂点位置の取得

for shape_key_point in bpy.context.active_object.active_shape_key.data:
    print(shape_key_point.co)

シェイプキーの頂点位置を変更

bpy.context.active_object.active_shape_key.data[0].co = (0, 0, 0)

頂点数の異なるオブジェクト間でのシェイプキーの転送

オブジェクトモードで転送元を選択後に転送先のオブジェクトを選択して、以下のスクリプトを実行するとシェイプキーを転送できる。Basis の頂点座標を元に転送しているので、頂点数が異なっていてもシェイプキーを転送できる。

転送先のオブジェクトのシェイプキーは必要なら削除しておく。元のオブジェクトに存在しないシェイプキーの可能性を考慮して、自動的に削除しないようにしてある。

頂点数やシェイプキーの数次第で処理の完了に数分かかる場合がある

import bpy
                
dst = bpy.context.active_object
src = bpy.context.selected_objects[0]
if dst == src:
    src = bpy.context.selected_objects[1]
    if dst == src:
        raise Exception()
    
# create basis if does not exists
if dst.data.shape_keys == None:
    bpy.ops.object.shape_key_add(from_mix=False)

for i in range(1, len(src.data.shape_keys.key_blocks)): # skip basis
    src_key = src.data.shape_keys.key_blocks[i]
    
    # get shape key data
    src_vertices = []
    basis = src.active_shape_key.relative_key.data
    key = src_key.data
    for b, k in zip(basis, key):
        if b.co[0] != k.co[0] or b.co[1] != k.co[1] or b.co[2] != k.co[2]:
            src_vertices.append((b.co, k.co))
            
    # add shapekey
    bpy.ops.object.shape_key_add(from_mix=False)

    # rename
    dst.active_shape_key.name = src_key.name

    # transfer data
    for v in dst.active_shape_key.data:
        for b, k in src_vertices:
            if b[0] == v.co[0] and b[1] == v.co[1] and b[2] == v.co[2]:
                v.co = k

アドオン

【Blender Plugin】メッシュ変更後のシェイプキー補正ツール(¥300)


soft mod 2.0

関連記事

Blender 記事の目次


広告
広告