dskjal
広告
広告

シェイプキーまとめ

カテゴリ:blender

目次

ワークフロー

シェイプキーを編集する前に重複頂点を削除しておくシェイプキー編集後に重複頂点を削除するとシェイプキーが壊れる

ミラーモディフィアを適用して、Xミラーでシェイプキーを作成する方法と、Apply Modifier アドオンを利用する方法とがある。Apply Modifier を利用する方法では左右対称が崩れることがないメリットがある。モディフィアを適用した結果、頂点の結合等で内部のインデックスがずれるとシェイプキーが壊れることに注意する必要がある。

複製したメッシュを編集して、シェイプとして統合(join as shapes)でシェイプキーを作成する方法がある。この方法はシェイプキーが壊れても容易に復元できるのが最大の利点だ。

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

最終的にオブジェクトを結合する場合でも、シェイプキー作成前にオブジェクトを結合する必要はない。ただしオブジェクト結合時、同名のシェイプキーは統合されることに注意する。

安全なシェイプキー作成フロー

  1. メッシュ編集系のモディフィア(ミラーやベベル、ソリッド化など)をすべて適用
  2. 重複頂点の削除
  3. 複製したメッシュを編集して、シェイプとして統合(join as shapes)でシェイプキーを作成する

シェイプキーのロック

バージョン 4.1 からシェイプキーをロックできるようになった。

シェイプキーのロック

シェイプキーのロック

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

手順

  1. 複製したオブジェクトを編集する
  2. それらを選択し、最後にシェイプキーを追加するオブジェクトを選択する
  3. シェイプとして統合(join as shapes)を実行する

シェイプとして統合

シェイプとして統合

絶対と相対

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

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

シェイプキーの値を一括で0にする

プロパティパネル > データー > シェイプキーの右下にある×を押す。

シェイプキーの値を一括で0にする

シェイプキーの値を一括で0にする

パーツの分離

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

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

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

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

Apply Modifier アドオンを使う。

Basis の変更

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

Basis の変更

Basis の変更

シェイプに反映

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

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

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

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

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

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

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

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)

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

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

ミラー反転

ミラー反転

シェイプキーのミラー

手順

  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)

シェイプキーを反対方向に移動させる

最小範囲(Range Min)を -1 に設定すれば反対方向にシェイプキーを移動させられる。間違って適用したシェイプキーを修正するときにもこの方法が使えるかもしれない。

シェイプキーを反対方向に移動させる

シェイプキーを反対方向に移動させる

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

転送元の選択されている頂点のみ転送するバージョン

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()

# get selected vertices indices
selected = [v.index for v in src.data.vertices if v.select]

# 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 i in selected:
        b = basis[i]
        k = key[i]
        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

法線のロック

バージョン 2.93 の時点ではシェイプキーの法線は編集できない。なので法線をテクスチャにベイクする必要がある。

アドオン

Lazy Shapekeys

形状の強制転送・個々のシェイプキーを別オブジェクト化するアドオン。

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

Shape Keys+

シェイプキーを管理するアドオン。フォルダでシェイプキーを管理したり、シェイプキーパネルでドライバーを編集する機能などがある。

ShapeKeysUtil(¥0)

シェイプキー付きのメッシュにミラーを適用する機能と、両側で作ってある表情シェイプを左右別々に分離する機能とがある。

Mio3 ShapeKeySync

複数のオブジェクトのシェイプキーを同期するアドオン。

関連記事

Blender 記事の目次


広告
広告

カテゴリ