LightWaveで二次元キャラ系人物モデリング奮闘記 ―視線コントロール編―

最終更新:2017/01/13

視線コントロールには、一般には目の中心軸の延長線上に視線用ターゲット・オブジェクトを配置し、両目からそれを参照させてIKを用いて視線をコントロールする。IKを使いたい場合は目を球状のオブジェクトとしてモデリングする必要があり、扁平な顔が基本の二次元イラストやアニメ調の作風にはなかなか合わせにくい傾向がある。劇画調を目指している場合を除き、IKを使いたいがために眼球がちゃんとはまるようにするには、顔のモデリングに必要な工夫の労力が釣り合わないことが多い。

そこで、瞳の動きにはモーフを使いながら、擬似的にIKのような視線コントロールを実現する方法を考える。

瞳の後退モーフによるカメラ目線

カメラ目線を実現するには、MMDなどでよく使われている方法を使う。MMD方式のカメラ目線は簡単に言うと、目の位置を後退させて、三次元的に瞳の中心をずらすことによって擬似的にカメラ目線になっているように見せる。

これまでは白目を自己発光させて陰影が出ないように設定していたけど、まぶたに白目が透けてしまったりする問題があったため、自己発光度を0%に変更し、拡散レベルを400%という非常に大きい値にすることで陰影を極力落とす。

morph031

目を後退させると、眼窩の内側が見えてしまうので、内側を白に染めて目の後退がわかりにくいような仕組みを作る。内側を自己発光度の設定してある白に染めてしまうと、目を閉じても内側が透けて見えてしまう。上のサーフェース設定はその対策でもある。

morph032

逆に、瞳の中心は目を後退させることでライトの光線が届かなくなり、徐々に暗くなっていってしまうので、自己発光度を「40%」に設定する。拡散レベルは「60%」に設定し、自己発光度と拡散レベルの合計が100%になるように設定すると、自己発光度を設定していなかった場合と色合いがあまり変わらないようにできる。

morph033 morph034

目の後退によるカメラ目線の例が次の画像。白目と眼窩の内側の境界がわからないようにunReal Xtreme2のToon Tracerピクセルフィルター・プラグインの設定を変更しておく。

morph035

上の画像だけではカメラ目線になっているかどうかが少しわかりにくいので、俯瞰構図と仰視構図も示しておく。いずれもモーフ量は同じで、瞳の位置を後ろに下げただけ。カメラの位置を上下に動かしても瞳はカメラの方を向いているように見える。

morph041
俯瞰
morph042
仰視

エクスプレッションによる視線コントロール

眼を独立した球状オブジェクトとして作成しなかったので、視線の制御にIKを使えない。二次元キャラクターの目を球体として作成しようとする場合に発生しうる問題は以前にも述べたとおりで、瞳は水平、垂直の二軸のみで動くようにデザインしている。

モーフを使っている場合でも、グラフ編集に用意されていている「Channel Follower」モディファイヤを使用すれば、ターゲット・オブジェクトの特定のチャンネルの値の変動にモーフを連動させる簡易的な視線コントロールはできる。ただ、ターゲットの距離などを考慮して左右のモーフ量を個別に制御できないので、両目をひとつのターゲットで制御するのは容易くない。

morph030

ただし、Channel Followerをモーフのグラフ(エンベロープ)に適用する場合に限り、X、Y、Zの座標系チャンネルだけにしか追随させられない。H、P、Bの回転系チャンネルに追随させようとしても不可解な値が返されてしまい(特定のチャンネルだけまともな数値が出ることもあるけど、ほとんどの場合、0に限りなく近い極小の値になる)、サインカーブのような動きをさせることはできない。モーフは線形補間なので、ある意味当たり前と言えば当たり前なんだけど、Channel Followerで連動する要素に回転系のチャンネルを指定してもエラーも警告も出ないので、設定か計算の間違いだと勘違いしやすい。

そうかと言って、どこか一点を注視するような視線をモーフのスライダーだけで実現するのは楽ではない。アニメーションさせることを考えに入れたりすると、キーフレームごとにモーフ量を計算するか、その都度目分量で調整しなければならず、かなり労力がかかりそうなことは想像に難くない。

そこで、注視している場所を大雑把に指示するターゲット・オブジェクトを用意して、モーフ適用量を計算させる。視線コントロールの基本的な考え方は次の図のとおり。IKでも考え方そのものは同じ。

morph040

この図から、目の正面方向と注視点に対する方向がなす角度\thetaについてのタンジェントは次のとおりに求められる。

     \begin{align*} \tan \theta&=\frac{X_{sight} - X_{eye}}{Z_{sight} - Z_{eye}} \end{align*}

