blog index

capa's blog on JUGEM

capaのblogページ
スポンサーサイト

一定期間更新がないため広告を表示しています

| スポンサードリンク | - | | - | - |
ワールド座標→スクリーン座標変換
仕事で何日かハマってしまっていた初歩的な処理。
3Dのワールド座標系から2Dスクリーン座標系への変換処理。

概念と流れは何となく理解してた“つもり”だったんですが、、
ハマって気がつく。
それじゃダメよね、ってこと。

勉強不足ですな。。。
…と反省?しつつ、でも解決したからまた一つ出来るようになったぞ、と。。。
一応、覚書として書いておこうと。
(…つっても、URL貼り付けですが)

●GLUTによる「手抜き」OpenGL入門
http://www.wakayama-u.ac.jp/~tokoi/opengl/libglut.html

…上記「資料」からもリンクされてるけど、
●sonson@Picture&Software
http://www.geocities.jp/yuichiy2001/

その中の「OpenGL Programming - 射影変換の基礎」
http://www.geocities.jp/yuichiy2001/programming/opengl/002.htm
※射影変換の図入りの説明が結構イメージし易かった。


まず、私は以下のような流れだと思っていました。

2Dスクリーン座標=
 3Dワールド座標×ビュー行列×プロジェクション行列

 ※あるいは、
 ビュー行列×プロジェクション行列×3Dワールド座標
  と書く場合もあるようで。
  乗算方向の違いは計算にもろに影響するんだけど、
  ここでは少し目をつぶってもらう。。。

  ようは、3D座標を行列を用いて変換するのだと。

コレ自体にどうやら間違いはない模様。
でも、正確には少し足りないところがあるな。

 3Dワールド座標×ビュー行列×プロジェクション行列

の後に、「ビューポート変換」ってのが必要。

この「ビューポート変換」および、「プロジェクション行列」ってのがミソでした。
私が上手いこと理解しきれてなかった部分です。

まず、「プロジェクション行列」。
こいつ、「ビュー(=カメラからの見た目)」上の座標系を「視体積」上の座標系にする行列です。
私は、この座標系になったときに既に、「ほぼスクリーン」上の位置に変換できているものだと思っていました。

…ですが、実際はまだ3D座標上の数値だったんですね。。

「視体積」を正面から見ると、奥の方が大きく広がっています。
画面上に描画されるときは、これらの広がりの端が、画面の端として描画されるため、「視体積」の“手前側”にあるものは大きく、“奥側”にあるものは小さく描画される、と。
(…文章だとムズイな。。。)

先ほど出てきた、「ほぼスクリーン」ってのは、
“手前側”が大きく“奥側”が小さく、が既に計算済みの数値
…ってことを意図していました。

そこまでをやってくれると考えると、「ビューポート変換」なるものは、「プロジェクション行列変換」で返されたX,Yの値をただスクリーンに合うようにスケールを掛ければ良いだけだ、と。奥行きは無関係だ、と。そう思い込んでいたわけです。

しかーーーし!!

現実にはここに間違いがありました。
実は「プロジェクション行列変換」では、“手前側”が大きく“奥側”が小さく、って変換までは行われません。
あくまでも「ビュー」から見た時のX,Y値。

え?でも、それだと、何をしているわけでしょうか??

…実は、そのときのZ値(奥行き情報)に合わせて、W値(ベクトル第4のメンバ…って、4次元ベクトルのときだけですが)に適切な「視体積膨らみ情報」とでも言えるような値が入ります。

この「視体積膨らみ情報」で、X,Y値を除算することで、奥に行くほど広がる座標値が、上手いこと画面上の座標値に変換されてくれるのです。
(てことは、X,Yもそれを意識して変換されているのかも。)

で、実際どう計算するのか?
まず、この「W値」でNear/Farのクリップ(視体積の手前面のさらに手前の座標や、奥面のさらに奥の方を見えないものとして扱うこと)を行い、Near〜Farの間にある場合に限り、
 X=X÷W
 Y=Y÷W
