「moreover lwjgl」 11 現代的な行列変換 ~JOMLを使って~
タイトル前回の丸パクリですね
今回は、行列を使って物体を動かしてみます。行列による物体の動き(行列変換)については、前に(適当に)まとめた記事があるので、参考にしてもらえると嬉しいです。
今回は、物体を動かす行列をGLSLに受け取って頂点座標を変換してもらいます。その時に行列はJavaプログラムの方で先に計算しておいたものを渡すのですが、平行移動などの簡単な計算はよくても、任意軸周りの回転や透視投影などはとても難しいので、そのような計算をしてくれるライブラリーを使ってみたいと思います。
それが、”JOML”です。
この”JOML”では、面倒な行列の計算だけでなく、ベクトルの概念やクォータニオン(四元数)、透視投影でのカリング処理、そして任意軸回転を表す"AxisAngle"なども独自に定義されており、色々な処理をしてくれます。
そして、JOMLはなんとMITライセンスでして、改変、商用利用でもなんでもしていいのです。ただし、ソースコードかライセンス用のファイルに、MITライセンスの全文かそれが載ったWebサイト( The MIT License (MIT) | Open Source Initiative )のURLを掲載するようにしてください。
また、JOMLはMavenやGradleなどのビルドツールを使うことも出来ます。(私は、LWJGLをEclipseで適当に使えるようにしてしまったので、ソースコードの一部として使うことにしています。)
ちなみに、JOMLはLWJGLのブログ http://blog.lwjgl.org でも取り上げられていました。
ということで、ソースコードとGLSLを…(JOMLのライセンスは各自でやって下さい…)
解説(jomlは青色で)
javaファイルの方から…
50行目 : 投影変換、モデル変換、ビュー変換それぞれの変換行列を保存するバッファーを宣言します。
120行目 : 投影変換行列に、透視投影の行列を掛けています。
JOMLで使える主な行列変換処理とその説明、行列式です。
JOMLの行列計算などのやり方は簡単で、各メソッドを実行するだけで、その行列演算を代入した行列がまた返ってくるというものです。また、それらは次のように省略できます。
このように、ドットでつなぐことが出来ます。
メソッドの中には、"rotate"と"rotation"、"translate"と"translation"のように、似たものがありますね。これらにおいて、"rotate"などの英語の動詞は今の行列に「回転」行列を「乗算」しており、"rotation"などの英語の名詞は今の行列を「回転」行列に「置き換え」ています。つまり、"rotation"を今の行列に掛けるのが"rotate"です。
ドットで省略するときなどに、"rotation"を掛けてしまったら、前までに掛けていた行列を無視してしまうので気をつけたほうがいいですね…
121行目 : モデル変換行列に、平行移動と拡大と回転の行列を掛けています。
122行目 : ビュー変換行列に、LookAt(カメラの位置と向きと上方向を一気に指定する)行列を掛けています。
178~187行目 : GLSL中のuniformに行列を代入しています。
glUniformMatrix4fvでは、第2引数で、転置させるかどうかを決められます。これによって、DirectXで決めた行列をそのままOpenGLでも使うことが出来るという利点があります。(両用する人ってなかなかすごいですね…)
アニメーションなどで様々な行列を使いたい場合には、
uniform mat4 Models[10];
などのように配列としてGLSLで定義して、
glUniformMatrix4fv(int location, int count, boolean transpose, FloatBuffer value);
の、countを10にしてvalueに行列のすべての値を、順番に入れるようにして渡せば、GLSL内で、javaの配列のように扱うことが出来ます、
GLSL~
v4~6行目 : uniformでそれぞれの行列を受け取ります。
v9行目 : 頂点座標に行列を掛けあわせて最終的な表示場所をgl_Positionに代入しています。
GLSLでは行列の掛ける順番は、
Projection * View * Model * vertex
となっています。
これは、Java内ですべての行列を掛けた時も同じです。
このようにして行列をかけると…
もちろんこのような形の四角形を作ったわけではなく、正方形から視点や形、投影法を変えてこの形に見えるようにしました。
行列などによる物体の動きは楽しいですねw