【Blender 5.1】ジオメトリノードのためのマトリックス入門|位置・回転・スケールを行列で理解する

blender
記事内に広告が含まれています。

BlenderのジオメトリノードにはTransform Geometryノードがあり、
移動・回転・スケールを直接操作できます。

一方で、Matrix系のノードを使って
同じようにトランスフォームを行うこともできます。

マトリックスとは行列のことです。
Transform Geometryノードも内部的にはマトリックス(行列)で変換していますが、
Matrix系ノードを使うことで、その仕組みをより直接的に扱うことになります。

ただ、行列にあまり馴染みがないと、
これらのノードは直感的に理解しづらく感じるはずです。

そこでこの記事では、まず
「どう値を入れると、どう動くのか」
という実用的な視点から整理していきます。

マトリックス(行列)は座標を変換する仕組みですが、
ここでは3Dのトランスフォーム(移動・回転・拡大縮小)に絞って、
最低限の知識をまとめます。

そのうえで、ジオメトリノードでの扱いに繋げていきます。

※ちなみに、行列計算ができる必要はありません。あくまでも、内部の計算に興味があるというマニアックな方とか、とりあえず知っておきたい方向けの解説です。回転とか移動の数値を入れるだけで動かせるノードもあるので、この記事の内容は「ふーん」でスルーして全く構いません!!

はじめてマトリクスノードを触るって方にわかりやすく解説してみた動画を作成しました。

これを見てからこのブログを読むことをオススメします。

スポンサーリンク

そもそもマトリックスとは何か

マトリックスとは行列のことです。行列とは、数値を格子状に並べたものです。

マトリックス(行列)

[]の中に数字を並べたもの。右図のようにいろんなマトリックスがある。※()に入れることもある

行と列

横に並んだものを行、縦に並んだものを列といいます。横に3行、縦に2列数字が並んだ行列を3×2行列などといいます。

ジオメトリノードで使うマトリックス

ジオメトリノードでトランスフォーム(移動・回転・スケール)に使うマトリックスは4×4行列です。

Combine Matrixノードに、それぞれの行列の成分の値を入力して行列を作ることができます。

行列はただの数字の並びに見えますが、3Dではこれが座標を変換するためのルールとして使われます。

「座標 × 行列 = 新しい座標」になる

つまり行列は、「どう動かすか」をまとめた装置です。

スポンサーリンク

行列の計算

マトリックスでどうやってトランスフォームをするのかってことなんですが、とりあえず基本的な行列の計算について説明します。

マトリックス(行列)の足し算

行列の足し算は同じ行と列にある値を足すだけです。

例えば
ベクトルa…[5 2]
ベクトルb…[3 5]

を足すと、合成されたベクトルの座標が出ます。

ベクトルを行列で表す
ベクトルP…
[X(xの座標の位置) Y(yの座標の位置)]
※実際は縦にして列でベクトルを表すことが多いです。

これは移動・回転・スケールなどのトランスフォームに使われる計算ではありません。トランスフォームの基本演算では、行列の足し算は使われず、主に行列の掛け算によって変換の合成が行われます。

一応、行列の足し算とはこういうルールです、という説明をしてみました。
行列の足し算を記号であらわしたもの↓

(abcd)+(efgh)=(a+eb+fc+gd+h)\left( \begin{array}{cc} a & b \\ c & d \end{array} \right) + \left( \begin{array}{cc} e & f \\ g & h \end{array} \right) = \left( \begin{array}{cc} a+e & b+f \\ c+g & d+h \end{array} \right)

マトリックス(行列)の掛け算

行列の掛け算は左の行列の●行と、右の行列の■列を取り出して、
対応する要素を掛けて、その合計を●行■列の成分にします。(足し算に比べて複雑すぎるルール…!)

行列の掛け算を記号であらわしたもの↓

(abcd)(efgh)=(ae+bgaf+bhce+dgcf+dh)\left( \begin{array}{cc} a & b \\ c & d \end{array} \right) \left( \begin{array}{cc} e & f \\ g & h \end{array} \right) = \left( \begin{array}{cc} ae+bg & af+bh \\ ce+dg & cf+dh \end{array} \right)

この掛け算を使って、あるベクトル[x y]を変換することができます。ある変換行列をベクトルに掛けるだけです。

