2011-10-11 42 views
5

OpenGLでスカイボックスの内部にジェットコースターを作成していますが、機能やコンピュータグラフィックスの背景があまりないため、非常に困難です。私はCatmull-Romスプライン補間を使ってローラーコースターを描き、glVertex3fで各点を描きました。今度は、update()関数を50msごとに呼び出して、カメラをトラックの周りに移動したいと考えています。 gluLookAt()は奇妙な結果を生み出しています。画面からトラックを削除したり、黒い画面を表示したりしています。私は行列関数の一部を移動する必要があると思いますが、それぞれをどこに置くのかはわかりません。ここに私のコードは、これまでです:OpenGL gluLookAt()が意図したとおりに動作しない

int main(int argc, char** argc) 
{ 
    // ... load track, etc ... 

    // Init currpos, nextpos, iter, up 
    currpos = Vec3f(0, 0, 0); 
    nextpos = currpos; 
    iter = 0; 
    up = Vec3f(0, 1, 0); 

    deque<Vec3f> points; 
    Vec3f newpt; 

    // Loop through the points and interpolate 
    for (pointVectorIter pv = g_Track.points().begin(); pv != g_Track.points().end(); pv++) 
    { 
     Vec3f curr(*pv);   // Initialize the current point and a new point (to be drawn) 
     points.push_back(curr);  // Push the current point onto the stack 
     allpoints.push_back(curr); // Add current point to the total stack 

     if (points.size() == 4) // Check if there are 4 points in the stack, if so interpolate 
     { 
      for (float u = 0.0f; u < 1.0f; u += 0.01f) 
      { 
       newpt = interpolate(points[0], points[1], points[2], points[3], u); 
       glColor3f(1, 1, 1); 
       glVertex3f(newpt.x(), newpt.y(), newpt.z()); 

       allpoints.push_back(newpt); 
      } 

      points.pop_front(); 
     } 
    } 

    // glutInit, InitGL(), etc... 
} 

void InitGL(GLvoid) 
{ 
    glEnable(GL_DEPTH_TEST); 
    glDepthFunc(GL_LEQUAL); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    gluPerspective(100.0, (GLfloat)WINDOW_WIDTH/(GLfloat)WINDOW_HEIGHT, .0001, 999999); 
    glMatrixMode(GL_MODELVIEW); 
    glClearColor(0.0f, 0.0f, 0.0f, 0.5f); 
} 

void display (void) 
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    gluLookAt(currpos.x(), currpos.y(), currpos.z(), nextpos.x(), nextpos.y(), nextpos.z(), up.x(), up.y(), up.z()); 

    glPushMatrix(); 
    glEnable(GL_TEXTURE_2D); // Enable texturing from now on 

    /* draw skybox, this was from previous assignment and renders correctly */ 

    glPopMatrix(); 

    // now draw rollercoaster ... 

    glPushMatrix(); 
    glBegin(GL_LINE_STRIP); 

    deque<Vec3f> points; 
    Vec3f newpt; 

    for each (Vec3f pt in allpoints) 
    { 
     glColor3f(1, 1, 1); 
     glVertex3f(pt.x(), pt.y(), pt.z()); 
    } 

    glutTimerFunc(50, update, 1); 
    glEnd(); 
    glPopMatrix(); 

    // Swap buffers, so one we just drew is displayed 
    glutSwapBuffers(); 
} 

void update(int a) 
{ 
    if (iter < allpoints.size()) 
    { 
     currpos = allpoints[iter]; 
     nextpos = allpoints[iter + 1]; 

     gaze = nextpos - currpos; 
     gaze.Normalize(); 

     Vec3f::Cross3(binorm, gaze, up); 
     binorm.Normalize(); 

     Vec3f::Cross3(up, binorm, gaze); 
     up.Normalize(); 

     glutPostRedisplay(); 
    } 

    iter++; 
} 

アイデアは、私はスプラインの制御点と補間点を含めたグローバル両端キューallpointsを保管しておりますということです。それが完了したら、update()を50msごとに呼び出し、allpointsの各ポイントに沿ってカメラを移動します。以前のバージョンのプロジェクトでは、ローラーコースターが正しく描かれていたことがわかりました。 gluLookAt()ですが、私はそれをしたいとは思えません。上記のコードでは、カメラはスカイボックスの片側をローラーコースターの一部で見てカメラから始まり、update()が呼び出されるとローラーコースターは消えるが、カメラは動かない。 OpenGLの行列関数をどこに置いているのか、どこにあるのかによっては、空白の画面が表示されることがあります。update()

答えて

5

(すでに発見user971377)glPopMatrixの欠如に加えて、あなたはもちろん、あなたが(gluLookAtを使用して)update方法でモデルビュー行列で行ったすべての変更を上書きし、あなたの描画ルーチンにglLoadIdentityを呼び出します。

