8. ビューイングとカメラ変換の使い方と gluLookAt() について

8.010 OpenGL においてカメラはどのように働きますか?

OpenGLが心配している限り、カメラが全然ありません。 より特に、カメラはいつも目スペース座標に置かれます(0.、0.、および0。)。 カメラを動かしている外観を与えるために、OpenGLアプリケーションはカメラ変化の逆によって場面を動かさなければなりません。

8.020 シーンの中でどのように視点やカメラを動かすことができますか?

OpenGLは、カメラモデルを使ってこれをするために、インタフェースを提供しません。 しかし、GLUライブラリは、目ポジションを取るgluLookAt()機能を提供し それを見るポジション 、上のベクトル、すべては、オブジェクトスペースで調和します。 この機能はそのパラメータに従って逆のカメラ変化を計算し、現在の行列スタックの上にそれを増加させます。

8.030 ModelView やプロジェクションマトリックスのどこでカメラを動かせばいいのですか?

GL_PROJECTION行列は、目スペース座標をクリップ座標に変換するためにそれに必要な投射変化呼び出しだけを含んでいるはずです

GL_MODELVIEW行列は、その名前が暗示しているので、オブジェクトスペース座標を目スペース座標に変換するモデリングと展望変化を含んでいるはずです。 忘れずにカメラ変化をGL_MODELVIEW行列に置いてください。およびGL_PROJECTION行列での決して。

投射行列を、眺め、焦点距離、魚目レンズなどのフィールドなどのカメラの属性を説明するとみなしてください カメラと方向によって立つ所に、それを指し示すと、ModelView行列について考えてください。

ゲームdev FAQはこれらの2つの行列についてのよい情報を持っています

投射乱用においてスティーブベーカーの記事を読んでください。 この記事は高く推奨されて、よく書かれます。 それはいくつかの新しいOpenGLプログラマーを助けました。

8.040 ズーム操作の実行はどのようにして行えばいいのですか?

急上昇する簡単な方法は、ModelView行列の均一なスケールを使うことです。 しかし、もし大きすぎるので、モデルが縮尺されるならば、これは、しばしば、zNearzFarを切り取っている飛行機によって刈ることを結果として生じます。

よりよい方法は、投射行列の眺めボリュームの幅と高さを限定することです

例えば、プログラムは、フローティングポイント数であるユーザーインプットに基づく急上昇ファクターを維持できます。 1.0の価値に設定される時には、急上昇は全然起こりません。 より大きい価値がより大きい急上昇を結果として生じること、またはより小さい価値が向こう側を起こす間起こる眺めの、より多くの、限定されたフィールド。 この効果を作成するコードは、以下のように見えるかもしれません:

静的なフロートzoomFactor; もし望んでいるならばグローバルです。 ユーザーインプッ
トにより修正されます。 最初1.0*/

/* 投射行列を設定するためのルーチン。 典型的なアプリケーションにおいてリサイズイ
ベントハンドラから呼ばれえます。 引いているエリアの整数幅と高さ次元を取ります。 
正しい縦横比と急上昇ファクターによって投射行列を作成します。 */
空のsetProjectionMatrix(int幅、int高さ){
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspectiveです(50.0*zoomFactorは、幅/(フロート)高さ、zNear、zFarを(浮
   かべます));
   /*… 埋めるために'zNear'と'zFar'があなたに任せられる所。 */}

() gluPerspectiveである アプリケーションの代わりに、glFrustum()を使うことができます。 これは、zNear飛行機距離、また影響とともに狡猾に それゆえ 左、右、および一番上のパラメータ なります 眺めのフィールド 。 もし一定のzNear飛行機遠景(妥当な仮定)を保持したいならば、glFrustum()コードはこれのように見えるかもしれません:

glFrustum(left*zoomFactor right*zoomFactor、bottom*zoomFactor、top*zoomFactor、zNear
、zFar);

glOrtho()は同様です

8.050 現在 ModelView マトリックスがカレントの状態です。オブジェクト空間でのカメラ位置を指定するにはどのようにしたら良いのでしょうか?

「カメラ」または観点は、目スペースの中にあります(0.、0.、および0。)。 これをベクトル[0 0 0 1]に変えて、ModelView行列の逆をそれに乗算する時には、結果として生じているベクトルはカメラのオブジェクトスペース位置です。

OpenGLは、あなたに逆をModelView行列に尋ねて(glGet*ルーチンを通じて)させません。 あなた自身のコードによって逆を計算する必要があります。

8.060 シーン内においてのカメラの「軌道」はどのようにして作ればよいですか?

場面/オブジェクトを翻訳/回転させて、カメラを同じ場所に置いていくことによって、軌道をシミュレーションできます。 例えば、オブジェクトを軌道に乗せることにより、起源を継続的に見る間、Y軸においてあなたはどこかに置かれました これをすることができる :

gluLookAt(カメラ[0]、カメラ[1]、カメラ[2]、カメラXYZ*/からの注視
               0 0および0、起源*/を見ます
               0、1、および0); /*ポジティブのY上ベクトル*/
glRotatef(orbitDegrees、0.f、1.f、および0.f);Y軸*/ /* ...where orbitDegreesが
マウス動作*/から引き出される/*軌道

glCallList(場面); /*引き場面*/

もしカメラポジションを物理的に周回することを強く主張するならば、展望変化においてそれを使う前に現在のカメラポジションベクトルを変換する必要があるでしょう

