0

Directx 11で動作する単純なカメラクラスがあり、前進と左右の回転が可能です。機銃掃射を実装しようとしていますが、いくつか問題があります。

機銃掃射は、カメラの回転がない場合、つまりカメラが 0, 0, 0 から始まる場合に機能します。しかし、カメラをいずれかの方向に回転させた後、斜めに機銃掃射したり、反転したり、奇妙なことをしたりするように見えます。

これは、この動作を示す Dropbox にアップロードされたビデオです。 https://dl.dropboxusercontent.com/u/287​​3587/IncorrectStrafing.mp4

そして、これが私のカメラクラスです。カメラ位置の計算に関係している気がします。機銃掃射でさまざまな計算を試しましたが、それらはすべて同じパターンと同じ動作に従うようです。また、ピッチングはまだ実装されていないため、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);
}
4

1 に答える 1

0

カメラシステムを実装する私の何時間ものフラストレーションで、ビューマトリックスがオルソ正規化されていないことに関係があることをお勧めします。これは凝った言い方です。行列で表される 3 つのベクトルは、長さが 1 (正規化) に保たれておらず、直交していません (互いに 90 度)。

回転を表すビュー マトリックスの 3x3 部分は、任意の時点でのビューの現在の x、y、z 軸を表す 3 つのベクトルを表します。float 値の不正確さに起因する丸め誤差により、これら 3 つのベクトルが伸びたり、縮んだり、発散したりして、あらゆる種類の問題を引き起こす可能性があります。

したがって、一般的な戦略は、回転する場合は数フレームごとに再直交正規化することです。また、機銃掃射または前後に移動する場合は、前後のビュー/ルックアット ベクトルと機銃掃射の右ベクトルの現在の値を使用して位置を変更します。

例えば

//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 +=

とにかく、回転については、ビューと右のベクトルを回転させるだけで、クラスを次のように書き直すことができます

class Camera
{
  Vector3 rightVec,lookVec,position;

  void Rotate(float deltaTime)
}

わかりますか?これは、考えさせるための大まかな例です。

于 2013-10-21T02:44:27.010 に答える