‘Programming’ カテゴリーのアーカイブ

ジオメトリパイプライン

2010.05.06 08:25 PM

ジオメトリパイプラインの超私的メモ。毎度の超私的メモでスミマセン。
このサイトの記事を参考にさせていただきました。ありがとうございました。

ジオメトリパイプラインとは3Dオブジェクトを画面に描画するための座標変換のこと。

変換の流れは以下。

1 . ローカル座標で3Dオブジェクトを組み立てる。
2 . ワールド座標変換
3 . ビュー座標変換(またはカメラ座標変換ともいう)
4 . プロジェクション座標変換(または射影変換ともいう)
5 . スクリーン座標変換(またはビューポート座標変換ともいう)

1 . ローカル座標で3Dオブジェクトを組み立てる。
まず、ローカル座標で3Dオブジェクトを組み立てる。
2 . ワールド座標変換
ワールド変換行列でローカル座標からワールド座標に変換する。
平行移動行列、回転行列、スケーリング行列を使う。
※平行移動行列は演算順序によって、結果が変わるので、以下の順序で演算を行う。

求めたい行列 = スケーリング行列 * 回転行列 * 平行移動行列

※ちなみにアフィン変換とは、変換によっても図形の形が変わらない変換のことをいう。

3 . ビュー座標変換(カメラ座標変換)
カメラの位置を定義することによって、物体をワールド座標からカメラの位置・方向を表す座標系への変換を行う。
カメラの位置を定義するには、視点(カメラ)の位置ベクトル、注視点の位置ベクトル、およびカメラの上方向を表すベクトルの3つのベクトルによって定義される。

ビュー座標変換の手順としては、まずカメラの座標を定義された位置から原点まで移動する。
そして、その負の移動座標を全てのオブジェクトに適用する。

カメラを移動したら、軸の調整をする。カメラの軸は以下のようにして求める。

At = 注視点の位置ベクトル
Eye = 視点(カメラ)の位置ベクトル
Up = カメラの上方向を表すベクトル

//z軸にカメラをあわせる。視線方向の単位ベクトルを求める。
zaxis = normal(At – Eye)

//x軸にカメラを合わせる。カメラの向いてる方向とカメラの上方向の法線がx軸となる。 
xaxis = normal(cross(Up, zaxis)) 

//y軸にカメラを合わせる。カメラの向いてる方向とx軸の方向の法線がy軸となる。
yaxis = cross(zaxis, xaxis)

軸を求めたら、それに合わせて全てのオブジェクトを回転させる。
以上をふまえるとビュー座標変換行列は以下になる。

ビュー座標変換行列 = [
 xaxis.x  yaxis.x  zaxis.x  0
 xaxis.y  yaxis.y  zaxis.y  0
 xaxis.z  yaxis.z  zaxis.z  0
 -dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)  1
]

※normal(a) = aの単位ベクトルを求める
※cross(a,b) = aとbの外積を求める
※dot(a,b) = aとbの内積を求める

4 . プロジェクション座標変換(射影変換)
3Dの情報であるビュー座標を、投影により2Dの座標に変換する。
それと、カメラの設定(主にズームなどの機能)をする。

プロジェクション座標変換行列には二通りある。平行投影と透視投影。
平行投影は視点の手前にあるものと視点の奥にあるものの大きさが同じ。
透視投影は実際にカメラで覗いてるように物体が視点に近いと大きくなり、遠いと小さくなる。

平行投影に関しては今回はスルーして、透視投影について。

まず視錘台を定義する。
定義する要素は、近クリップ平面、遠クリップ平面、アスペクト比、視野角。
近平面と遠平面の間が実際に画面に表示される部分。つまり視錘台とは見える領域を表す。
視野角はカメラの角度。ズームインやズームアウトといったことができる。
アスペクト比は横と縦の比率を決める。

