5

私は OpenGL のスカイボックス内にジェットコースターを作成していますが、その機能やコンピューター グラフィックスに関するバックグラウンドがあまりないため、非常に難しいことがわかりました。Catmull-Rom スプライン補間を使用してジェットコースターを描き、glVertex3f で各点を描きました。update()ここで、50 ミリ秒ごとに関数を呼び出して、カメラをトラック上で移動させたいと考えています。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()50 ミリ秒ごとに呼び出し、 の各ポイントに沿ってカメラを移動しallpointsます。プロジェクトの以前のバージョンでは、ジェットコースターが正しく描かれていることがわかりました。それはgluLookAt()、私が望むように機能していないようです。上記のコードでは、プログラムはジェットコースターの一部があるスカイボックスの片側をカメラが見ている状態で開始し、update()が呼び出されると、ジェットコースターは消えますが、カメラは動きません。OpenGL マトリックス関数を配置する場所をいじっていますが、場所によってupdate()は空白の画面が表示されることもあります。

4

4 に答える 4

6

が存在しないことに加えてglPopMatrix(user971377 が既に発見)、glLoadIdentity描画ルーチンを呼び出します。これはもちろん、updateメソッド内のモデルビュー マトリックスに対して行った変更を ( を使用してgluLookAt) 上書きします。

gluLookAtglOrthogluPerspectiveglTranslateglRotateおよび他のすべての行列および変換関数glPush/PopMatrixは、現在選択されている行列スタック ( によって変更)の一番上の要素 ( によって変更された) で常に機能することに注意してくださいglMatrixMode。そして、現在の行列を置き換えるのではなく、常に乗算します。for と同様にgluPerspective、 を呼び出すglLoadIdentity前に呼び出す必要がありますgluLookAt。また、カメラの変更全体は、更新ルーチンではなく、レンダリング ルーチンで行う必要があります。

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

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 = ...;
}

}

于 2011-10-11T16:59:23.457 に答える
3

あなたのコードで気づいたglPushMatrix();ことは、noで呼び出されますglPopMatrix();

ちょっと考えてみると、これはあなたの問題に関係しているかもしれません。

于 2011-10-11T16:49:19.680 に答える
0

gluLookAt は常にその結果を現在のマトリックスに適用します。この場合は GL_MODEL_VIEW です。しかし、ジェット コースターをレンダリングすると、そのマトリックスに ID が読み込まれ、gluLookAt を使用して入力した値が消去されます。

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

また、各フレームではなく、フレームごとに 1 回だけ射影行列を変更することをお勧めします。

于 2011-10-11T06:35:03.640 に答える
0

OpenGL に触れてから長い時間が経ちましたが、考慮すべき点がいくつかあります。

  • display() を呼び出すたびに、現在の行列でスカイボックスを描画し、単位行列をロードしてジェット コースターを描画します。おそらく、スカイボックスが一定になるようにプッシュ/ポップ内にアイデンティティをロードしますが、ジェットコースターでの一般的な変換が適用されます.
  • display() を呼び出すたびに gluPerspective と glMatrixMode を呼び出す必要がありますか?
  • up からの binorm の計算と、binorm からの up の計算を繰り返すと、画面の z 軸を中心としたカメラの回転に関して、予期しない結果が生じる可能性があります。
  • gluLookAt の呼び出しでは、nextpos と currpos が逆になり、カメラが反対方向を向いているように見えます。
  • (意見のみ)完全に静止したスカイボックスでは、まだ奇妙に見えるかもしれません。スカイボックスとジェット コースターを描画するときに、カメラの回転 (移動ではなく) を一致させると、見栄えが良くなる場合があります。
于 2011-10-11T06:35:41.783 に答える