…という計算をしてあげます。
すると、この計算で初めて
“手前側”が大きく“奥側”が小さく
…てのが行われるんです。
実際、そのスケールが掛かった後、「視体積」に収まる(=画面内にある)場合は、X,Yとも -1.0〜+1.0 の間の値を取るように変換されます。

で、これで画面内の値として使えるX,Y値になったので、それらにスクリーンサイズに合わせるようなスケールを掛けてやれば、晴れて「2Dスクリーン座標値」の出来上がり、ってわけです。

…ふぃ〜、、、長かった。。。
(そして分かりづらい-_-;)

※注意※
今回のケースは、上記リンクにある「OpenGL」で試したわけではなく、「あるゲームプラットフォーム」での話であります。
すべてのプラットフォームの3Dの座標変換処理で上のような「プロジェクション行列」の役割やら、その変換後の「W値」のことやらが言える訳では無いんじゃないか、と思います。その辺お気をつけください。

…つーか、あくまで「自分用の覚書」、なんですけどね。。。
| capa | プログラム | 01:28 | comments(7) | trackbacks(0) |
スポンサーサイト
| スポンサードリンク | - | 01:28 | - | - |
コメント
3D初心プログラマです
参考になりました!
ありがとう!
| 通りすがり | 2007/08/20 9:37 PM |
>通りすがりさん
参考になったようで何よりです(^-^)b
3Dプログラム、がんばってください〜
| capa | 2007/08/21 2:36 AM |
W値で除算するのはビューポート変換の方なんですか?

http://homepage2.nifty.com/skimp-studio/htm/crawl/1_9_transform4.htm
このページだとプロジェクション変換でやっているみたいなんですが…
| まる | 2007/09/12 8:00 PM |
>まるさん
ご紹介いただいたページ、図がついてて分かり易いですね!

確かに、そのページだとプロジェクション変換でやってますね。
ただ、
「射影変換には色々ありますが、ここではDirect3Dで
 標準的に用いられている方法を説明します。」
ということなので、どちらが絶対、というわけでは
無いのではないかと思います。

一般的なのはどっち?
ということで言うのであれば、Direct3Dで標準的
なようなので、ご紹介いただいたページの方を
参考にされるのが良いかと思います。
| capa | 2007/09/12 9:27 PM |
自分もスクリーン座標変換を自前でやることになって、ネットでいろいろ調べていたら、どこのサイトも若干言ってることが違っていて困惑していたんですw
返答ありがとうございました。
| まる | 2007/09/12 10:18 PM |
>まるさん
なるほど、そういうことでしたか。>いろいろ調べ中
困惑の一端となってしまいましたかね^^;
申し訳ないです。
でも少しでも役立ってたら嬉しいです。

自前でやるとなると、なかなか大変かと思いますが
がんばってください(^-^)b
| capa | 2007/09/12 11:46 PM |
プロジェクション変換でやってない気がするのですが。
スクリーン座標に変換するときにちゃんとやっていると思いますよ。
| なお | 2008/11/19 3:37 AM |
コメントする


この記事のトラックバックURL
http://capa.jugem.cc/trackback/144
      1
2345678
9101112131415
16171819202122
23242526272829
30      
<< September 2018 >>
[ Twitter ]
ユグドラシル
ユグドラシル (JUGEMレビュー »)
BUMP OF CHICKEN,藤原基央
「待ちに待った!」そして「期待以上!」
ここ2年半のベスト盤であり、正に欲しかったオリジナル盤!

ちなみに、ジャケットの絵のサイドストーリー?が歌詞カード内に描かれています。
これも一見の価値あり。
RAW LIFE MUSIC
RAW LIFE MUSIC (JUGEMレビュー »)
Caravan
Caravanのソロデビューアルバム。
3曲目の「ハミングバード」、良いです。
視聴は↓のURLへ
http://www.indiesmusic.com/itemview.asp?id=8898

bolg index このページの先頭へ