第1回「掟を破ったら空間がブラックホール化した!」|ド文系3DアニメーターのMaya行列入門

当ページのリンクには広告が含まれています。

3DCGをやっていていると、避けては通れないモノがあります。

それが行列(Matrix)です。

しかし、多くの3DCGアーティストは「行列(Matrix)」を意識(理解)することなくMayaやBlenderといったDCCツールを使用しています。

実際に私もその1人です(まだ勉強中で完全に理解したわけではないので過去形にはできません)。

とはいえ、RiggingAnimationといった分野では、この「行列(Matrix)」を理解することが非常に重要です。

特にRiggingの分野では、「行列(Matrix)」を理解することなしに高度なリグを組むことは出来ません。

行列を理解すると、今までコンストレイント(Constraint)を何重にも重ねて重くなっていたリグを、スッキリと軽量化できます。

また、アウトライナーの階層を無視した自由な親子関係も作れるようにもなります。

私も長年「行列(Matrix)」については、いずれは勉強しなければ…と思っていました。

しかし、正直な話、ド文系の3DCGアニメーターということもあって「行列(Matrix)」から逃げ続けていました。

言い訳を言わせてもらえば、学習すべき適切な教材がなかったからです。

そんなモヤモヤした時を過ごした後に、Jean-Paul TossingsさんのYoutubeチャンネルの動画に出会ってしまったのです。

Jean-Paul Tossingsさんの動画は、3DCG空間と行列の関係性を直感的に理解しやすい素晴らしい内容です。

英語の動画ではありますが、日本語字幕をつければ内容を理解できないことはありません。

そこから学んだことを自分なりに理解したうえで、Mayaの行列(Matrix)に関する記事を書くことにしました。

Jean-Paul TossingsさんのYoutubeチャンネルの内容は、非常に高度な内容にも及んでおり、正直、まだ理解していない部分のほうが多いです。

そういう理由なので、数学と英語た得意な方はJean-Paul TossingsのYoutubeチャンネルでどんどん先を学んでいってください。

でも、数学と英語が苦手な人は私と一緒にゆっくりじっくり学んで行きましょう。

目次

はじめに

なぜ行列なのか?

リグが驚くほど軽くなる(脱・コンストレイント)階層構造から自由になれる(脱・アウトライナー)修正・変更に強い(脱・作り直し地獄)
これまでの「ペアレントコンストレイント」などは、Mayaが常に裏で「親の動きを見て、子の位置を計算し直す」という重い処理を繰り返していました。
行列を直接コネクション(接続)すれば、計算がシンプルになり、キャラクターが何体いてもサクサク動く「超軽量リグ」が作れるようになります。
「親の子供にしないと動かない」というアウトライナーの見た目上のルールを完全に無視できます(自由すぎる親子関係を構築できる)。
行列をバケツリレーのように繋ぐだけで、構造はバラバラなのに動きは完璧に連動する、自由度の高いモジュラーリギングが可能になります。
従来のコンストレイントは、ジョイントの位置(肘など)をずらすと、オフセットが狂って繋ぎ直しが必要でした。
行列リグなら、16個の数字(バケツの中身)を最新にするだけで、リグの構造を壊さずに配置だけをいつでも「後出しジャンケン」で直せるようになります。

基本的にはコンストレイント(Constraint)から解放されて軽くなる。

そして、親子関係の階層構造から解放されることによって、モジュラーリギングといった高度なリギングが可能になります。

さらに、アニメーターやリガーにとって1番嬉しいのが、この「修正への強さ」でしょう。

従来のコンストレイントを使ったリグの場合、後から「やっぱり肘の位置を3cmずらして」と言われると地獄でした。

いちどコンストレイントを剥がして、新しい場所でつなぎ直す作業が必要でした。

しかし、行列(特にOffset Parent Matrix)を使ったリグならば、位置関係は「16個の数字が入ったバケツ(行列)」として独立しています。

肘の位置を変えても、そのバケツ(行列)の中身を最新の数値に書き換える(更新する)だけでOKです。

