Astro de 3D(14) PerspectiveProjection は放棄<5>
2008/06/18 21:57 - Astro
前々回、PerspectiveProjection について ASDoc などを見た際に、PerspectiveProjection.fieldOfView と透視の状態には以下のような関係があると書きました。
- fieldOfView の値が 0 に近づくほど focalLength の値はその絶対値が大きくなる、そして、透視による歪みが小さくなる(平行投影に近づく)
- fieldOfView の値が 180 に近づくほど focalLength の値はその絶対値が小さくなる、そして、透視による歪みが大きくなる(魚眼レンズ効果が高まる)
実際のところどうなのか、fieldOfView の値を変えてコンパイルした結果が以下のサンプルです。
30度からはじめて30度おきに150度までの4つのサンプルを用意しました(90度は除く)。
- fieldOfView = 30 (require Flash Player 10)
- fieldOfView = 60 (require Flash Player 10)
- fieldOfView = 120 (require Flash Player 10)
- fieldOfView = 150 (require Flash Player 10)
期待される見栄えは、30度のときが一番平行投影に近い形で、順次値が大きくなるごとに歪みが大きくなる、というもの。
ところが、見てのとおり、全然期待どおりの見栄えになりません。
個人的には60度、120度での見栄えがいかにも遠近感って感じで好きなんですが、それはまぁ置いといて、何で30度と150度、60度と120度で同じような見栄えになるんだよ、と声を大にして言いたい。
魚眼レンズ風の歪みを生み出す元は PerspectiveProjection.focalLength で、これは PerspectiveProjection.fieldOfView とステージのサイズによって定まる、ということを前々回見ました。
今回並べたサンプルはステージサイズを変えていません。ということは fieldOfView の値の変更が直接 focalLength に影響を与えているということです。
そこで fieldOfView を変えたとき focalLength の値がどうなるかを trace してみました。 結果は以下のとおり。
fieldOfView focalLength 0 Infinity 30 952.6279270648956 60 317.5426423549652 90 3.3676674730115375e-14 120 -317.5426423549652 150 -952.6279270648956 180 -4491239087302246400
あからさまに期待はずれです。
fieldOfView が90度のとき focalLength の値は 0 と見做して良いと考えられます。
そして fieldOfView が180度のときの focalLength を NEGATIVE_INFINITY と見做すと、fieldOfView 90度を境に、focalLength は点対象のような関係になっています。
focalLength の値を見るに、fieldOfView が90度を境に0度に近づくと、あるいは fieldOfView が90度を境に180度に近づくと、魚眼レンズ効果が小さくなっていくということ。 実際上記サンプルを見ても確かにそんな感じになってます。
つまり0度~90度までは ASDoc に書かれていたとおりの動きをするが、90度を超えると逆転してしまってると。
おかしいじゃんかよぅ。
さらに問題になるのは、0~90度と90~180度で片や値が正、片や値が負ということ。 これじゃZソートが逆転してしまいます。
上のサンプルの対になる fieldOfView のものを見較べてもらうと分かると思うんですが、90度より大きいもの正しいZソートですが、そうでないものはZソードが狂っています。
ここで俺結論。
ASDoc には fieldOfView に指定できる値は0~180度となっているが、本当は0~90度なのではないか。
そうすると ASDoc の PerspectiveProjection 冒頭にある図の ViewPoint に書いてある座標値( 0, 0, -focalLength ) のZ座標値にマイナスが付いている理由も分かります。 Astro では左手座標系が使われているのでZ座標は手前がマイナスになります。 そして fieldOfView が0~90度ならば、focalLength は正の値であることが上記 trace から確認できました。
ASDoc の記述がどうも間違っているらしいというのはともかく、focalLength が自由に設定できないというのが個人的には違和感があります。
もっとも focalLength の数値を単体で弄くる方がそもそも邪道との非難があるかもしれません。
三次元表現理論では focalLength を決めるのは、視野角とアスペクト比による計算だそうですし。 いろいろなサイトを見ていると、もっとたくさんの要素が絡んでくる計算もあるし。
しかし私としては focalLength の値をダイレクトに弄るやり方に慣れてしまっています。
とりあえずは PerspectiveProjection を使わずに、ユーザ変数として focalLength に相当するものを定義する方法で 3D 表現をおこなうこととしておきます。
そのうちカメラやプロジェクションをちゃんと学んで、知識を正しく補正しましょう。 そうすれば PerspectiveProjection が必要になるときが来るかもしれません。