[xAyA]=[11A11A][xAyA]\begin{bmatrix} x’\vphantom{\Large A} \\ y’\vphantom{\Large A} \end{bmatrix} = \begin{bmatrix} 1 & -1\vphantom{\Large A} \\ 1 & 1\vphantom{\Large A} \end{bmatrix} \begin{bmatrix} x\vphantom{\Large A} \\ y\vphantom{\Large A} \end{bmatrix}

こうして、新たなベクトル[x’ y’]を作ることができます。

図の中で、変換行列を使って、具体的に[2 1]のベクトルを[1 3]に変換しています。

これは2次元ですが、3×3行列を使えば3次元の形を変形することができます。こうして行列を掛けることで、ベクトルの位置や向きを変えるというのが、トランスフォーム変換のざっくりとした仕組みです。

新しい位置 = 行列 × ベクトル

ただ、これだけでは「どんな行列をかけると、ベクトルがどう変形するのか」は分かりません。
変換行列は、ベクトルをどのように動かすかというルールを表しています。
ここからは、そのルールの中身を少しずつ見ていきます。

スポンサーリンク

スケール(拡大・縮小)変換

では具体的に拡大縮小はどう計算するのかやってみます

例えば、X方向に2倍、Y方向に3倍にスケール変換したい場合、変換行列である

[2A00A3]\begin{bmatrix} 2 \vphantom{\Large A}\, & \,0 \\ 0 \vphantom{\Large A}\, & \,3 \end{bmatrix}

を掛けます。

右図のように、例えば
[1 1]ベクトルにかけると、
[2 3]になり、確かにX方向に2倍、Y方向に3倍にスケール変換されています。

しかし、この変換行列はどうやって作るのでしょうか?

変換行列はどう作る?

上の図を見ながら読んでほしいんですが、まず座標には、

x方向の基準ベクトルとなる
大きさ1のベクトルi…[1 0]

y方向の基準ベクトルとなる
大きさ1のベクトルj…[0 1]

があります。これは、座標の基準となる、基底ベクトルと呼ばれます。

X方向に2倍、Y方向に3倍にスケール変換したい場合

ベクトルiを2倍にして[2 0]
ベクトルjを3倍にして[0 3]
にします。基準となるベクトル(基底ベクトル)を変換すると、その組み合わせで表されるすべての点も同じように変換され、格子全体の形が変わります。

なので、この変換された基底ベクトルを列として並べることで、変換行列を作ることができます。

[2A00A3]\begin{bmatrix} 2 \vphantom{\Large A}\, & \,0 \\ 0 \vphantom{\Large A}\, & \,3 \end{bmatrix}

これを3次元にするには、3×3の変換行列を作ります。例えば、X方向に2倍、Y方向に3倍、Z方向に1.5倍スケール変換したい場合、変換行列は以下のようになります。

[2A000A300A01.5]\begin{bmatrix} 2 \vphantom{\Large A}\, & \,0 \, & \,0 \\ 0 \vphantom{\Large A}\, & \,3 \, & \,0 \\ 0 \vphantom{\Large A}\, & \,0 \, & \,1.5 \end{bmatrix}

見た目からも、行列の対角成分が各軸方向のスケールを表していることがわかります。

スポンサーリンク

回転の変換

回転は少し複雑ですが、本質は同じです。

回転も、基底ベクトルを変換したあとのベクトルを並べて変換行列を作ります。

まず基底ベクトルの

ベクトルi…[1 0]
をθ回転すると
[cosθ sinθ]になります。

ベクトルj…[0 1]
はX軸方向から90°回転したところからスタートしているので90°足して、さらにθ回転すると、
[cos(θ+90°) sin(θ+90°)]
加法定理より
[-sinθ cosθ]になります。

これを列方向に並べて

[cosθAsinθsinθAcosθ]\begin{bmatrix} \cos\theta \vphantom{\Large A} & \, -\sin\theta \\ \sin\theta \vphantom{\Large A} & \cos\theta \end{bmatrix}

θ回転の変換行列になります。

3次元だと、Z軸回転の変換行列は

[cosθAsinθ0sinθAcosθ00A01]\begin{bmatrix} \cos\theta \vphantom{\Large A} & \, -\sin\theta \, & \, 0 \\ \sin\theta \vphantom{\Large A} & \cos\theta \, & \, 0 \\ 0 \vphantom{\Large A} \, & \, 0 \, & \, 1 \end{bmatrix}

X軸回転の変換行列