タンジェントの逆関数インバース・タンジェント(又はアークタンジェント)を用いて\thetaを求める。

     \begin{align*} \theta &= \tan^{-1} \frac{X_{sight} - X_{eye}}{Z_{sight} - Z_{eye}} \end{align*}

これをLightWaveで受け付けられるエクスプレッションに置き換える。プログラミング言語ではインバース・タンジェント(アークタンジェント)を「atan」などと記述することが多い。次の式は左目のエクスプレッションの例。名称は左右の区別がつきやすく、わかりやすければなんでもいい。

式の出力はラジアンではなく、関数電卓などで「DEG」と表される円周360°の角度なので、0^\circ \leq \theta \leq 90^\circの範囲の値をとる。必要であれば、これに定数を掛けて調整する。

atan(([Null_EyeSight.Position.X] - [Null_Eye_L.Position.X]) / ([Null_Eye_L.Position.Z] - [Null_EyeSight.Position.Z]))

エクスプレッションと、グラフで表されるチャンネルはそれぞれ独立していて、一義に定まる名称で識別されるエクスプレッションを複数のチャンネルに割り当てられるようになっている。そのため、最初は左目用のエクスプレッションを右目のチャンネルにも割り当ててしまったり、重複したエクスプレッションの除去に手間取ったり、インターフェースにとっつきにくさを感じるかもしれない。

同じく次の式は右目のエクスプレッションの例。右目のX座標は左目の正負反転なので、参照するチャンネルが異なるだけで式はほぼ同じ。両目とも瞳を顔の外側に動かすほうをモーフ量のプラスにしている場合は、全体をマイナスで正負を反転する。

atan(([Null_EyeSight.Position.X] - [Null_Eye_R.Position.X]) / ([Null_Eye_R.Position.Z] - [Null_EyeSight.Position.Z]))

それぞれの目のモーフにエクスプレッションを適用(アタッチ)し、両目のグラフを同時に表示させると次の画像のようになる。注視ターゲット・オブジェクトは-1m \leq X_{sight} \leq 1mの範囲で行ったり来たりさせているだけ。Z軸座標は目から約1m先に固定で、注視距離によって必要があれば移動させる。Z_{sight}を移動させるとグラフの振幅が変動する。

morph036

ターゲット・オブジェクトを注視させた場合と、スライダーで視線を手動設定した場合の比較。ターゲット・オブジェクトとは言うものの、上の式では精密に注視させることはできないので、あくまでも擬似的な制御。IKではないのでモーフ量と視線の角度を完全に同期させるにはエクスプレッションを更に作り込む必要がある。

morph038
両目ともモーフ適用量「100%」。視線は交わらずに平行になっている。
morph037
エクスプレッションで視線コントロールをしたもの。左目のモーフ量は「88.78%」、右目は「66.20%」。


今回は水平方向のモーフしか使っていないけど、同様に上下方向のモーフを作っておけば、理屈はまったく同じで瞳の上下運動も可能。

関連記事

LightWaveで二次元キャラ系人物モデリング奮闘記 ―表情モーフ編―

最終更新:2016/10/14

モーフィングも昔は高度な技術のひとつだったけど、今では安価な3DCGソフトウェアでも比較的手軽に利用できるようになった。

LightWaveでは、サブパッチやキャトマルといったリアルタイムに編集可能なサブディビジョン技術を備えたことによって、モデル全体のポリゴンを実際に細分化して固定させなくてもローポリゴンのまま、ハイポリゴン状態のモーフィングを実現できるようになった。また、それがモーフであるかどうかをあまり意識しないでモーフ・マップを作成及び編集できる機能を備えている。

ただ、勘違いされがちなんだけど、モーフィングは線形補間なので、ベース・モデルからモーフターゲット(LightWaveでは「エンドモーフ(Endomorph)」と呼んでいる)までは直線的に変形され、何らかの曲線を経由させるような変形や、捻りといった回転系の変形は難しい。よって、関節の旋回を伴う指などに使うことは稀なんだけど、デザイン上、指が少なかったり関節があってもないと見なせるようなデフォルメ風キャラクターなどの場合はボーンを節約してリグを簡略化したい場合は指にモーフを使うこともある。普通は顔の各所の表情や、息を吸ったり吐いたりすることによって胸や腹が規則的に膨らんだり縮んだりするモーションに用いられるのが一般的。

目を閉じるモーフの作成

「マップ」メニューグループにある新規モーフ(New Endomorph)で新しいモーフ・マップを作成する。モーフ・マップ名には、ファイル名やサーフェース名と同様に日本語全角文字(マルチバイト文字)を避けて命名する。

また、マップ名をピリオドで区切ることでモーフ・マップをグループ化することができる。グループ数にはメモリの許す限り特に上限がないので、左右を別々に管理したり、顔のパーツごとではなく「笑い」「怒り」「泣き」など表情ごとに一括管理したければそのようにすることも可能。