構造(コネクション)はそのままに、配置だけを自由に変えることが出来る

まさに、構造の束縛から解放された自由すぎる親子関係と言えます。

Offset Parent Matrixとは

Maya 2020から「Offset Parent Matrix」という機能が追加されました。

今までは、「オフセット用の空グループ(Null)を作り、それを挟むことによって数値を「0」の状態を保つ」必要がありました。

Offset Parent Matrix へは、Attribute Editorからアクセスできます。

Transform Attributesの中の「Offset Parent Matrix」の左側にある▷をクリックします。

すると、「Composition」「Matrix」というタブを切り替えてアクセス出来るようになります。

「Composition」「Matrix」の値は、それぞれ連動しています。

片方を変更するともう一方の数値も変わります。

この「Composition」「Matrix」に、今までオフセット用の空グループのTRS(Translate, Rotate, Scale)の値を入力することによって、チャンネルボックスのTranslateとRotateを『0』、Scaleを『1』の状態にたもったまま、オフセットすることができます。

さらに、Offset Parent Matrixの利点としては、4x4行列に気軽にアクセスできることです。

4x4行列を学ぶうえで気楽に数値をいれてみて、その結果、どのように変化するのかをお手軽に試すことが出来ます。

わたしはこの機能のおかげで、気軽にいろいろと実験してみることができました。

なぜ3x3ではなく4x4行列なのか?

「X、Y、Z」の三次元空間なのだから、3x3行列でも良さそうですが、4x4行列でないといけない明確な理由があります。

Jean-Paul Tossingsさんの「Mastering Matrices for 3D animation」05:36 Translationあたりで視覚的に非常にわかりやすく説明されているのでそちらを見ていただければ直感的に理解できます。

よって、結論だけ申し上げます。

3x3の行列では、原点からの「回転」と「スケール」しか扱うことが出来ないためです。

そのために、3x3行列に1行と1列を追加して1番下の4行目(横)の0, 0, 0, 1の右から3つまでの数値をそれぞれ、(X, Y, Z)のTranslate(移動)の値を入れることで解決されました(1番右側の「1」については後で説明します)。

ちなみに四次元空間の場合は、何x何行列が必要なのかとAI(Gemini)に聞いてみました。
結論は「5x5行列」必要とのことです。
つまり、「n次元空間の移動を含む変換には、(n+1) x (n+1) の行列が必要になる」という、シンプルで美しいルールが成り立っています。
もし、4次元空間でアニメーションさせる必要があったら、5x5行列を使ってくださいね(笑)。

徹底解剖!4x4行列の中身はどうなっているのか?

行列のデフォルトポーズ「単位行列」

行列の中には16個もの数字が入りますが、まずは「何も変化していない、真っさらな状態」を知ることから始めましょう。

これを数学の言葉で「単位行列(Identity Matrix)」と呼びます。

単位行列
1000
0100
0010
0001

このように斜めに「1」が並んだ状態です。

左上の3x3エリアは、数学的には「基底ベクトル(Basis Vector)」と呼ばれます。

これは、その空間における「前・上・横」(Mayaが右手系Y-upなので)を指す3本の矢印のことです。

単位行列の状態

  • X軸が(1, 0, 0)を向いていて長さ1の状態
  • Y軸が(0, 1, 0)を向いていて長さ1の状態
  • X軸が(0, 0, 1)を向いていて長さ1の状態

つまり、すべての軸がどこにも傾かず(回転なし)、かつ100%の長さ(スケール1)であることを意味しています。

よって、これらの3x3エリアの12にすると、対応する軸のスケールが2倍になります。

4x4行列の中身を徹底解説

X-compY-compZ-compW-comp
X-axis(Basis Vector X)X.xX.yX.z0
Y-axis(Basis Vector Y)Y.xY.yY.z0
Z-axis(Basis Vector Z)Z.xZ.yZ.z0
Translation(Position)TXTYTZ1

左上の3x3エリア(ブルー):回転とスケール

この左上の3x3エリアは、「空間を形作る3本の矢印(基底ベクトル)の先端座標」が入っています。

  • 1行目:新しいX軸の向きと長さ(スケール)
  • 2行目:新しいY軸の向きと長さ(スケール)
  • 3行目:新しいZ軸の向きと長さ(スケール)

これら3本の矢印が「どの方向を向いているか」回転が決まります。

そして、「矢印の長さがどれくらいか」スケールが決まります。

ここの数値を直接いじって回転とスケールの値を入力するのは至難の業(というよりも無理)です。

ためしにこの3x3エリアに様々な数値を入れてみてください。

様々なシェイプに歪む(Shearする)はずです。

もとに戻すには、上で紹介した単位行列を入力すれば良いので、怖れずにいろんな数値を入れてみてください。

一番下の4行目(オレンジ):移動(Translation)

場所を示すエリアです。

もっとも直感的にわかりやすい所です。

TX(X座標)、TY(Y座標)、TZ(Z座標)を表します。

3x3行列だけでは、移動を表現出来ないので、この4行目が必要になります。

この4行目のオレンジの部分の3つの数値(一番右の「1」は触らないで!)に、いろいろと数値を入れてみてください。

ここに入れた数値は完全に意図したもの(X、Y、Zの各Translationの値)になっていることが確認できます。

当然のことながら、「0, 0, 0」を入力すれば原点に戻ります

一番右の4列目(赤):W成分(スイッチ)

計算の最後に場所(点)?それとも向き(ベクトル)と判断するための数値です。

  • 上から3つの「0」:X、Y、Z軸の「向き」を計算する際に、移動(4行目)の値を無視するために使われます。
  • 右下の「1」:「場所」を計算する際に、4行目の移動成分を正しく加算するために使われます。

このエリアの数値をいじってはいけません!

4列目(縦並びの0, 0, 0, 1)は、「触らぬ神に祟りなし」でいじってはいけません!
では、なぜいじっては行けないのか?

  • アニメーターが扱う行列(Affine変換): 移動・回転・スケール。これらは4列目(縦並びの)が 0, 0, 0, 1 であることが大前提の計算です。
  • もし数値をいじると: 空間そのものが歪んでしまいます
  • 3DCGでこの数値が変わる「唯一の瞬間」: 3D空間のモデルを、2Dのモニター画面に映し出すとき。この瞬間にだけ、4列目に数値が入ります。
  • 遠近感の魔法: 遠くのものを小さく見せるための「割り算」をこの4列目で行っています。

4列目はカメラにお任せ!

3DCGでこの数値が変わる「唯一の瞬間」が、3D空間のモデルを2Dのモニター画面に映し出すときです。

この瞬間にだけ4列目(縦)に数値が入ります。

遠くのものを小さく見せるための「割り算」をこの4列目で行っています。

私たちがカメラのレンズ(Focal Length(焦点距離)の値)を変更したり、Near / Far Clip Planeをいじったりする時、その裏でこの4列目が激しく計算されています。

よって、私たちが直接これらの数字をいじる必要はありません

『ユークリッド幾何学』『透視図法』
数学の世界には、平行な線がどこまでも交わらない 『ユークリッド幾何学』 というルールがあります。
私たちが3D空間でリグを組んだりモデルを作ったりしているのは、この真っ直ぐな「歪みのない世界」です。
しかし、私たちがカメラ越しに見る映像には、必ず 『パース(遠近感)』 が存在します。
遠くにある平行な線が、地平線の彼方にある点に集まっていく 『透視図法(パースペクティブ)』 の現象です。
カメラの向きによって一点、二点、あるいは三点透視と呼び方は変わりますが、どれも 「遠くのものが1点に向かってすぼまっていく」 というルールは共通しています。
実は、行列の4列目に数値を入れるという行為は、この 「真っ直ぐなユークリッドの世界」を、あえて「遠近感のあるパースの世界」へと翻訳する作業 なのです。
私たちが普段4列目をいじってはいけない理由……それは、モデル自体をグニャリと歪ませるのではなく、あくまでカメラというフィルター(レンズ)を通してその歪みを表現するのが、3DCGの正しいルールだからです。

特殊なレンダリング手法(テクニカルな例外)
非常に稀なケースとして、テクニカルディレクターやエンジニアが以下のような特殊な表現を狙う際、行列を直接(またはシェーダー経由で)操作することがあります。

  • 特殊な歪みの表現: 映画的な演出で、通常のカメラではあり得ないような空間の歪み(わざとパースを狂わせるなど)を作りたい場合。
  • ノンフォトリアル(NPR)な表現: 2Dアニメのような「嘘のパース」をつけるために、頂点シェーダーの中で行列計算に介入する場合。

実験

移動とスケールは超簡単!

ScaleとTranslateにそれぞれ数値を入れればOK!
Scale.X000
0Scale.Y00
00Scale.Z0
Translate.XTranslate.YTranslate.Z1

移動とスケールに関しては、非常に簡単です。

「Scale.X」に「2」を入れれば、X軸にそってスケールが2倍になります。

そして、「Translate.X」に「2」を入れれば、X軸方向に「2」移動します。

といった具合なので、これ以上の説明は必要ないでしょう。

回転、それが問題だ!

4x4行列の左上の3x3行列で回転とスケールを扱います。

回転をともなわないスケールについては上で説明したように、めちゃくちゃ簡単です。

回転とスケールを一緒に扱うと非常に複雑なので、回転だけ(回転だけでも複雑ですが…)の場合を解説します。

回転の正体は「三角関数」

いきなり全軸を動かすとパニックになるので、まずはシンプルに「Rotate X = 45」の行列の中身を覗いてみましょう。

「Rotate X = 45」の4x4行列の中身
1.0000.0000.0000.000
0.0000.7070.7070.000
0.000-0.7070.7070.000
0.0000.0000.0001.000

行列の中に「0.707」という数字が並びました。

実はこれ、数学の授業で聞いたことがあるサイン(sin)とコサイン(cos)の計算結果です。

45度のサインとコサインは、どちらも約0.707になります。

行列の中の数字は、「モデルを45度傾けるために、座標を0.707倍して混ぜ合わせる」といったことMayaに伝えています。

もうすこし詳しく:

  • 0.707:これが 45度のサイン($\sin 45^\circ$)とコサイン($\cos 45^\circ$)の値です。
  • なぜ同じ数字?:45度のときだけ、サインとコサインは同じ値($\frac{1}{\sqrt{2}}$)になります。
  • 1.000(1行目):X軸を中心に回しているので、X軸自体の向きは変わっていないことを示しています。

Rotate Order(回転順序)による結果の違い

それでは、1軸だけでなく3軸回転させてみましょう。

3軸回転させる場合には、どの軸から順番に回転させるかを決めなければいけません。

それが、「Rotate Order(回転順序)」です。

Rotate Orderが(X, Y, Z)の場合は、「X」「Y」「Z」の順番で回転させます。

例として、「Rotate X = 45、Rotate Y = 45、Rotate Z = 45」のシリンダーを用意しました。

X軸だけでなく、3軸すべてを45度ずつ回転してみた結果が以下のようになります。

Rotate Order : XYZ(全軸に「45度」 )
0.5000.500-0.7070.000
-0.1460.8540.5000.000
0.854-0.1460.5000.000
0.0000.0000.0001.000
Rotate Order : YZX(全軸に「45度」 )
0.5000.854-0.1460.000
-0.7070.5000.5000.000
0.500-0.1460.8540.000
0.0000.0000.0001.000

まったく同じ角度(45度)をいれても、計算の順番が違うだけで行列内の数値はこれだけかわります!

すべてに同じ45度が入った状態ですが、見ての通り、Rotate Orderの違いによって結果が異なります。

シリンダーの向きも違いますが、3x4行列に入った数値も違います。

「-0.707」という数値こそ残っていますが、「0.500」「0.854」といった複雑な数字に書き換わっています。

これは、「45度傾いたものを、さらに別の軸で45度傾けた」ことで、サインやコサインの計算結果がバケツリレーのように掛け合わされた結果です。

そして、この「掛け合わせる順番」Rotate Order(回転順序)であり、行列は掛け合わせる順番によって答えが変わります

マトリョーシカと行列の意外な関係

以前、別の記事「Rotate Order(回転順序)は、右側の軸が親、左側の軸が子になるマトリョーシカのような親子関係だ」 と解説したことがあります。

あの記事を書いた頃は行列について全く知らなかったのですが、今になってみると非常に理にかなっていたことが分かりました。

行列の計算には、右側にあるものから順番に計算していく(右から左へのバケツリレー)」 という鉄則があります。

例えば、Mayaのデフォルト設定である Rotate Order が XYZ の場合 (X→Y→Zの順で計算)の場合、数学的な式ではこのように書かれます。

$$Result = M_{Z} \times M_{Y} \times M_{X}$$

「えっ、逆じゃない?」と思うかもしれませんが、これでいいんです!

一番右に置かれた $M_{X}$ が、マトリョーシカの『一番小さな芯(子供)』 になります。

  1. まず $M_{X}$(一番小さな子供)が置かれる
  2. その左から $M_{Y}$ という親がガバッと被さる
  3. さらにその外側から $M_{Z}$ という一番大きな親(爺さん?婆さん?)が包み込む

こうして、右から左へとバケツリレーのように計算が積み重なって、最終的な1つのマトリョーシカ(完成した行列)が出来上がります。

過去の私が直感的に右側の軸ほど親だと感じていたのは、この行列が右から順に積み重なって、左側で最終的な座標が決まるという性質をなんとなく感じ取っていたのでしょうか。

だとしたら、過去の自分を褒めてやりたい気持ちになってきました(笑)。

この構造が崩れて、軸と軸が重なってしまう現象が、アニメーターの宿敵 「ジンバルロック」 です。

おまけ:非ユークリッド幾何学への挑戦状

「いじるな!」と言われると、いじってみたくなるのが人間の性です。

それでは、せっかくなので、いじってはいけないという4列目(縦)0, 0, 0, 1の値をいじってみましょう。

いじると「空間が歪む」とは、なんとも中二心をくすぐる言葉です。

というわけで実験してみました。

禁断の実験1

まずは、動画を見てください。

この動画はCubeがZ方向に前後しているだけのアニメーションですが、空間が歪んでいることが確認できます。

4x4行列の数値としては、1番右側の4列目(縦)に、0.5, 0, 0.5, 1 の数値を入れました。

cubeのアニメーションはZ軸方向に「+10」移動して、「0」にもどって、「-10」に移動して、最後に「0」に戻るという非常に単純なものです。

それなのに、このような歪んだ空間によって奇妙なアニメーションが完成しました。

非ユークリッド空間恐るべし!

「空間が歪むとどういうことが起こるのか」と期待していたのですが、動画を見ていただければわかるように、微妙(?)な結果が出ました。
しかし、スケールをいじっていないのに、あのような不安定な挙動になったことは、しっかりと確認できます。

禁断の実験2

最後に4x4行列の1番右下の「1」は何を意味しているのかを見てみましょう。

なんと、スフィアが消失してしまいました!

「だから、どうした?」
かもしれませんが、今回の記事のクライマックスのひとつです…。

アフィン変換という「世界の掟」の崩壊

私たちが普段 Maya で行っている移動・回転・スケールは、「アフィン(Affine)変換」というルールに基づいています。

このルールの絶対条件は、「平行な線は平行なまま保つ」ことであり、これを数学的に守るためのアンカー(重し)として、右下に1 があるのです。

ここを 0 にしてしまうと、アフィン変換という掟が消滅します。

するとスフィアは、「形を保ったまま移動する」というユークリッド幾何学の保護を失い、計算上「形を維持できない存在」になってしまうのです。

場所を失い、無限の彼方へ…

3DCGの数学において、右下の 1 は、そのオブジェクトが空間内の「どこか(点)」に存在していることを証明するフラグです。

  • 「1」のとき:「場所(点)」として認識され、4行目の移動成分(TX、TY、TZ)が正しく加算されます。
  • 「0」のとき:スフィアは「場所(点)」ではなく、ただの向き(ベクトル)」として扱われます。

