0

I'm currently in the process of finishing the implementation for a camera that functions in the same way as the camera in Maya. The part I'm stuck in the tumble functionality.

The problem is the following: the tumble feature works fine so long as the position of the camera is not parallel with the up vector (currently defined to be (0, 1, 0)). As soon as the camera becomes parallel with this vector (so it is looking straight up or down), the camera locks in place and will only rotate around the up vector instead of continuing to roll.

This question has already been asked here, unfortunately there is no actual solution to the problem. For reference, I also tried updating the up vector as I rotated the camera, but the resulting behaviour is not what I require (the view rolls as a result of the new orientation).

Here's the code for my camera:

using namespace glm;
// point is the position of the cursor in screen coordinates from GLFW
float deltaX = point.x - mImpl->lastPos.x;
float deltaY = point.y - mImpl->lastPos.y;

// Transform from screen coordinates into camera coordinates
Vector4 tumbleVector = Vector4(-deltaX, deltaY, 0, 0);
Matrix4 cameraMatrix = lookAt(mImpl->eye, mImpl->centre, mImpl->up);
Vector4 transformedTumble = inverse(cameraMatrix) * tumbleVector;

// Now compute the two vectors to determine the angle and axis of rotation.
Vector p1 = normalize(mImpl->eye - mImpl->centre);
Vector p2 = normalize((mImpl->eye + Vector(transformedTumble)) - mImpl->centre);

// Get the angle and axis
float theta = 0.1f * acos(dot(p1, p2));
Vector axis = cross(p1, p2);

// Rotate the eye.
mImpl->eye = Vector(rotate(Matrix4(1.0f), theta, axis) * Vector4(mImpl->eye, 0));

The vector library I'm using is GLM. Here's a quick reference on the custom types used here:

typedef glm::vec3 Vector;
typedef glm::vec4 Vector4;
typedef glm::mat4 Matrix4;
typedef glm::vec2 Point2;

mImpl is a PIMPL that contains the following members:

Vector eye, centre, up;
Point2 lastPoint;
4

1 に答える 1

0

これが私の考えです。これは、オイラー角 (したがって球座標) で発生するジンバル ロックと関係があります。

minimum(0, -zoom,0) または maxima(0, zoom,0) を超える場合は、ブール値を切り替える必要があります。このブール値は、deltaY を正に扱う必要があるかどうかを示します。

特異点が原因である可能性もあるため、極角の値を 89.99° ~ -89.99° に制限してください。

あなたの問題はこのように解決できます。

したがって、カメラがオブジェクトの真上 (0, zoom,0) または真下 (0, -zoom,0) の場合、カメラは回転するだけです。(また、オブジェクトが (0,0,0) にあり、アップベクターが (0,1,0) に設定されていると仮定しています。)

これを解決するための数学的なトリックがあるかもしれませんが、私は線形代数でそれを行います。

新しい右ベクトルを導入する必要があります。外積を作成すると、カメラ ベクトルが得られます。カメラ ベクトル = アップ ベクトル x カメラ ベクトル。これらのベクトルが (0,0,0) から始まり、(0,0,0)-(camera-vector) の減算を行うだけで簡単にカメラ位置を取得できると想像してください。

したがって、deltaX を取得した場合は、右ベクトル (アップ ベクトルの周り) に向かって回転し、更新します。

deltaX の影響によって、アップベクターが変更されることはありません。

deltaY を取得した場合は、アップ ベクトルに向かって (右ベクトルを中心に) 回転させて更新します。(これは右ベクトルには影響しません)。

https://en.wikipedia.org/wiki/Rotation_matrix軸と角度からの回転行列で、重要な式を見つけることができます。

u は回転させたいベクトルで、theta はピボットしたい量だとします。theta のサイズは deltaX/Y に比例します。

例: deltaX から入力を取得したので、アップベクターを中心に回転します。

up-vector:= (0,1,0)

right-vector:= (0,0,-1)

cam-vector:= (0,1,0)

theta:=-1*30° // -1 due to the positive mathematical direction of rotation


R={[cos(-30°),0,-sin(-30°)],[0,1,0],[sin(-30°),0,cos(-30°)]}

new-cam-vector=R*cam-vector // normal matrix multiplication

やらなければならないことが 1 つ残っています: 右ベクトルを更新します。

right-vector=camera-vector x up-vector .
于 2016-04-11T05:07:22.810 に答える