简体   繁体   English

3D第一人称视角相机横冲直撞

[英]3D First Person Camera strafing at angle

I have a simple camera class working in directx 11 allowing moving forward and rotating left and right. 我在DirectX 11中有一个简单的相机类,它允许向前移动和向左和向右旋转。 I'm trying to implement strafing into it but having some problems. 我正在尝试实施,但是遇到了一些问题。

The strafing works when there's no camera rotation, so when the camera starts at 0, 0, 0. But after rotating the camera in either direction it seems to strafe at an angle or inverted or just some odd stuff. 在没有相机旋转的情况下,扫射有效,因此,当相机从0、0、0开始时。但是,沿任一方向旋转相机后,它似乎会以一定角度扫射或倒转或出现一些奇怪的东西。

Here is a video uploaded to Dropbox showing this behavior. 这是上传到Dropbox的视频,显示了此行为。 https://dl.dropboxusercontent.com/u/2873587/IncorrectStrafing.mp4 https://dl.dropboxusercontent.com/u/287​​3587/IncorrectStrafing.mp4

And here is my camera class. 这是我的相机课。 I have a hunch that it's related to the calculation for camera position. 我预感这与相机位置的计算有关。 I tried various different calculations in strafe and they all seem to follow the same pattern and same behavior. 我在strafe中尝试了各种不同的计算,它们似乎都遵循相同的模式和相同的行为。 Also the m_camera_rotation represents the Y rotation, as pitching isn't implemented yet. 另外,m_camera_rotation表示Y旋转,因为尚未实现俯仰。

#include "camera.h"


camera::camera(float x, float y, float z, float initial_rotation) {
m_x = x;
m_y = y;
m_z = z;
m_camera_rotation = initial_rotation;

updateDXZ();
}


camera::~camera(void)
{
}

void camera::updateDXZ() {
m_dx = sin(m_camera_rotation * (XM_PI/180.0));
m_dz = cos(m_camera_rotation * (XM_PI/180.0));
}

void camera::Rotate(float amount) {
m_camera_rotation += amount;

updateDXZ();
}

void camera::Forward(float step) {
m_x += step * m_dx;
m_z += step * m_dz;
}

void camera::strafe(float amount) {
float yaw = (XM_PI/180.0) * m_camera_rotation;

m_x += cosf( yaw ) * amount;
m_z += sinf( yaw ) * amount;
}

XMMATRIX camera::getViewMatrix() {
updatePosition();

return XMMatrixLookAtLH(m_position, m_lookat, m_up);
}

void camera::updatePosition() {
m_position = XMVectorSet(m_x, m_y, m_z, 0.0);
m_lookat = XMVectorSet(m_x + m_dx, m_y, m_z + m_dz, 0.0);
m_up = XMVectorSet(0.0, 1.0, 0.0, 0.0);
}

With my many hours of frustration implementing camera systems Id suggest its something to do with your view matrix not being ortho-normalized. 经过数小时的烦恼,实施摄像头系统后,Id提出建议,这与您的视图矩阵未进行正交归一化有关。 Thats a fancy way of saying - the three vectors represented in the matrix are not kept to the length of 1 (normalized) and also not orthogonal (at 90 degrees to each other). 那是种花哨的说法-矩阵中表示的三个向量的长度不保持1(标准化),也不正交(彼此成90度)。

The 3x3 part of a view matrix representing rotation represents 3 vectors that describe the current x,y and z axes of your view at any given time. 表示旋转的视图矩阵的3x3部分表示3个向量,这些向量描述了任意给定时间视图的当前x,y和z轴。 Due to rounding off errors caused by the imprecision of float values these three vectors can stretch, shrink and diverge to cause all manner of headaches. 由于浮点值的不精确导致的舍入误差,这三个向量可能会拉伸,收缩和发散,从而引起各种麻烦。

So a general strategy is re-orthonormalize every few frames if rotating and also another thing - when strafing or moving back/forward change the position using the current value of your view/lookat vector for back/forward and right vector for strafing. 因此,一般的策略是在旋转时每隔几帧重新进行正交标准化,还有另一件事-进行划面或向后/向前移动时,请使用视图/后视向量的当前值来进行向前/向后调整,并使用正确的向量来进行位置调整。

eg 例如

//deltaTime for all of these examples is the amount of time elapsed since the last  
//frame of your game loop - this ensures smooth movement, or you could fix your   
//timestep -  Glen Fielder did a great article on that please google for it!

void MoveForward(float deltaTime)
{
  position += (deltaTime * lookAtVector); 
}

void MoveBackwards(float deltaTime)
{
  position -= (deltaTime * lookAtVector);
}

void StrafeLeft(float deltaTime)
{
  position -= (deltaTime * rightVector);
}

//do something similar for StrafeRight but use a +=

Anyway for the rotations just rotate the view and right vectors, maybe re-write your class as follows 无论如何旋转,只要旋转视图和正确的向量,也许可以如下重写您的类

class Camera
{
  Vector3 rightVec,lookVec,position;

  void Rotate(float deltaTime)
}

You get the idea? 你有主意吗? Thats a rough example just to get you thinking. 那只是一个粗糙的例子,只是为了让您思考。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM