【发布时间】:2011-03-13 05:27:19
【问题描述】:
这会让我难以解释,所以请多多包涵。
我已经在我的相机类中实现了大多数类型的移动和旋转,一切都在使用键盘,现在我想实现鼠标。我像这样捕捉鼠标移动:
#define SENSITIVITY 25.0f
void main(void) {
(...)
glutPassiveMotionFunc(processPassiveMotion);
glutWarpPointer(WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2);
glutSetCursor(GLUT_CURSOR_NONE);
(...)
}
void processPassiveMotion(int x, int y) {
int centerX = WINDOW_WIDTH / 2;
int centerY = WINDOW_HEIGHT / 2;
int deltaX = -1 * (x - centerX);
int deltaY = -1 * (y - centerY);
if(deltaX != 0 || deltaY != 0) {
mainCamera.Rotate(deltaX / SENSITIVITY, deltaY / SENSITIVITY);
glutWarpPointer(centerX, centerY);
}
}
在阅读完所有内容之后,我相信这对我的情况来说已经足够了。但是我必须声明,首先我尝试调用 Pitch() 和 Yaw() 相机函数,但这是不行的,我必须创建一个额外的函数来“同时”旋转两个轴。
旋转功能是这样的:
#define DEG2RAD(a) (a * (M_PI / 180.0f))
#define SINDEG(a) sin(DEG2RAD(a))
#define COSDEG(a) cos(DEG2RAD(a))
void Camera::Rotate(GLfloat angleX, GLfloat angleY) {
Reference = NormalizeVector(
Reference * COSDEG(angleY) + UpVector * SINDEG(angleY)
);
Reference = NormalizeVector(
Reference * COSDEG(angleX) - RightVector * SINDEG(angleX)
);
UpVector = CrossProduct(&Reference, &RightVector) * (-1);
RightVector = CrossProduct(&Reference, &UpVector);
}
Reference 是查看方向,即相机正在查看的点。由于它是一个归一化向量,它从 -1.0 变为 1.0。该向量或点稍后会与另一个向量(Position,即相机位置)一起用于计算在gluLookAt 中使用的真实观察点,如下所示:
void Camera::LookAt(void) {
Vector3D viewPoint = Position + Reference;
gluLookAt(
Position.x, Position.y, Position.z,
viewPoint.x, viewPoint.y, viewPoint.z,
UpVector.x, UpVector.y, UpVector.z
);
}
上面的所有向量操作,如+、- 和*,当然都是重载的。
现在我将尝试描述我的问题...
上面的旋转功能很好用,因为它使用鼠标正确地执行了俯仰和偏航。但是,这些轮换看起来不像第一人称射击游戏中的轮换。在那些游戏中,当一个人看着天空然后向左/向右看时,人们期望继续看天空。想象我们在一个球体内,这样的运动应该在球体的顶部“画”一个圆圈。
但这不是发生的事情,因为偏航不是这样做的。偏航运动将围绕任意轴旋转,我认为这是这种情况下的向上向量。所以,问题在于偏航运动,因为俯仰似乎工作正常。
换句话说,我上面的代码不能保持水平线,这就是必须发生的事情,因为在游戏中当一个人看着天空然后向左/向右看时,水平线总是水平的。我的代码不会发生同样的情况,我向上看,然后向左/向右看,地平线将全部扭曲。
我说得够清楚了吗?我不确定如何更好地解释这一点。 :( 希望这足以让任何人理解。
我不知道如何解决这个问题...如何在向上/向下看后正确地向左/向右看,同时保持水平线?
编辑:
我的旋转函数代码取自同样存在的 Yaw 和 Pitch 函数,因此我可以独立调用这些旋转。出于参考目的,我将在下面添加它们以及 Roll 功能(我可能永远不会使用,但如果我需要它,它就在那里):
void Camera::Pitch(GLfloat angle) {
Reference = NormalizeVector(
Reference * COSDEG(angle) + UpVector * SINDEG(angle)
);
UpVector = CrossProduct(&Reference, &RightVector) * (-1);
}
void Camera::Yaw(GLfloat angle) {
Reference = NormalizeVector(
Reference * COSDEG(angle) - RightVector * SINDEG(angle)
);
RightVector = CrossProduct(&Reference, &UpVector);
}
void Camera::Roll(GLfloat angle) {
RightVector = NormalizeVector(
RightVector * COSDEG(angle) - UpVector * SINDEG(angle)
);
UpVector = CrossProduct(&Reference, &RightVector) * (-1);
}
【问题讨论】:
标签: opengl camera mouse move glut