1

ビューポート インタラクションで MotionBuilder と同様の機能を持つアプリケーションに取り組んでいます。3 つのボタンがあります。ボタン 1 は、マウスの X/Y ドラッグに応じて、X と Y を中心にビューポートを回転させます。ボタン 2 は、マウスの X/Y ドラッグに応じて、X と Y を中心にビューポートを移動します。ボタン 3 は、Z 軸に沿って移動することでビューポートを「ズーム」します。

コードは簡単です:

glTranslatef(posX,posY,posZ);
glRotatef(rotX, 1, 0, 0);
glRotatef(rotY, 0, 1, 0);   

さて、問題は、最初に平行移動すると、平行移動は正しくなりますが、回転はワールド軸に従います。私も最初に回転させてみました:

glRotatef(rotX, 1, 0, 0);
glRotatef(rotY, 0, 1, 0);
glTranslatef(posX,posY,posZ);

^ 回転は機能しますが、平行移動はワールド軸に従って機能します。

私の質問は、コード スニペット 1 からの翻訳とコード スニペット 2 からの回転を実現するにはどうすればよいかということです。

編集 世界とローカルの回転/平行移動の意味を説明するために、このかなり粗い画像を描きました。カメラをローカル軸を中心に回転および移動させる必要があります。 http://i45.tinypic.com/2lnu3rs.jpg

4

3 に答える 3

1

リンゴを噛んで、カメラの現在の状態 (位置、ビュー方向、アップ ベクトル、右ベクトル) を格納するカメラ クラスを実装し、制御スキームに従ってその状態を操作することをお勧めします。次に、gluLookAt() を使用して射影行列を設定できます。その場合、操作の順序は重要ではなくなります。以下に例を示します。

camPos をカメラの現在の位置、camView のビュー方向、camUp をアップ ベクトル、camRight を右ベクトルとする。

moveDelta でカメラを移動するには、camPos に moveDelta を追加するだけです。回転はもう少し難しいですが、クォータニオンを理解していればすぐに理解できるでしょう。

最初に、2 つの回転のそれぞれにクォータニオンを作成する必要があります。水平方向の回転は、常に正の Z 軸 (「天井」を指す) を中心にしていると思います。hQuat を水平回転を表すクォータニオンとします。さらに、垂直回転のためにカメラを右軸を中心に回転させたいと仮定します (ピッチ効果を作成します)。このためには、水平回転をカメラの現在の角度に適用する必要があります。結果は、垂直回転 hQuat の回転軸です。総回転クォータニオンは、rQuat = hQuat * vQuat です。次に、rQuat をカメラのビュー方向、上方向、および右方向のベクトルに適用します。

Quat hRot(rotX, 0, 0, 1);      // creates a quaternion that rotates by angle rotX about the positive Z axis
Vec3f vAxis = hRot * camRight; // applies hRot to the camera's right vector
Quat vRot(rotY, vAxis);        // creates a quaternion that rotates by angle rotY about the rotated camera's right vector
Quat rQuat = hRot * vRot;      // creates the total rotation
camUp = rQuat * camUp;
camRight = rQuat * camRight;
camView = rQuat * camView;

これが問題の解決に役立つことを願っています。

于 2012-04-29T10:29:06.127 に答える
1

わかりました、画像は物事を少し明確にします。

オブジェクトについて話しているだけなら、最初のコード スニペットは問題ありませんが、カメラの場合はまったく異なります。

技術的には、opengl には「カメラ」としてのオブジェクトがないため、カメラを構築するときに行っていることは、カメラの移動方法とは逆にすべてを移動することです。つまり、カメラを Y 軸で +1 だけ上に移動するのではなく、ワールドを Y 軸で -1 だけ移動するだけで、カメラがあるのと同じ視覚効果が得られます。

位置 (Cx、Cy、Cz) にカメラがあり、x/y 回転角度 (CRx、CRy) があるとします。これがカメラではなく単なる通常のオブジェクトである場合、次のように変換します。

glTranslate(Cx, Cy, Cz);
glRotate(CRx, 1, 0, 0);
glRotate(CRy, 0, 1, 0);

しかし、これはカメラであるため、代わりにこの操作の逆を行う必要があります (「カメラ」の移動をエミュレートするために、(-Cx、-Cy、および -Cz) によって世界を移動したいだけです。行列の場合、個々の変換の逆を実行し、逆の順序で実行するだけです。

glRotate(-CRy, 0, 1, 0); 
glRotate(-CRx, 1, 0, 0);
glTranslate(-Cx, -Cy, -Cz);

これにより、画像で言及している種類のカメラが得られると思います。

于 2012-04-29T01:29:33.577 に答える
0

glRotate は常に原点を中心に機能します。もしあなたがそうするなら:

glPushMatrix();
glTranslated(x,y,z);
glRotated(theta,1,0,0);
glTranslated(-x,-y,-z);
drawObject();
glPopMatrix();

次に、「オブジェクト」は原点の代わりに (x,y,z) を中心に回転します。これは、(x,y,z) を原点に移動し、回転を行い、(x,y,z) を押し戻したためです。始まりました。

しかし、あなたが説明している効果を得るには、それだけでは十分ではないと思います。常に現在の参照フレームに対して変換を実行したい場合は、変換行列を自分で追跡する必要があります。これが、人々がクォータニオン ベースのカメラを使用する理由です。

于 2012-04-29T02:11:52.970 に答える