は常に心に留めておく:gluLookAtglOrthogluPerspectiveglTranslateglRotate、および他のすべての行列と変換関数は常に(glMatrixModeによって変更)現在選択されている行列スタックの(glPush/PopMatrixによって変更)先頭の要素に取り組みます。そして、彼らは常に現在の行列、それを置き換えるisteadを掛けます。 gluPerspectiveの場合と同様にを呼び出す前にglLoadIdentityに電話する必要があります。そしてカメラ全体の変更は、アップデートルーチンのisteadというレンダリングルーチンで行う必要があります。

updateでGL変換を行う代わりに、カメラが依存する変数を変更し、displayメソッドでカメラを設定する(モデルビューマトリックスでgluLookAt)必要があります。これらの関数の標準的な使用を実証するために、あなたのコードのようなものでなければなりません:

void display() 
{ 
    <general state setup (glClear, ...)> 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    glLookAt(camera);  //view transformation (camera) 

    //object 1 
    glPushMatrix();  //save modelview 
    glTranslate/glRotate/glScale;  //local model transformations 
    <draw object 1> 
    glPopMatrix(); 
    ... 
    //object n 
    glPushMatrix();  //save modelview 
    glTranslate/glRotate/glScale;  //local model transformations 
    <draw object n> 
    glPopMatrix(); 

    gluSwapBuffers(); 
} 

void update() 
{ 
    camera = ...; 
} 

}

+0

申し訳ありませんが、 'glPopMatrix()'はローラーコースターの前にスカイボックスコードの最後にあります(私はスカイボックスコードを含んでいないので、それを忘れてしまいました)またはそれはジェットコースターの描画の後にする必要がありますか? –

+0

@Logan実行時に制御フローが同じでも、 'glPopMatrix'は' glPushMatrix'と同じスコープになければなりません。 –

+0

'glPopMatrix()'は、コメントされたスカイボックスコードの後(rcが 'glVertex3f'で描画される前)であるべきですか、' glVertex3f'でrcを描画するループの後にあるべきですか? –

0

gluLookAtは、その結果を現在の行列に適用します。この行列は、GL_MODEL_VIEWです。しかし、あなたがローラーコースターをレンダリングすると、あなたはgluLookAtを使って置いた値を消去するその行列にアイデンティティを読み込みます。

この場合、モデルビューに触れる必要はありません。実際、GL_MODEL_VIEWは、ビューマトリックスによるモデル行列の乗算を表します。この場合は、glPushMatrix()、次にglMulMatrix(myModelMatrix)、レンダリング後はglPopMatrix()となります。これにより、GL_MODEL_VIEW内にビュー行列を保持したまま、オブジェクトごとに異なるモデル行列を使用することができます。

また、フレームごとに投影行列を変更することをお勧めします。

0

考慮すべきいくつかのこと、私はOpenGLを触れたので、長い時間があったが、ここにあります:

  • (表示するには、各呼び出しで)、あなたはその後、身元をロードし、現在のマトリックスでスカイボックスを描画していますマトリックスを使ってジェットコースターを描く。おそらく、プッシュ/ポップ内でアイデンティティを読み込んでスカイボックスが一定になるようにしますが、ローラーコースターの一般的な変換情報が適用されます。
  • display()を呼び出すたびにgluPerspectiveとglMatrixModeを呼び出す必要がありますか?
  • binormを上から上まで繰り返し計算すると、おそらく、画面のz軸周りのカメラの回転に関する予期しない結果が得られます。
  • gluLookAtを呼び出すと、nextposとcurrposが逆になり、カメラの方向が逆になります。
  • (オピニオンのみ)まだ完全に静止しているスカイボックスでは見えないかもしれません。スカイボックスとジェットコースターを描いたときのカメラ回転のマッチング(訳ではない)が良く見えるかもしれません。あなたのコードglPushMatrix();に気づい
+0

ジェットコースター自体は今のカメラで回転しているようおかげで、あなたの提案は(私が思う)大丈夫取り組んでいます。カメラ自体は動き出していますが、トラックに追従せず、最終的に制御不能になり、スカイボックスの外に出ます。私はnextposとcurrposを切り替えたので、おそらくこれはbinorm/upベクトルの計算によるものでしょうか?私は自分のコードで私が持っているものは私たちのTAによって提案されたものなので、これらを計算する方法を知っていますか? –

+0

upの計算はカメラの回転にのみ影響するはずですが、スカイボックスの外側ではそれを説明しません。コントロールポイントはOpenGLと同じxyz方向を使用しますか? – SlightNihilism

+0

一方、あなたのローラーコースターがステップ間で正確に上下に面していない場合、あなたは "上向き"を一定に保つことで逃げることができます。私は一時的にレールを微調整して、カメラのxyz位置をデバッグ/テストするまでこの方法を使うことができました。それから私は後で "up"のより安全な計算について心配します。残念ながら、私はその計算のための推奨を持っていません。 – SlightNihilism

3

だけ考えていないglPopMatrix();

と呼ばれ、これはあなたの問題とは何かを持っているかもしれません。

関連する問題