2

OpenGLで3D空間にレンダリングする3Dモデルがいくつかありますが、この世界で「キャラクター」(つまりカメラ)を回転および平行移動して移動する際にいくつかの問題が発生しています。

外部イベント(ユーザー入力またはGPS +コンパスデバイスからのデータの画像)から入力(つまり、移動する場所/回転する角度)を受け取り、イベントの種類は回転または平行移動です。

これらのイベントを管理するために、このメソッドを作成しました。

- (void)moveThePlayerPositionTranslatingLat:(double)translatedLat Long:(double)translatedLong andRotating:(double)degrees{

    [super startDrawingFrame];
    if (degrees != 0)
    {
        glRotatef(degrees, 0, 0, 1);
    }

    if (translatedLat != 0)
    {
        glTranslatef(translatedLat, -translatedLong, 0);
    }

   [self redrawView];
}

次に、redrawView実際にシーンとモデルを描画しています。それは次のようなものです:

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

NSInteger nModels = [models count];

for (NSInteger i = 0; i < nModels; i++) 
{
    MD2Object * mdobj = [models objectAtIndex:i];
    glPushMatrix();
    double * deltas = calloc(sizeof(double),2);

    deltas[0] = currentCoords[0] - mdobj.modelPosition[0];
    deltas[1] = currentCoords[1] - mdobj.modelPosition[1];

    glTranslatef(deltas[0], -deltas[1], 0);

    free(deltas);
    [mdobj setupForRenderGL];
    [mdobj renderGL];   
    [mdobj cleanupAfterRenderGL];
    glPopMatrix();

}
[super drawView];

問題は、変換時に回転イベントが次々に呼び出されることです。たとえば、いくつかの反復で増分回転している場合(まだ原点を中心に)、変換して最後に再度回転しますが、最後の回転は発生しないようです。現在の(変換された)位置の周りですが、古い位置(古い原点)の周りです。これは、変換の順序が逆になったときに発生することをよく知っていますが、描画後、翻訳されたシステムによって世界の新しい中心が与えられたと思いました。

私は何が欠けていますか?どうすればこれを修正できますか?(OpenGLへの参照も高く評価されます)

4

2 に答える 2

1

イベントハンドラーで累積変換を行うのではなく、変換の現在の値を内部に保存してから1回だけ変換することをお勧めしますが、これが目的の動作であるかどうかはわかりません。

擬似コード:

someEvent(lat, long, deg)
{
  currentLat += lat;
  currentLong += long;
  currentDeg += deg;
}

redraw()
{
  glClear()
  glRotatef(currentDeg, 0, 0, 1);
  glTranslatef(currentLat, -currentLong, 0);
  ... // draw stuff
}
于 2010-11-15T20:52:04.263 に答える
1

ここで起こっていることがいくつかあるようです。

1つ目は、原点を中心に回転が発生することに注意する必要があるということです。したがって、平行移動してから回転すると、原点と思われるものを中心に回転するのではなく、T -1 0(平行移動の逆によって変換された原点)である新しい原点を中心に回転します。

第二に、あなたは本当に必要なものよりも物事をかなり難しくしています。代わりに検討したいのは、gluLookAtを使用することです。基本的に、シーン内の位置とシーン内の見るポイント、および「上」ベクトルを指定すると、シーンが適切に設定されます。これを適切に使用するには、カメラが配置されている場所を追跡し、そのベクトルをpと呼び、ベクトルn(通常の場合は...はあなたが見ている方向を示します)とu(上向きのベクトル)を呼び出します。nuが正規直交ベクトルである場合(つまり、互いに正規直交であり、単位長である場合)、より高度な機能が容易になります。これを行うと、r = nを計算できますx u、(あなたの「右」ベクトル)。これは、他の2つに直交する法線ベクトルになります。次に、' p + nを見て、アップベクトルとしてuを指定します。

理想的には、nurは、たとえば次のような標準形になります。

n = <0, 0, 1>
u = <0, 1, 0>
r = <1, 0, 0>

次に、回転を段階的に累積し、それらを方向ベクトルの正規に適用します。オイラー回転またはクォータニオン回転のいずれかを使用して、回転を累積できます(さまざまな理由から、クォータニオンアプローチに本当に感謝するようになりました)。

于 2010-11-15T20:48:58.730 に答える