読者です 読者をやめる 読者になる 読者になる

デジタル・デザイン・ラボラトリーな日々

アラフィフプログラマーが数学と物理を基礎からやり直す

射影変換(ホモグラフィ)について理解してみる その13

前回、猫画像1枚を3D回転させてみたが、CSSの3D回転ジェネレータの「3D CSS Tester(github)」を見つけたので、これをCSSでなく敢えてCanvasで動きを真似てみます。

3D回転する際には、一般的には三角形に分割して表現します。
参照:テクスチャマッピングを理解してみる その2

下図は左側がIE上で表示、右側がChrome上で表示したものなのですが、三角形に分割して表現した際にIE上では微妙に線が見えてしまいます。ひどいよねIEさんって。
f:id:Yaju3D:20140310011843j:plain

射影変換で表示した場合は、画像データから生成した上で表示しているため、遅いですが変形した画像は綺麗に表示されます。
更に今回は、使用した2枚の画像に透過色が含まれています。
f:id:Yaju3D:20140311215405p:plainf:id:Yaju3D:20140311215412p:plain
射影変換して透過色の状態で画像を重ねる方法は、「射影変換(ホモグラフィ)について理解してみる その10」で説明した通り、隠しCanvasに一旦描画して表示Canvasに転送する方式により描画コストが高くなっています。

■3D回転
今回3D回転ということで、3Dライブラリ(glMatrix.js)の「Perspective」、「LookAt」メソッドを使いました。参考:glMatrix.js でイメージ投影

this.pMatrix = mat4.perspective(fovy, wx / wy, 0.1, 100.0);
this.vMatrix = mat4.lookAt(new Float32Array([0, 0, 4.5]), new Float32Array([0, 0, 0]), new Float32Array([0, -1, 0]));

「Perspective」メソッドは、透視投影(遠近感を表現)です。
「LookAt」メソッドは、カメラの位置、姿勢を決定しています。
glMatrix.jsは、OpenGLを参考に作成されているので、「gluLookAt」で調べると動作が見えてきます。

中身を理解したい場合は下記サイトが参考になります。自分でも後で調査して、自分なりに理解できるような記事を書く予定です。
(1) gluLookAt はどんな matrix を生成するのか?
(2) gluLookAt はどんな matrix を生成するのか?

あと、3D回転した際に他の画像と重なりの描画順に「Zソート」(Z座標が大きいのから順番に描画する)を使っています。

// Zソート
this.planes.sort(function (a, b) {
    return b["z" ] - a["z"];
});

反省点として、今回は2つとも同じサイズの画像(200x200)を使っているのですが、違うサイズの画像にした場合に中央に表示されません。ここらへんの座標計算の理解度が弱いため、いずれ克服した際には修正したいと思っています。

■プログラム
今回もTypescriptで作成して、jsdo.itには変換されたJavascriptで投稿しています。今までは投稿する前に変換されたJavascriptにコメントを追記する作業をしていたのですが、Typescriptが改良されてコメントを含めてJavascriptに変換されるようになっていたので、手間が無くなり非常に嬉しいかぎりです。

今回は画像を2枚使っていることもあって、画像のプリロードクラスを作成しました。まーJQueryを使えば簡単なのですが、勉強も兼ねている為、あえて自作しています。
せっかくTypescript使っているのでクラスを意識して作ってみました、平面と軸の表示には継承を使ってます。オブジェクト指向の方がプログラムは組みやすいです。

Typescriptで組んだソースリストは、github/Rotate3Dに公開しました。