移动摄像机时,为什么“极角”应限制在的范围内?

在“使用DirectX12进行3D游戏编程的介绍:Frank D. Luna”的示例代码d3d12book-master\Chapter 6 Drawing in Direct3D\Box\BoxApp.cpp中,通过三个variablesmTheta修改相机位置,方位角为mPhi对于极角, mRadius ,在鼠标移动事件处理程序中。

如代码所示, mTheta没有任何限制。 但是, mPhi限制为[0,PI]; 如果限制被注释掉,则图像在[0,PI]的边界处突然改变。 你能否帮助评论这种限制背后的推理? 是否有可能看到相机在[0,PI]的边界上连续旋转? O_O

初始化为构造函数中的世界空间中的某些值

  XMFLOAT4X4 mWorld = MathHelper::Identity4x4(); XMFLOAT4X4 mView = MathHelper::Identity4x4(); XMFLOAT4X4 mProj = MathHelper::Identity4x4(); float mTheta = 1.5f*XM_PI; float mPhi = XM_PIDIV4; float mRadius = 5.0f; 

在鼠标移动中修改

 void BoxApp::OnMouseMove(WPARAM btnState, int x, int y) { if((btnState & MK_LBUTTON) != 0) { // Make each pixel correspond to a quarter of a degree. float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x)); float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y)); // Update angles based on input to orbit camera around box. mTheta += dx; mPhi += dy; // Restrict the angle mPhi. mPhi = MathHelper::Clamp(mPhi, 0.1f, MathHelper::Pi - 0.1f); } mLastMousePos.x = x; mLastMousePos.y = y; } 

用于更新相机位置

 void BoxApp::Update(const GameTimer& gt) { // Convert Spherical to Cartesian coordinates. float x = mRadius*sinf(mPhi)*cosf(mTheta); float z = mRadius*sinf(mPhi)*sinf(mTheta); float y = mRadius*cosf(mPhi); // Build the view matrix. XMVECTOR pos = XMVectorSet(x, y, z, 1.0f); XMVECTOR target = XMVectorZero(); XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); XMMATRIX view = XMMatrixLookAtLH(pos, target, up); XMStoreFloat4x4(&mView, view); XMMATRIX world = XMLoadFloat4x4(&mWorld); XMMATRIX proj = XMLoadFloat4x4(&mProj); XMMATRIX worldViewProj = world*view*proj; // Update the constant buffer with the latest worldViewProj matrix. ObjectConstants objConstants; XMStoreFloat4x4(&objConstants.WorldViewProj, XMMatrixTranspose(worldViewProj)); mObjectCB->CopyData(0, objConstants); } 

这是因为向上。

它指向并允许您的相机正确转动。 它总是一样的:当你改变相机的方向时,你不会改变它的值。

从我记忆中,像XMMatrixLookAtLH这样的函数将会“修复”向上的vector:它将首先从up和(target – eye)创建“side”向量,然后从“side”和(target-eye) “起来”做出正确的变换matrix。

这使得所有的操作都变得简单,并且在你不超过pi或0时“修复自己”,但是当你这样做的时候,就好像你正在告诉相机“翻转”方向一样。 当你正好处于零或pi时,你的“向上”向量与你的“向前”向量平行,这不足以形成基础(你需要两个,这就是你基本上提供给XMMatrixLookAtLH )。

通过在[0,pi]之间夹住phi,确保您的转换matrix总是有效的,并为您的用户提供“平滑”的体验。


为了解决这个问题,我不确定你只能使用phi和theta。 我想不出从头到尾的正确方法,因为我不记得有制作这样的相机。 你可以探索的方法是在更新theta的同时保持一个“side”向量,并使用这个向量和(目标 – 眼睛)向量来创建向上的向量(通过使用交叉产品)。