首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >平行于上方向向量时Arcball摄影机锁定

平行于上方向向量时Arcball摄影机锁定
EN

Stack Overflow用户
提问于 2016-04-11 09:11:46
回答 1查看 385关注 0票数 0

我目前正在完成一个相机的实现,它的功能与Maya中的相机相同。我被困在翻滚功能中的部分。

问题如下:只要摄影机的位置不平行于上方向向量(当前定义为(0, 1, 0)),翻滚功能就可以正常工作。一旦摄影机与此向量平行(因此它正向上或向下看),摄影机就会锁定在适当位置,并且只会围绕上方向向量旋转,而不是继续滚动。

这个问题已经被问到了here,不幸的是这个问题没有实际的解决方案。作为参考,我还尝试在旋转相机时更新上方向向量,但产生的行为并不是我所需要的(视图滚动是新方向的结果)。

这是我相机的代码:

代码语言:javascript
复制
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));

我使用的向量库是GLM。下面是这里使用的自定义类型的快速参考:

代码语言:javascript
复制
typedef glm::vec3 Vector;
typedef glm::vec4 Vector4;
typedef glm::mat4 Matrix4;
typedef glm::vec2 Point2;

mImpl是一个包含以下成员的PIMPL:

代码语言:javascript
复制
Vector eye, centre, up;
Point2 lastPoint;
EN

回答 1

Stack Overflow用户

发布于 2016-04-11 13:07:23

这是我的想法。它与万向节锁有关,它发生在欧拉角(因此球面坐标)。

如果超过最小值(0,-zoom,0)或最大值(0,zoom,0),则必须切换布尔值。这个布尔值将告诉您是否必须将deltaY视为正数。

它也可能是由奇点引起的,因此只需将极角值限制在89.99°和-89.99°之间即可。

你的问题可以这样解决。

因此,如果摄影机恰好在对象的上方(0,缩放,0)或下方(0,-zoom,0),则摄影机仅滚动。(我还假设您的对象位于(0,0,0),并且上方向向量设置为(0,1,0)。)

也许有一些数学技巧可以解决这个问题,不过我会用线性代数来解决这个问题。

你需要引入一个新的右向量。如果你做一个叉积,你会得到相机矢量。camera-vector =上方向向量x Camera-vector。想象一下,这些向量从(0,0,0)开始,然后很容易得到你的相机位置,只需做这个减法(0,0,0)-( camera -vector)。

因此,如果你得到一些deltaX,你旋转向右向量(围绕着上方向向量)并更新它。

deltaX的任何影响都不应该改变你的上方向向量。

如果你得到一些deltaY,你向上方向向量旋转(围绕右向量)并更新它。(这对右向量没有影响)。

https://en.wikipedia.org/wiki/Rotation_matrix在旋转矩阵中可以从轴线和角度找到一个重要的公式。

你说u是你想要旋转的向量,θ是你想要旋转的量。θ的大小与ΔX/Y成正比。

例如:我们从deltaX得到一个输入,所以我们围绕上方向向量旋转。

代码语言:javascript
复制
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

还有一件事要做:更新右向量。

代码语言:javascript
复制
right-vector=camera-vector x up-vector .
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36538328

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档