Answers:
以下是有关相机旋转(mouselook)的一些技巧。从头开始天真地实现了相机类之后,我发现我必须做一些其他的调整才能获得良好的旋转性能:
将鼠标坐标重置为每一帧的屏幕中心,以使鼠标永远不会卡在屏幕边框上
保持相机的“向上”矢量(禁止滚动)并重新计算“横向”矢量
禁止在垂直+ y轴上方向上或向下-y轴下方(向上/向下太远)向上查找
正确获得旋转顺序(先向上/向下,然后向左/右)
每帧重新标准化“上”,“目标”和“侧身”矢量
希望您可以使用其中一些代码来发挥自己的优势:
const int mouseDeltaX = mouseAxisX * (input.GetMouseX() - int(app.GetWidth()/2));
const int mouseDeltaY = -mouseAxisY * (input.GetMouseY() - int(app.GetHeight()/2)); // mouse y-offsets are upside-down!
// HACK: reset the cursor pos.:
app.SetCursorPosition(app.GetWidth()/2, app.GetHeight()/2);
float lookRightRads = mouseDeltaX * CAMERA_ANGULAR_SPEED_DEG * DEG_TO_RAD;
float lookUpRads = mouseDeltaY * CAMERA_ANGULAR_SPEED_DEG * DEG_TO_RAD;
// Limit the aim vector in such a way that the 'up' vector never drops below the horizon:
static const float zenithMinDeclination = DEG_TO_RAD * MIN_UPWARDS_TILT_DEG;
static const float zenithMaxDeclination = DEG_TO_RAD * (180.0f - MIN_UPWARDS_TILT_DEG);
const float currentDeclination = std::acosf(camera.aim_.y_); ///< declination from vertical y-axis
const float requestedDeclination = currentDeclination - lookUpRads;
// Clamp the up/down rotation to at most the min/max zenith:
if(requestedDeclination < zenithMinDeclination)
lookUpRads = currentDeclination - zenithMinDeclination;
else if(requestedDeclination > zenithMaxDeclination)
lookUpRads = currentDeclination - zenithMaxDeclination;
// Rotate both the "aim" vector and the "up" vector ccw by
// lookUpRads radians within their common plane -- which should
// also contain the y-axis: (i.e. no diagonal tilt allowed!)
camera.aim_.rotateAboutAxis(camera.right_, lookUpRads);
camera.up_.rotateAboutAxis(camera.right_, lookUpRads);
ASSERT_ORTHONORMAL(camera.aim_, camera.up_, camera.right_);
// Rotate both the "aim" and the "up" vector ccw about the vertical y-axis:
// (again, this keeps the y-axis in their common plane, and disallows diagonal tilt)
camera.aim_.rotateAboutAxis(Y_AXIS, -lookRightRads);
camera.up_.rotateAboutAxis(Y_AXIS, -lookRightRads);
camera.updateRightAxis();
注意:
mouseAxisX和mouseAxisY定义为+/- 1,具体取决于您是否希望将mouselook的x轴或y轴反转。通常,游戏至少在垂直轴上提供此选项。
MIN_UPWARDS_TILT_DEG的定义为1.0度(因此,允许观看者从-89度向下观看到+89度向上,这看起来非常令人信服,就像完整的180度垂直范围-极端情况下丢失的2度几乎可以忽略不计) 。
camera.aim_,camera.right_和camera.up_当然是3D向量,您可以从Wikipedia和任何数量的在线资源中整理出rotateAboutAxis()方法。Y_AXIS是固定常数(0,1,0)。
ASSERT_ORTHONORMAL()是仅调试模式的完整性检查,永远不会在优化/发布模式下进行编译。
预先为C样式的代码表示歉意...然后,再次,您从一个叫Mediocritus的家伙那里获得建议!; ^)
有几种解决方法(例如,请参见此处,此处和此处的教程,以及通过Google在互联网上提供的更多功能)。您可以在网上找到的资源中使用的技术可能略有不同(就D3D,XNA,OpenGL等而言),但是基本原理将是相同的:
您可以选择直接存储向量,或者根据需要和偏好每次都重新计算基础视图矩阵。该技术具有很大的灵活性,因此,如果您需要常规步骤之外的其他帮助,则可以使用更具体的查询发布新问题。
有关使用Direct3D的摄像头系统的实现的特定参考,我建议本文:http : //www.toymaker.info/Games/html/camera.html。作者还描述了可用于扩展实现的其他方法和功能。