2009-06-24 5 views
3

3D環境をナビゲートするために、オービット、ウォーク、パン、回転などのナビゲーション機能を実装するOpenGLアプリケーションがあります。このすべては完璧に機能し、gluPerspectivegluLookAtを使用してセットアップするのはかなりストレートです。 CADソフトウェアの典型的なZoomExtents又はZoomToFitコマンドと同様OpenGLズームエクステントを実装する方法

glMatrixMode GL_PROJECTION 
    glLoadIdentity 
    gluPerspective m_ViewAngle, m_AspectRatio, m_ClipDistance_Near, m_ClipDistance_Far   

    glMatrixMode GL_MODELVIEW 
    glLoadIdentity 
    gluLookAt m_Eye.X, m_Eye.Y, m_Eye.Z, m_Focus.X, m_Focus.Y, m_Focus.Z, m_ViewUP.X, m_ViewUP.Y, m_ViewUP.Z 

    glCallList DisplayListIndex 

、任意の視点(視線方向)から、私は (1)全体の3D環境ことをズームできるようにしたいと思い (2)3D環境モデルはビューポート全体を塗りつぶします(ビューポートの現在のサイズを考慮して、できるだけ大きい)。

私は環境の境界ボックス(範囲)を知っています(最小XYZ、最大XYZ)。しかし、私は、指定されたViewAngleとAspectRatioと環境エクステントに対して目と焦点の位置がどんなものであるべきかを導き出すことができませんでした。

gluLookAtよりも簡単な方法があります。どんな助けもありがとう!

答えて

2

実際には、それはもっと簡単に行うことができます。

あなたの必要なことは、モデルを平面に投影することです。次に、最高点と最低点(上端y、下端y、左端x、右端x)を決定し、実際に必要とする矩形にこの矩形を収める必要があるスケーリング量を最終的に決定します。

投影する必要のある平面は、画面平面です。

幸いなことに、あなたはすでにこれをやっています。

したがって、すでに設定した行列を使用してモデルのすべての点を変換し、最大点を決定します。

画面上にどれだけの縮尺を合わせる必要があるかを計算します。このスケーリングをオブジェクトのズームに適用します。

Thats it

+0

「あなたはすでにこれをやっている」と言ったとき、実際に起こっていることは、OpenGLが彼のためにやっているということです。私はそれらの計算の結果にアクセスする方法を知らない。それは簡単ですか?そうでない場合は、これを実装するために、彼は自身のコードで行列/頂点の算術を複製する必要があります:PROJECTIONとMODELVIEWの行列をとり、モデルのすべての頂点でそれらを掛けます。モデル内のすべての頂点ではなく、モデルの境界ボックス全体で計算します。 –

+0

Ah。このバウンディングボックスのショートカットは、この質問に対する他の回答に対するJRSのコメントを考慮すると、明らかに適切ではありません。 –

0

球体に近似し、以下の式をピクセル単位のモデル単位比で除算したものを適用します。 単位球を既知のz座標でレンダリングすることによって、ピクセルとモデルの単位の比を計算することができます。球に関する良いことは、どこから見ても、その幅は常に直径になるということです。詳細は、perspective projectionを参照してください。

alt text

編集:球の良いところは、それが方向から独立したということです。ボックスや球にかかわらず、カメラベクトルの方向とのベクトルを指定する必要があります。ベクター。いったんそれがあると、唯一の未知数は目の視点からの深さzです。あなたはBz := Bx * Az/Axを導き出すことができます式、Bx := Ax * Bz/Az から

eye := (center.x, center.y, center.z) - depth * (camera.x, camera.y, camera.z) 

:そこからで、目の位置を算出することができます。

モデル座標1.0を1.0mと定義しましょう。 距離100.0mから半径1.0mの球が20ピクセル幅に見えるとします。

Bz := 1.0 * 100.0/10 
Bz := 10.0 

今度は、あなたのバウンディングボックスが100.0になるように斧を行っており、広い200.0メートルで、画面の幅がBXシリーズ512pixelを作る1024pixel、あるとしましょう。

Az := (Ax/Bx) * Bz 
Az := (100.0/512.0) * 10.0 
Az := 1.953m 

上記において、mとピクセルとの間の単位変換はBzによって吸収されている。

アップベクトルが(0,0,1)で、カメラベクトルが(1,0,0)であり、中心が(0,0,0)であるとする。

eye := center - depth * camera 
eye := (0, 0, 0) - 1.953 * (1, 0, 0) 
eye := (-1.953, 0, 0) 
+0

球を使用することはできません。これは、環境全体を保証します。しかし、この方法では、すべての場合(例えば、境界ボックスのサイズがX = 10、Y = 10、Z = 2、視点が側からの場合など)の画面をできるだけ大きくする必要はありません。 – JRS

+1

これがあなたの苦情である場合、軸に沿っていない方向からシーンを見るとき、軸に沿った境界ボックスは無用です。シーンの凸包が必要になります。 – Eric

+0

JRS:私はあなたのコメントをしばらく理解できませんでした。境界ボックスのサイズがX = 10、Y = 2、Z = 2で、側面から見たときに動作しないと言っていると思います。 –

関連する問題