シェイプキーまとめ
目次
- ワークフロー
- シェイプキーのロック
- 複製したメッシュからシェイプキーを作成
- 絶対と相対
- シェイプキーの値を一括で0にする
- パーツの分離
- モディフィアの適用
- Basis の変更
- シェイプに反映
- シェイプキーの一部をコピー・任意の頂点のシェイプキーを削除
- シェイプキーをミラー反転
- シェイプキーのミラー
- シェイプキーを反対方向に移動させる
- Python
- 法線のロック
- アドオン
ワークフロー
シェイプキーを編集する前に重複頂点を削除しておく。シェイプキー編集後に重複頂点を削除するとシェイプキーが壊れる。
ミラーモディフィアを適用して、Xミラーでシェイプキーを作成する方法と、Apply Modifier アドオンを利用する方法とがある。Apply Modifier を利用する方法では左右対称が崩れることがないメリットがある。モディフィアを適用した結果、頂点の結合等で内部のインデックスがずれるとシェイプキーが壊れることに注意する必要がある。
複製したメッシュを編集して、シェイプとして統合(join as shapes)でシェイプキーを作成する方法がある。この方法はシェイプキーが壊れても容易に復元できるのが最大の利点だ。
シェイプキーを作成した後はポリゴン数を変更できないので、シェイプキーの作成はモデル作成工程の一番最後になる。部分的に変更したい場合はパーツの分離を参照。頂点数の異なるオブジェクト間でシェイプキーを転送するには頂点数の異なるオブジェクト間でのシェイプキーの転送を参照。
最終的にオブジェクトを結合する場合でも、シェイプキー作成前にオブジェクトを結合する必要はない。ただしオブジェクト結合時、同名のシェイプキーは統合されることに注意する。
安全なシェイプキー作成フロー
- メッシュ編集系のモディフィア(ミラーやベベル、ソリッド化など)をすべて適用
- 重複頂点の削除
- 複製したメッシュを編集して、シェイプとして統合(join as shapes)でシェイプキーを作成する
シェイプキーのロック
バージョン 4.1 からシェイプキーをロックできるようになった。
複製したメッシュからシェイプキーを作成
手順
- 複製したオブジェクトを編集する
- それらを選択し、最後にシェイプキーを追加するオブジェクトを選択する
- シェイプとして統合(join as shapes)を実行する
絶対と相対
相対は、変更した頂点のインデックスとその頂点の位置差分ベクトルとのみを保存している。なので頂点数やインデックスを変更していなければ、基準の対象(Relative to)を変更しても機能する。頂点を結合したり面を分離したりすると頂点のインデックスがずれるので注意する必要がある。
絶対は全頂点の頂点座標を保存してる。絶対は順次オブジェクトを変形させるときに使う。通常は相対で問題ない。
シェイプキーの値を一括で0にする
プロパティパネル > データー > シェイプキーの右下にある×を押す。
パーツの分離
シェイプキーを作成した後でポリゴン数を変更したい場合は以下の手順でシェイプキーの破壊を低減できる。
- 変更が必要な個所を分離「メッシュ > 分離(P)」して別オブジェクトにする
- 分離したオブジェクトのシェイプキーを削除(必要ならば)
- 分離したオブジェクトを編集
- 統合「オブジェクト > 統合(Ctrl + J)」する
この方法では壊れるシェイプキーを分離した部分に限定できる。不要部分の削除は不要部分を分離した後で、分離したオブジェクトを削除する。
ミラーモディフィアの適用
Basis の変更
基準の対象(Relative to)を変更する。2.79 では基本形状となるシェイプキー。
シェイプに反映
「頂点 > シェイプに反映(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)
シェイプキーをミラー反転
トポロジーバージョンはメッシュのトポロジーに基づいて計算するので、メッシュの頂点位置が厳密なミラーでなくてもよい。しかしうまくいかないことが多い。
シェイプキーのミラー
手順
- 空のシェイプキーを作成
- 「頂点 > 任意のシェイプキーを選択部に合成(Blend From Shapes)」を実行してシェイプキーを複製
- 複製したシェイプキーをミラー反転
- 元のシェイプキーに「頂点 > 任意のシェイプキーを選択部に合成(Blend From Shapes)」を「追加」にチェックを入れて実行
- 複製したシェイプキーを削除
選択されているシェイプキーをミラーするスクリプト
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 に設定すれば反対方向にシェイプキーを移動させられる。間違って適用したシェイプキーを修正するときにもこの方法が使えるかもしれない。
シェイプキーはマイナスも設定できます
— Ginneko3D (@kiofwjjpTyq08Cz) [August 18, 2020
1. お] Range Min を -1 にする
Valueをマイナスに調節し, 口を閉じた顔にする
2. 右の [V] ボタン押す, [New Shape From Mix], 名前は[Basis]にする
3. [お] のValueとMinを 0 に戻す
4. [Basis]を上三角ボタンで一番上に持ってくる
5. [通常]を削除する
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
形状の強制転送・個々のシェイプキーを別オブジェクト化するアドオン。
Shape Keys+
シェイプキーを管理するアドオン。フォルダでシェイプキーを管理したり、シェイプキーパネルでドライバーを編集する機能などがある。
ShapeKeysUtil(¥0)
シェイプキー付きのメッシュにミラーを適用する機能と、両側で作ってある表情シェイプを左右別々に分離する機能とがある。
Mio3 ShapeKeySync
複数のオブジェクトのシェイプキーを同期するアドオン。