視野角に関して。
視野角が広いほど奥行き感が増加する。またズームアウトする感じになり、周りの映る範囲が広がる。
カメラを回転させるとパースがきき過ぎて歪んでいる感じがする。
逆に視野角が狭いほど奥行き感が減少する。
ズームインする感じになり周りの映る範囲が狭くなる。
45 ~ 60度くらいが3Dゲームではよく使われているらしい。

先にも書いたが、視錘台の外にあるオブジェクトは見えない。つまり描画処理を行う必要はない。
そこでオブジェクトを内包する単純な形状(球など)を考え、それが視錘台の内部にあるかを判定し、
内部に無ければ描画処理を行わないようにする。これを視野カリングとか視錘台カリングと呼ぶ。

プロジェクション変換行列を適用した結果は、
X座標が-1.0 から1.0、
Y座標が-1.0 から1.0、
Z軸が0.0 から 1.0の間の値になる。
ちなみに、近クリップ平面がz=0、遠クリップ平面がz=1。

んで、プロジェクション変換行列を生成する計算式。

θ = Y方向の視野角
a = アスペクト比
n = 近クリップ平面までの距離
f = 遠クリップ平面までの距離

sy = cot(θ/2)
sx = sy / a
sz = f / (f-n)

プロジェクション変換行列 = [
 sx, 0, 0, 0,
 0, sy, 0, 0,
 0, 0, sz, 0,
 0, 0, -sz*n, 0
]

となる。
んー、むずい。

5 . スクリーン座標変換(ビューポート座標変換)
スクリーン座標は左上隅を原点とし、Flashの場合なら、右方向を+X、下方向を+Yとする。

w = スクリーンの横幅/2
h = スクリーンの縦幅/2

スクリーン座標行列 = [
 1, 0, 0, 0,
 0, 1, 0, 0,
 0, 0, 1, 0,
 w, h, 0, 1
]

※Flashで実装する場合はわざわざスクリーン座標変換するよりも、3D空間を内包したDisplayObjectをまるっとステージの中央に配置した方が処理的に軽いかも。

ちょっと間違ってるところありそうだけど以上。

MacでFlex SDKを使用してswfをコンパイルする

2009.11.08 11:15 PM

MacでFlex SDKを使用してswfをコンパイルをすることは滅多にないけど、
いざやろうとする時、いつも忘れているので、一応メモっとく。

例えばHOMEディレクトリ/Works/にあるMain.asをコンパイルする場合。
1.ターミナルを起動。
2.ディレクトリをHOMEディレクトリ/Works/に移動 (cd ~/Works/と入力してreturn)。
3.mxmlcキーワードに続いてコンパイルしたいファイルを指定 (mxmlc Main.asと入力してreturn)。

以上。

Pixel Benderメモ

2009.10.05 10:05 PM

Flash Player 10でサポートされているカスタムフィルタ(ピクセルシェーダ)を作成できるツール、Pixel Bender Toolkitのメモ。

Pixel Benderは、Adobe Flash Player 10、Adobe After Effects等がサポートするグラフィックス処理エンジン。
Pixel Benderの言語は、3Dレンダリングピクセル描画処理の最適化に用いられる、フラグメントシェーダ言語(GLSL:OpenGL Shading Languageなど)に基づいて開発されているとのこと。Flash Playerでは、このPixel Benderのプログラムを利用してフィルタやブレンド、面または線の塗りを独自に作成することができる。

Pixel Bender Toolkitで新規Filterファイルを作成すると、以下のようなデフォルトのソースが生成される。