[1A000Acosθsinθ0Asinθcosθ]\begin{bmatrix} 1 \vphantom{\Large A} \, & \, 0 \, & \, 0 \\ 0 \vphantom{\Large A} \, & \, \cos\theta \, & \, -\sin\theta \\ 0 \vphantom{\Large A} \, & \, \sin\theta \, & \, \cos\theta \end{bmatrix}

Y軸回転の変換行列

[cosθA0sinθ0A10sinθA0cosθ]\begin{bmatrix} \cos\theta \vphantom{\Large A} \, & \, 0 \, & \, \sin\theta \\ 0 \vphantom{\Large A} \, & \, 1 \, & \, 0 \\ -\sin\theta \vphantom{\Large A} \, & \, 0 \, & \, \cos\theta \end{bmatrix}

軸のところは1を掛けて固定するので、回転する平面にだけ cos と sin が出てきます。

スポンサーリンク

移動(トランスレーション)は特殊

実は「移動」は普通の3×3行列では表せません。

右図のように、適当な3×3の変換行列で変換してみると、どうしても他の軸の座標同士がまざってしまい、平行移動できません。

そこで使うのが 4×4行列 です。

[100Tx010Ty001Tz0001]\begin{bmatrix} 1 \;\; 0 \;\; 0 \;\; T_x \\ 0 \;\; 1 \;\; 0 \;\; T_y \\ 0 \;\; 0 \;\; 1 \;\; T_z \\ 0 \;\; 0 \;\; 0 \;\; 1 \end{bmatrix}

これを変換行列にすれば変換後の行列が以下のようになり、それぞれの軸で簡単に移動できるようになります。

[x+Txy+Tyz+Tz1]\begin{bmatrix} x + T_x \\ y + T_y \\ z + T_z \\ 1 \end{bmatrix}

※Tx, Ty, Tzはそれぞれの軸の移動量

最終的に1×4行列が出てきてるし、1っていう謎の数字出てきてますが、最終的な座標としては最初のxyzの位置のみを考慮するので問題ないです。

スポンサーリンク

変換マトリックスのルール

  • スケール
  • 回転
  • 移動

4×4行列を変換行列にすると、これらを 全部まとめて1つの行列にできる のが便利です。(人間からはわかりにくいけど、機械からみると便利ってことです)

複数の変形を変換行列一回掛けるだけで適用できるので計算も早くなります。

では今までの変換をまとめた4×4マトリックスの変換ルールを見てみます。

  • スケール・回転
    左上の3×3行列部分で行います。
    • 対角線に並ぶ値でスケール
    • cosθ、sinθと軸に1を入れることで回転
    • ある軸方向に引き延ばしたせん断変形もできます。(詳細は後述)
  • 移動(トランスレーション)
    4列目に値を入れると各軸の移動ができます

対角線上に1が並んだマトリックスは単位行列といい、掛けても同じ位置が出てくるので、何も移動・変形させません。

基本的には上3行部分で変形・移動させます。

射影変換

4行目は、ある数値が入っている場合

[xpypzpwp]=[m11m12m13m14m21m22m23m24m31m32m33m34m41m42m43m44][xyz1]\renewcommand{\arraystretch}{1.6} \left[ \begin{array}{cccc} x_p \\ y_p \\ z_p \\ w_p \end{array} \right] = \left[ \begin{array}{cccc} m_{11} & m_{12} & m_{13} & m_{14} \\ m_{21} & m_{22} & m_{23} & m_{24} \\ m_{31} & m_{32} & m_{33} & m_{34} \\ m_{41} & m_{42} & m_{43} & m_{44} \end{array} \right] \left[ \begin{array}{cccc} x \\ y \\ z \\ 1 \end{array} \right]

と言う風に新たな座標のWpの部分に数値が入ります。これを1にするために各座標を割って最終的な座標を作ります。

xndc=xpwp,yndc=ypwp,zndc=zpwpx_{\text{ndc}} = \frac{x_p}{w_p}, \quad y_{\text{ndc}} = \frac{y_p}{w_p}, \quad z_{\text{ndc}} = \frac{z_p}{w_p}

投影のための計算では、行列の結果に「Wpで割る工程」があり、それによって遠近感(射影)が生まれます。
Transform Geometryノードの変換ではこの工程は基本的に使われないため、透視的な効果は発生しません。つまり、特別なノード(Project Pointノード)を使わない限り、4行目に値を入れても正しい効果が出ません。

射影変換をやってみる

では実際射影変換をやってみます。そのためにはProject PointノードとSet Positionノードを使って変換します。

Project Pointノードは得られた同次ベクトル(次元を1つ増やして、同じ点を別の表現でも表せるようにしたベクトル)をW成分の絶対値で割るという工程を実行してくれます。この最後の処理は 透視除算(perspective division) と呼ばれます。

では4行目の1列目に1を入れてみます。

すると計算結果のベクトルは
[x y z x+1]になります。最後のx+1でこのベクトルの値すべてを割って最終的なベクトルにします。

すると、xの位置に応じてスケールが変わるような射影変換になります。

4行目の2列目に値を入れればyの位置に応じたスケール、

4行目の3列目に値を入れればzの位置に応じたスケールになります。

4行目の4列目に値を入れれば全体的なスケールが変わります。

基本的には遠近(パース)をつけるための変換であり、普通のトランスフォーム変換ではあまり使われないのかな…?という印象です。ただ、ある軸の位置に応じてスケールしたい、ということって結構あるので、そういう変形にも使えそうです。

スポンサーリンク

ジオメトリノードで動かしてみる

Combine Matrixノードに値を入れてスケールと回転変換をしてみます。

右図は入力したマトリックスと結果の画像です。

  • スケール
    左3×3の対角線上の値を変える
  • 回転
    左3×3回転軸以外の平面にcosθ、sinθなどを入力する
  • せん断
    1列目は今のx座標の位置
    2列目は今のy座標の位置
    3列目は今のz座標の位置
    に値を掛けて計算に加える
    1行目はx座標
    2行目はy座標
    3行目はz座標
    に掛けた値を合成する
    結果として斜めにひき伸ばしたような変形ができます。
  • 移動
    4列目に値を入れると、
    1行目はx
    2行目はy
    3行目はz
    方向にその量だけ移動します。

特にせん断は自分はジオメトリノードで文字を打って斜体にしたい場合によく使ってました。

※行列を直接指定する他に、最初にスケール、回転のマトリックス乗算でもできます

スポンサーリンク

面白い形を作ってみよう

Transform Geometryノードを使うと、単一の値しか受け付けないので、上記で言ってた

  • スケール
  • 回転
  • 移動
  • せん断

の組み合わせのような変形しかできません。

フィールド値を使えるようにするために、Transform PointノードとSet Positionノードを使って変換していきます。

マトリックスにzの位置座標のsinの値を2行目1列目に入れると、ねじれたような形ができます。

他の軸にも位置に応じた三角関数の値を入れていくと、ねじれ、とかひねったような形が重なって、なんか、謎の複雑な物体が簡単に作れます。

右の動画は行列の値を変えてキューブを変形していくアニメーションです。

スポンサーリンク

マトリックスの利用

行列には今回紹介した変換以外にも、逆行列や転置行列など、さまざまな性質や計算があります。ジオメトリノードにもそれに対応したマトリックス系のノードが用意されています。

また、これらの機能が追加されたことで、ジオメトリノード内にTransformのソケットが登場し、ローカル座標系を意識した変換や、より柔軟な動きの制御ができるようになりました。

もともと行列は、機械工学やCGの分野で物体の位置や向きを正確に制御するために使われているものです。そのためジオメトリノードでも、単なる変形だけでなく、アニメーションやシミュレーションなど、より複雑な動きを扱う際に重要な役割を持ちます。

こうした応用については、別の記事で詳しく解説していきたいと思っています。

スポンサーリンク

関連記事

  • マトリックス系ノードの紹介
    マトリックス変換を便利に使うために、その他のマトリックス計算やトランスフォームに使えそうなノードを紹介していきます。
  • ジオメトリノードで作るマトリクスロボットアーム:Multiply Matricesで親子関係を再現する方法
    マトリックス変換をつなげて親子階層を作って、ジオメトリノードでリグっぽい仕組みを再現する方法を解説しています。
  • 回転系ノードについて解説
    インスタンスの回転、ベクトル回転、回転の補間やクォータニオンなど、回転系ノードの使い方を網羅。
  • カーブの接線・法線・従法線を解説:Tiltのトラブルを解決する
    カーブの接線・法線・従法線とは何かを解説し、Set Curve Normalノードを使ってねじれを修正する方法を説明

ジオメトリノード記事のガイドです。ジオメトリノード関連の記事をまとめています。

コメント