我尝试实现一个相机类。其中一种模式应该是基本的FPS摄像机行为,当你可以用鼠标改变方向,左右扫描并向前/向后移动时向前/向后移动。我有以下代码,它似乎在开始时工作正常,但随后方向向量被破坏:
我的想法是我不存储当前方向的角度,而是将glutPassiveMotionFunc()
上的每个像素的前向矢量(我已经有)旋转1-2度:
void Camera::Control(int x, int y)
{
switch (mode) {
case AVATAR:
if (x < prevX) direction.Rotate(1. * (prevX - x), up.Inverted());
if (x > prevX) direction.Rotate(1. * (x - prevX), up);
if (y < prevY) direction.Rotate(1. * (prevY - y), direction % up);
if (y > prevY) direction.Rotate(1. * (y - prevY), up % direction);
direction.Normalize();
//up = (direction % up) % direction; //UP in vitual space or for the camera?
prevX = x;
prevY = y;
//Debug vector values:
//printf("\nwinX: %d\twinY: %d\n", x, y);
//printf("radX: %0.3f\tradY: %0.3f\n", x, y);
//printf("dirX: %0.3f\ndirY: %0.3f\ndirZ: %0.3f\n", direction.X, direction.Y, direction.Z);
//printf("posX: %0.3f\nposY: %0.3f\nposZ: %0.3f\n", position.X, position.Y, position.Z);
break;
case ORBIT: /* ... */ break;
default: break;
}
}
void Camera::Control(int x, int y)
{
switch (mode) {
case AVATAR:
if (x < prevX) direction.Rotate(1. * (prevX - x), up.Inverted());
if (x > prevX) direction.Rotate(1. * (x - prevX), up);
if (y < prevY) direction.Rotate(1. * (prevY - y), direction % up);
if (y > prevY) direction.Rotate(1. * (y - prevY), up % direction);
direction.Normalize();
//up = (direction % up) % direction; //UP in vitual space or for the camera?
prevX = x;
prevY = y;
//Debug vector values:
//printf("\nwinX: %d\twinY: %d\n", x, y);
//printf("radX: %0.3f\tradY: %0.3f\n", x, y);
//printf("dirX: %0.3f\ndirY: %0.3f\ndirZ: %0.3f\n", direction.X, direction.Y, direction.Z);
//printf("posX: %0.3f\nposY: %0.3f\nposZ: %0.3f\n", position.X, position.Y, position.Z);
break;
case ORBIT: /* ... */ break;
default: break;
}
}
Strafe效果很好:
void Camera::Control(int key)
{
switch (key) {
case 'w': position += direction.Normal(); break;
case 's': position -= direction.Normal(); break;
case 'a': position += (up % direction).Normal(); break;
case 'd': position += (direction % up).Normal(); break;
default: break;
}
}
相机如何刷新其视图:
void Camera::Control(int key)
{
switch (key) {
case 'w': position += direction.Normal(); break;
case 's': position -= direction.Normal(); break;
case 'a': position += (up % direction).Normal(); break;
case 'd': position += (direction % up).Normal(); break;
default: break;
}
}
向量的旋转:
void Camera::Draw()
{
gluLookAt(position.X, position.Y, position.Z, position.X + direction.X, position.Y + direction.Y, position.Z + direction.Z, up.X, up.Y, up.Z);
}
void Camera::Draw()
{
gluLookAt(position.X, position.Y, position.Z, position.X + direction.X, position.Y + direction.Y, position.Z + direction.Z, up.X, up.Y, up.Z);
}
当我测试旋转功能并且整个概念仅在X轴上旋转时,它工作正常。我可以看看向量(Y轴)。仅围绕(方向%向上)和(向上%方向)旋转也有效。 (
定义了交叉乘积。)当我计算X和Y位置的旋转时会出现问题。有什么想法吗?void Vector::Rotate(float angle, float x, float y, float z)
{
float rad = angle * PI / 180.;
float s = sin(rad), c = cos(rad);
float matrix[9] = {
x*x*(1-c)+c, y*x*(1-c)-s*z, z*x*(1-c)+s*y,
x*y*(1-c)+s*z, y*y*(1-c)+c, z*y*(1-c)+s*x,
x*z*(1-c)-s*y, y*z*(1-c)+s*x, z*z*(1-c)+c
};
*this = Vector(X * matrix[0] + Y * matrix[3] + Z * matrix[6], X * matrix[1] + Y * matrix[4] + Z * matrix[7], X * matrix[2] + Y * matrix[5] + Z * matrix[8]);
}
void Vector::Rotate(float angle, Vector& axis)
{
Rotate(angle, axis.X, axis.Y, axis.Z);
}
答案 0 :(得分:1)
计算方向%向上并在应用Y旋转之前对结果进行标准化。