以下、ざっくりメモ。
・Parameterを定義すると、実行したときにツールの右側エリアにスライダーが表示されて動的にパラメータを変更できるようになる。
・inputは入力画像を宣言するキーワード。
・outputは出力するピクセル色を宣言するキーワード。
・実際のシェーダーの処理はevaluatePixelメソッド内に記述。このメソッドで指定した処理が、
描画領域の全ピクセルに対して実行される仕組みになっている。
・outCoordメソッド : 処理中のピクセルのグローバル座標を返す。
・sampleNearestメソッド : サンプリングメソッド。入力画像の所定の座標に最も近いピクセルのチャンネル値が含まれたベクトルを返す。戻り値はfloat4型で、それぞれrgbaにてアクセスできる。第一引数に入力画像、第二引数で位置を指定。戻ってきた値をoutput変数に割り当てるのが一般的な処理の流れ。
・distanceメソッド: 2点間の距離を算出。
・float3x3型は行列データ型。asのMatrixクラスみたいなもの。
・Flashで使用する場合、ループ処理、配列、カスタム関数は使用できない。
・浮動小数点数を記述する際には、必ず小数点まで記述しなければならない。
・Flashで使用するには、.pbjという形式のバイトコードデータとして書き出してFlashで読み込むもしくは埋め込む。
・どうやらFlash Player 10ではまだGPU機能が有効になってない模様。なんじゃそれって感じ。早く対応してほしい。

Flashでのクロスドメインに関して

2009.09.25 01:04 PM

久々にクロスドメインになりそうなFlash案件があったのだが、
そういえばFlash Player 10になって、セキュリティの扱いに変更があったことを思い出したので調べてみた。
いくつか有効な手段があった。ので備忘録的メモ。

Flash Player 10 におけるセキュリティ変更はakihiro kamijo: Flash Player 10 におけるセキュリティ変更を参照。

要は、クロスドメイン間のデータのやりとりをしたければ、
参照される側のサーバールートにポリシーファイル(crossdomain.xml)を設置し、
ポリシーファイル内で、メタポリシーを設定してくれっていう内容。

サーバーのルートに、ポリシーファイルの設置が可能であれば、特に問題はないのだが、
共有サーバーなどを使用しているケースでは、
基本的にはサーバーのルートにポリシーファイルを設置できないことが多い。
実際にこの問題に直面している記事があったので、以下参照。
RIAトピック: 【trick7】crossdomain.xml 格納場所を変更しても外部ドメインのルートからも呼び出そうとする問題

で、この問題の有効な対処法が以下。
FLASH-japan: サイトルートにポリシーファイルを置けない環境下でのクロスドメイン運用について

上記の記事はHTTPヘッダーを使って解決するという方法。

別ドメインからのアクセスを許可するファイルと同じ階層かそれ以上のディレクトリに、ポリシーファイルを設置。
Flash側では、loadPolicyFileメソッドで、設置したポリシーファイルを予め読み込んでおく。

Security.loadPolicyFile(“http://www.hoge.com/hoge/hoge/crossdomain.xml”);

さらに、ポリシーファイルと同じディレクトリにHTTPヘッダーを設定した.htaccessを設置。
こうすることでサーパーのルートにあるはずのポリシーファイルよりも、
.htaccessと同じディレクトリにあるポリシーファイルの読み込みが優先されるので、
サーパーのルートのポリシーファイルを読みにいかなくなり、セキュリティエラーが出なくなるということのようだ。
gaienboy様、ありがとうございます。

 

上記のようにサーバーにポリシーファイルが置ける場合はいいとして、
ポリシーファイルを絶対に設置できない場合はどう対処したらいいだろうか?
例えば外部のWebAPIサービスを利用する際などは、ポリシーファイルを設置していないサービスも多い。
こういったケースでは、Flashからの(ActionScriptからの)外部APIへのアクセスができない。

このケースでの有効な対処法がこれ↓
YOPPA BLOG: Flash(AS3)でcrossdomain.xml無しにクロスドメインにアクセスする

要は、PHPでProxyを設定して、Proxy経由で外部APIから情報を引っ張ってくるという方法。
この方法を用いれば、ポリシーファイルを設置していないサービスでも情報を引っ張ってこれる。
YOPPA BLOG様、あざーす!