ここでは、左右の区別なく、目に関するモーフをすべて「EYE」グループに分類する。左右を区別する時はボーンのように「_L」や「_R」といった接尾辞をつけることで管理する。

morph000

モーフ・マップの種別を「相対」に設定し、「作成」ボタンを押す。なお、モデラーウィンドウの右下に並んでいるボタンから「M」を選択して「(新規)」を選択しても同じ結果になる。ちなみに、「絶対」モーフ・マップというのはベース・モデルの形状に関係なく固定の形状にモーフィングするために使うものだけど、キネマティック・アートやモーション・グラフィックスのようなケースを除くとそんなに使う機会はないかもしれない。

モーフ・マップを作成すると、同時にモーフ・マップ編集モードに移される。LightWave 11から表示が改善され、HUD(ヘッド・アップ・ディスプレイ)が表示されるようになった。すべてのビューの左上に編集中のモーフ・マップ名とその種別、現在編集中を意味するビューを囲む枠が表示されるようになったため、誤ってベースや意図しないモーフを編集してしまうといったミスを未然に防止できる。

morph001

表情に関係ない部分をすべて隠し(Shift+-:「=」キー)、左目が閉じるようにポイントをひたすら調整する。ちょっと顔側のパッチの数が足りなくてまぶたが伸びきってしまったけど、まだなんとかなるレベル。ここでいったんオブジェクトを保存する。

morph002

今度は右目のモーフを作る。左目のモーフを先に作ってしまってから左右対称になるようにモデリングするのは困難だし、そうかと言って両目を対称モードで一度にモデリングしてしまうとウィンクができなくなってしまうので、左目のモーフを複製して作成する。まずは、頂点マップのコピー(Copy Vertex Map)で左目のモーフを単純に複製して「EYE.CLOSE_R」モーフ・マップを作成する。

morph003

このままだと両方のモーフ・マップが左目を閉じるモーフになってしまうので、「EYE.CLOSE_R」モーフ・マップ上の左目のモーフを右目側に反転して複製する。

「ユーティリティ」メニューグループからMMorphプラグインを選択する。「Keep Original Map Value」にチェックを入れると、元になったモーフをそのまま残して複製する。身近なところで言い換えると「コピー&ペースト」に似たような動作になる。チェックを外すと、元のモーフを残さない「カット&ペースト」と似たような動作になる。

morph004

反転して複製してみたところ、右目の閉じ方が左目と同じようにならなかった。原因としては、まつ毛の先端の非常に近い距離に6個ほどあるポイント群を結合していなかったために、ポイントにモーフを適用する順番が狂ってしまったことが考えられる。

morph005

ポイントの位置そのものは左右対称なのでモーフで問題になるとは想定していなかったんだけど、解決策はある。とりあえず、左右ともまつ毛の先端のポイントをひとつに結合してしまう。結合してしまうと先端が尖らなくなるので、先端のポイントをひとつ選択し、「詳細」メニューグループにあるCCシャープネス設定(Set CC Sharpness)を選択する。

morph006

値はいくつでもいいけど、結合前と大体同じくらいの尖鋭度になるように「80%」とした。ここで設定したシャープネス値は「エッジ・ウェイト」とも呼ばれるけど、必ずしもエッジを選択しないと設定できないわけではない。LightWaveに限ったことではないけど、マップ類はすべてポイントで管理されているので、エッジ単位でなければエッジ・ウェイトを設定できないなんてことはない、というのは勘の良い人ならすぐ気付くはず。

再度、左目を閉じるモーフを右目に反転複製する。今度は次の画像のとおり左右対称になった。両目ができたらオブジェクト・ファイルを保存する。

morph006a

レイアウトに移り、アイテムプロパティウィンドウの「変形タブ」を選択し、変位プラグイン追加から「Morph Mixer」を選択する。オブジェクト・ファイルをちゃんと保存していれば、自動的にエンドモーフ(モーフ・マップ)が読み込まれ、レイアウト内のオブジェクトにも反映される。以後、オブジェクト・ファイルを更新する度に自動的にモーフ・マップの増減と変更が反映されるようになるけど、たまにクラッシュするので適宜シーン・ファイルも保存しておく。

morph007

モーフミキサーのプロパティを選択すると、次の画像のような設定パネルが表示される。グループ化した部位が階層化されて表示される。

morph008

パネル左下の「オプション」を選択すると「スライダー範囲を設定」を選択できる。

morph009

