OpenGL 3D相机gluLookAt

时间:2013-04-06 23:48:36

标签: opengl 3d camera rotation glulookat

我正在尝试使用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立方体中的幽灵,可以在任何我想要的地方行走。我想搬到右上角?我只是去那儿。那么......任何想法我应该改变/添加什么?

1 个答案:

答案 0 :(得分:3)

编辑:我从头开始回复,因为我可能对这个主题有太多熟悉。

你面临的问题是你的公式基本上是不正确的:你的公式左/右旋转是正确的,假设“向上”向量(从摄像机向上指向的向量)总是[0 1 0 ] ...如果您还想要向上/向下旋转,则情况并非如此。而你向下旋转的公式是不正确的,因为它只修改Y分量,旋转不起作用。

处理这个问题的正确方法是:

  • 存储3个代表摄影机位置的变量(就像你一样)。我们称他们为PxPyPz
  • 存储3个表示摄像机视图方向的变量(而不是编码摄像机正在查看的点的eyeX / Y / Z)。我们称他们为VxVyVz
  • 存储3个表示摄像机右矢量的变量(或向上矢量,如您所愿)。我们选择正确的向量,并将其称为RxRyRz

或者,您可以使用一个很好的“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);

要向左/向右旋转,首先需要计算不需要存储的“向上”向量(除非您想要,但它是多余的),并旋转视图方向和右向量: / p>

// 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.

当然,我没有测试任何代码,现在写了。希望它有效!