いずれにせよ、私は、gluLookAt()を調査するように勧めます(もしすでにこのルーチンを使っていないならば)。

8.070 全てのモデルが表示できるようにビューを自動計算するにはどうしたら良いですか?バウンディング球と、上方ベクトルがわかっています

以下は、基本的な展望システムをセットアップするとすぐに、デイブShreinerによる投稿からです

第一に、場面のすべてのオブジェクトのための隣接球を計算してください。 これは2ビットの情報をあなたに提供するべきです: 球(であること そのポイント を貸してください(c.x、c.y、c.z))およびその直径のセンター(それを「diam」と呼んでください)。

次に、zNearを切り取っている飛行機のために価値を選んでください。 一般ガイドラインは、近く 1.0までの で何か より大きい than けれども を選ぶ必要があります。 従って、設定すると言いましょう

zNear=1.0;
zFar = zNear + diam;

行列呼び出しをこの注文に構造化してください(正書法の投影のために):

GLdoubleは= c.x - diamを残しました;
GLdouble右= c.x + diam;
GLdouble底c.y - diam;
GLdouble一番上= c.y + diam;

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(左右底、トップ、zNear、zFar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

このアプローチはするべきで センター ウィンドウの中央のオブジェクト 、適合するように、それらを張ります(すなわち、それが、縦横比=1.0によってウィンドウを使っていると想定します)。 もしウィンドウが四角くないならば、上および呼び出しの前に以下のロジックにおいてglOrtho()に置かれるように左、右、底を計算し、蓋を付けてください

GLdouble面=(GLdouble)windowWidth/windowHeight;

ならば (面<1.0 )広い底/= 面 より高い{//ウィンドウ;
   トップ/=面;
他に
   左の*=面;
   右の*=面;
}

上記のコードは場面のオブジェクトを適切に置くべきです。 もし処理し(すなわち回転してください)つもりならば、展望変化をそれに追加する必要があります。

典型的な展望変化はModelView行列に行き、これのように見えるかもしれません

GluLookAt(0.、0.、2.*diam 、
                c.x、c.y、c.z、0.0、1.0、および0.0);

8.080 なぜ、gluLookAt が動かないのでしょう?

これは通常間違った変化により起こされます

もし投射行列スタックで() gluPerspectiveなので、3番目と4番目のパラメータとしてzNearzFarによって使っているならば、gluLookAtをModelView行列スタックに設定する必要があり、zNearzFarの間の幾何学落下をパラメータにそう手渡します

変化を見ることを理解しようとしている時には、それは、通常、コードの簡単な断片を持つ実験に最も親切です。 起源に集中されたユニット球を見ようとしていると言いましょう。 変化を次の通り設定したい:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspectiveです(50.0、1.0、3.0、および7.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0、0.0、および5.0 、
          0.0、0.0、0.0、0.0、1.0、および0.0);

どのように投射とModelView変化がいっしょに働くかに注意することが重要です

この例には、投射変化は1.0の縦横比によって眺めの50.0度フィールドを設定します。 zNearを切り取っている飛行機は、目の前で3.0のユニットであり、zFarを切り取っている飛行機は、目の前で7.0のユニットです。 これは、4.0のユニットのa Zボリューム距離、十分な部屋をユニット球に去ります。

ModelView変化は、それで目ポジション(0.0、0.0、および5.0)を設定し、注視場合ポイントは私達のユニット球のセンターの起源です。 ポイントで、目ポジションが注視から向こうの5.0のユニットであることに注意してください。 目の前の5.0のユニットの距離が、投射変化が定義するZボリュームの中央にあるので、これは重要です。 もしgluLookAt()呼び出しにより目(0.0、0.0、および1.0)が、それに置かれたならば、それは1.0の起源への距離を生産したでしょう。 これは、球を眺めボリュームに含めるために十分に長くなく、それは、zNearを切り取っている飛行機により切り取られます。

同様に、もし目(0.0、0.0、および10.0)をそれに置くならば、10.0のポイントの時の注視への距離は、目から、および7.0のユニットに置かれたzFarを切り取っている飛行機の遠く後ろで向こうの10.0のユニットであるユニット球を結果として生じるでしょう

もしこれがあなたを混同したならば、OpenGL赤本またはOpenGL指定での変化において研究してください。 オブジェクト同等スペース、目同等スペース、およびクリップ同等スペースを理解した後に、上記はクリアになるはずです。 また、小さいテストプログラムを持つ実験。 もし主要なアプリケーションプロジェクトでの正しい変化を得るトラブルをしているならば、より簡単な幾何学によって、問題を再生しようとするコードの小さい断片を書くことが教育的であるかもしれないでしょう。

8.090 指定された点 (XYZ) をシーンの中央に表示されるにはどうしたらよいでしょうか?

gluLookAt()は、最もこれをしやすい方法です。 単に、X、Y、およびポイントのZ値を、4番目、gluLookAt()への5番目と6番目のパラメータと取り決めてください。

8.100 プロジェクションマトリックスに gluLookAt() のコールを加えました。フォグ、ライティング、テクスチャマッピングが動かなくなりました。何が起こったのでしょう?

この問題の説明のための問題8.030を見てください

8.110 立体表示を行うにはどうしたら?

ポールバークはステレオのOpenGL展望についての情報を組み立てました