場所という概念を失ったスフィアは、パース計算の過程で「無限の彼方」へと追いやられます。

これが、ビューポートから忽然と姿を消す「消失事件」の正体だったのです。

ユークリッド幾何学の終焉

私たちが慣れ親しんでいる「真っ直ぐで歪みのない世界(ユークリッド幾何学)」は、この 1 という数値によって支えられています。

ここを 0 に書き換えることは、ユークリッドの世界から一方的にログアウトし、非ユークリッド幾何学(射影変換)という、平行線すら交わってしまう混沌とした世界へと足を踏み入れてしまうことなのです。

スフィアが消えたあとに待ち受けているのは、上の動画で見たような「空間が引き裂かれる暴走した世界」なのです。

「カーナビ、GPS、そして行列の深淵へ」

調べてみると、非ユークリッド幾何学はGPSの制度維持など、私たちの身近な場所で使われていることがわかりました。

地球の湾曲や宇宙の歪みを記述する世界。

ちなみに、大気圏の湾曲を行列で表すとどうなるのか?

気になってAI(Gemini)にシミュレーションを依頼したところ、4列目の数値は『0.00015』程度になるという驚きの結果が出ました。

私が軽い気持ちでいじった4列目の「0.5」という数値は、現実の世界に当てはめれば「ブラックホールの中心部」に匹敵するような、とてつもない空間のねじれを意味していたようです。

3DCGの行列を学ぶことは、この世界を司る『神の数式』に触れることなのかもしれません。

まとめ

ド文系を自称し、行列から逃げ続けてきた私ですが、実は3DCGアニメーターという仕事そのものが、誰よりも多くアフィン変換をこなす職業であったのだと、今さらながら突きつけられた思いです。

私たちが自由に表現できるのは、Maya(とその他DCCツール)がこの厳密な数学的ルールを完璧に処理してくれているおかげです。

これからは、ビューポートの向こう側に広がる『神の数式』に感謝しつつ、この最強の武器をさらに使いこなしていきたいと思います。

行列は「怖くない」

蓋を開けてみれば、中身はマトリョーシカのような親子関係だったり、sin / cosの計算結果が詰まったバケツのようなものだとわかりました。

とはいえ、私も完全に理解しているわけではありません。

でも、どの数字が、どんな役割を担っているのかを知ることで、行列に対する恐怖心はかなり少なくました。

次回予告

今回は、4x4行列の「正体」に迫ってみました。

次回は、「Matrix vs Constraint」でリグの軽さがどのくらい変わるのかを検証します。

コンストレイント(Constraint)に頼らず、行列同士を直接繋ぐことで生まれる「超軽量リグ」

どのくらい軽くなったのかを体感できるようにベンチマークシーンを用意したので、ぜひご自分のPCで確かめてみてください。

さらに、その次には、階層に縛られない「自由な親子関係」

その仕組みをMayaを使ってどう構築していくのか、私なりの試行錯誤を含めて、まとめていきたいと思います。

実際、私自身もまだ実験を繰り返している最中です。

行列を使いこなすことで見えてくる「新しいリギングの形」を、できるだけ分かりやすく整理して共有できればと考えています。

内容がまとまり次第更新しますので、楽しみにお待ちいただけると嬉しいです。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

フリーの3DCGアニメーター。
メインツールはMaya(使用歴20年以上)です。お仕事ではSoftimage(XSI)やMotionBuilderの使用経験もあり。思いに手付け(キーフレームアニメーション)が多いですが、キャプチャーもいけます。サブスキルとしてはリグ(Maya限定ですが)も少々いけます。

ゲームが昔から大好きなので「ゲーマー」としての側面からもいろいろ発信出来ればと考えています。
CG歴よりもゲーマー歴のほうがずっと長いもので(笑)。

twitterアカウント
@inopoa1

よろしくお願いします。

コメント

コメントする

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

目次