モデラーでのモーフ・マップは適用量「100%」の状態を編集しているわけだけど、レイアウトでは適用量を任意の範囲に拡大又は制限できる。極端な話、「1000%」や「-300%」なんていう指定も可能なんだけど、アニメーションとして動かしてみたら思っていたより変位量が足りなかったとか、海外アニメのカートゥーンのようにもっと大袈裟にしたいといったケースに対応するためのもので、動きの範囲が限られている人間の表情モーフを作る上では使う機会はほぼないと言って良い。最低値を「0」にしておいてもいい。

morph010

両目のモーフ適用量を100%にしてテスト・レンダリングしてみたところ、まぶたの裏にあるはずの目が見えてしまい、寝ている人にマジックで目を落書きされてしまったみたいになってしまった。理由は明快で、SSSの深度を100mmとありえないくらいの値にしているために、皮膚の表皮にあたる半透明部分が想定よりも深くなっていて、目が透けて見えている。

morph011

SSSの設定を見直すのが一番いいんだけど、一応悪あがきとして目の位置をモーフ・マップを利用して頭の中まで後退させるという方法を使ってみた。次の画像のように、まぶたに目は映らなくはなったんだけど、眼窩にぽっかりと穴が開いているのは変わらないため、結局眼窩の影がまぶたに映り込んでしまうという結果になった。

morph012

遠景なのであまり目立たないけど、顔をアップにすると細かいところに問題が起きているので、いずれにせよSSSの設定は近いうちに見直さなければならなかった。

ひとまず、Epidermis DistanceとSubdermis Distanceを「10mm」に修正した。

morph013

SSSを修正してレンダリングしたのが次の画像。影の境界線がやや鋭くなって肌がマットな感じになってしまったけど、モーフで問題が起きるのを回避するにはこのくらいにする必要がある。また、影が鋭くなってしまう問題についてはライティングの方向を見直すことで少し改善できる。

morph014

口を閉じるモーフの作成

同様にして、口を閉じる「MOUTH.CLOSE」モーフ・マップを作成していく。まぶたは筋肉と皮膚だけでできていて骨は入っていないので顔の輪郭には影響しないんだけど、口の場合は開閉によって顎の骨が動くため、顔の輪郭にも影響が出る。

最初は強引に下唇を引き上げて口を閉じようとしてみたけど、全体的に位置が高く、不自然になってしまった。

morph015

そこで、口を全体的に下げてみた。多少は顔のパーツの配置のバランスは改善したけど、顎が長く面長に見えるのはあまり改善しなかった。二次元アニメでは口と顎が必ずしも連動しているわけではないので、輪郭をいじらないようにモデリングする方法もないことはないけど、口が開いている状態を先にモデリングしてしまったので輪郭をいじらないほうが無理がきてしまった。

morph016

更に、口が完全に閉じるまでモーフ・マップを調整し、下顎を少し上げて顔の輪郭を整えた。しかし、今度は口が完全に閉じてしまったことでどこに口があるのか判りにくくなってしまった。

morph017

口が開いている状態を基準にしていたスケッチ色の配置を見直し、上唇と下唇を色分けする。その際、異なるスケッチ色が隣り合わないように注意する。スケッチ色が隣り合っていると想定外のところに境界線が引かれてしまう原因になる。

morph018

スケッチ色の再塗り分けが終わったら、次の画像のようにモーフ・マップで口を閉じてみて、唇の上下のスケッチ色が隣り合っていることを確認する。

morph019

再びレイアウトに戻り、unReal Xtreme2のToon Tracerピクセルフィルター・プラグインのパラメータを調整する。口を閉じている状態を基準にスケッチ色を塗り分けたので、今度は口が開いていると輪郭線が引かれなくなる。そこで、境界設定で「深度境界」を追加し、「深度しきい値」をひとまず「50mm」とした。

morph020

「MOUTH.CLOSE」モーフ・マップの適用量100%でレンダリングしてみたのが次の画像。口が閉じていても輪郭線が引かれているのがわかる。口の位置が判りやすくなった。

morph021

次の画像は「MOUTH.CLOSE」モーフ・マップの適用量90%のもの。輪郭線は引かれなくなるものの、口の中の影が赤く見えるようになるので、口が行方不明になったりはしない。

morph022

次の画像は「MOUTH.CLOSE」モーフ・マップの適用量50%のもの。

morph023

次の画像は「MOUTH.CLOSE」モーフ・マップの適用量0%、つまりベース・モデルのもの。これまでは口の向かって右側に輪郭線が引かれていたけど、深度境界を指定したことによって向かって左側に輪郭線が引かれるようになっている。若干口元の印象が変わった気もしないでもないけれど、特に不自然なところはないので、Toon Tracerの設定はこれで仮決めとする。

morph024

表情集

morph026
視線右
morph027
視線左

 

morph028
怒りの表情
morph029
悲しみの表情(要見直し)

関連記事