我试图用gluLookAt方法设置一个3D相机。我有一个10x10x10的立方体,现在我想把相机移动到这个立方体里面。像这样:
gluLookAt( camera->x,camera->y,camera->z, camera->eyeX, camera->eyeY, camera->eyeZ, 0, 1, 0 );
现在我正在向前/向后移动:
if(GetKeyState(VK_UP) <0)
{
camera->x += sin(camera->angleX)*0.1f;
camera->eyeX += sin(camera->angleX)*0.1f;
camera->z -= cos(camera->angleX)*0.1f;
camera->eyeZ -= cos(camera->angleX)*0.1f;
}
现在我正在左右旋转:
if(GetKeyState(VK_LEFT) <0)
{
camera->angleX -=0.1f;
camera->eyeX = sin(camera->angleX) +camera->x;
camera->eyeZ = -cos(camera->angleX) + camera->z;
}
所以这一切都工作得很好,但现在我想在SHIFT按钮被按下时向上/向下旋转。所以我有这样的东西:
if(GetKeyState(VK_SHIFT) <0)
{
if(GetKeyState(VK_UP)<0)
{
camera->angleY +=0.1f;
camera->eyeY = sin(camera->angleY) +camera->y;
}
实际上奇怪的事情发生了。摄像机一直上下跳动,慢慢向前移动。另外,我想补充的是,当我向上看并向前移动时,相机实际上会移动到它看起来的地方。所以基本上情况是这样的:我是一个被困在一个10x10x10的立方体里的幽灵,我可以走到任何我想去的地方。我想移到右上角?我只是去那里。所以…有什么想法我应该改变/添加吗?
编辑:我从头开始回复,因为我可能对这个主题太熟悉了。
你所面临的问题是,你的公式基本上是不正确的:你的左/右旋转公式是正确的假设下,"向上"向量(从相机指向向上的向量)总是[0 1 0]…如果你想上下旋转就不是这样了。你的向上向下旋转的公式是不正确的,因为它只改变了Y分量,旋转不是这样的。
正确的处理方法是:
- 存储代表摄像机位置的3个变量(如您所做的)。分别为
Px
,Py
,Pz
- 存储3个变量,代表相机的视角方向(而不是你的眼睛x/Y/Z,编码相机正在看的点)。我们称它们为
Vx
,Vy
,Vz
- 存储3个变量,代表相机的右矢量(或上矢量,如你所愿)。让我们取右边的向量,命名为
Rx
,Ry
,Rz
。
或者,你可以有一个很好的"Vector"类来表示向量,而不是每次存储3个变量。这是一个细节。
现在,你移动相机的方法变成了:
Px += Vx;
Py += Vy;
Pz += Vz;
例如,你可以使用Rodrigues公式来旋转(希望没有人会向你发射"四元数"这个神奇的词来表达他们的聪明;))。围绕任意轴旋转的一般自包含代码是:
// rotate the vector (vx, vy, vz) around (ax, ay, az) by an angle "angle"
void rotate(double &vx, double &vy, double &vz, double ax, double ay, double az, double angle) {
double ca = cos(angle);
double sa = sin(angle);
double crossx = -vy*az + vz*ay;
double crossy = -vz*ax + vx*az;
double crossz = -vx*ay + vy*ax;
double dot = ax*vx + ay*vy + az*vz;
double rx = vx*ca + crossx*sa + dot*ax*(1-ca);
double ry = vy*ca + crossy*sa + dot*ay*(1-ca);
double rz = vz*ca + crossz*sa + dot*az*(1-ca);
vx = rx;
vy = ry;
vz = rz;
}
并确保保持相机矢量的标准化坐标。
现在,当你按下一个按钮时,要使你的相机上下旋转:
// rotate up:
rotate(Vx, Vy, Vz, Rx, Ry, Rz, some_CONSTANT_angle);
// rotate down:
rotate(Vx, Vy, Vz, Rx, Ry, Rz, - some_CONSTANT_angle);
要向左/向右旋转,你首先需要计算不需要存储的"向上"向量(除非你想要,但它是多余的),并旋转你的视图方向和右向量:
// find up vector using a cross product:
double Ux = Ry*Vz - Rz*Vy;
double Uy = Rz*Vx - Rx*Vz;
double Uz = Rx*Vy - Ry*Vx;
//rotate left
rotate(Rx, Ry, Rz, Ux, Uy, Uz, some_CONSTANT_angle);
rotate(Vx, Vy, Vz, Ux, Uy, Uz, some_CONSTANT_angle);
// rotate right
rotate(Rx, Ry, Rz, Ux, Uy, Uz, - some_CONSTANT_angle);
rotate(Vx, Vy, Vz, Ux, Uy, Uz, - some_CONSTANT_angle);
设置你的相机矩阵现在变成:
gluLookAt( Px, Py, Pz, Px+Vx, Py+Vy, Pz+Vz, Rx, Ry, Rz); // or is it Ux, Uy, Uz at the end? don't remember.
当然,我没有测试任何代码,现在就写了。希望它有效!