2017-06-25 41 views
0

我把別人的意見,但我預期它沒有工作:的DirectX矩陣:相對變換到(在FPS等)面臨方向

M=inverse(inverse(M)*rotation_matrix); 

這是我更新的代碼:

void TestApp::Update(float dt) { 
    DirectX::SimpleMath::Matrix rotation = 
    Matrix::CreateFromYawPitchRoll(rot.y, rot.x, 0.0f); //Rotation Matrix 
    DirectX::SimpleMath::Matrix position = 
    Matrix::CreateTranslation(pos); //Postion Matrix 

    m_view = 
    DirectX::XMMatrixInverse(nullptr, DirectX::XMMatrixMultiply( 
    DirectX::XMMatrixInverse(nullptr, position), rotation)); //This uses the advice 
//m_view is the Camera/View Matrix 

for (int i = 0; i < 256; ++i) { 
    if (GetAsyncKeyState(i)) { 
     if (i == 87) { // W 
      pos.z += dt * playerSpeed; //Move Forward 

      continue; 

     } 
     else if (i == 68) { //D 
      pos.x -= dt * playerSpeed; //Move Right 
      continue; 

     } 
     else if(i == 83){//S 
      pos.z -= dt * playerSpeed; //Move Backwards 
      continue; 

     } 
     else if (i == 65) { // A 
      pos.x += dt * playerSpeed; //Move Left 
      continue; 

     } 

     else if (i == VK_NUMPAD8) { 
      rot.x -= dt; 
      continue; 
     } 
     else if (i == VK_NUMPAD4) { 
      rot.y += dt; 
     } 
     else if (i == VK_NUMPAD5) { 
      rot.x += dt; 
      continue; 
     } 
     else if (i == VK_NUMPAD6) { 
      rot.y -= dt; 
     } 
    } 
} 

這個機芯工作得很好,但是旋轉很不穩定。它不像FPS相機那樣繞世界起源旋轉。任何幫助?

我在DirectX Tool Kit中使用DirectX 11。該模型呈現良好,向前,向後,向左,向右移動像FPS相機一樣工作,但它是旋轉世界原點(0,0)。

回答

0

下面是使用OpenGL代替Direct X的較舊遊戲引擎的一部分。您可能必須調整座標系的指向性,但基本原則仍然適用。在3D環境中處理運動時;相機,玩家或世界反對的運動應該通過switch聲明來完成,而不是一堆if else聲明。

看看這個片段,在OpenGL遊戲引擎中完成旋轉運動。

void Player::move(Action action, float fDeltaTime) { 
    v3LookDirection = m_v3LookCenter - m_v3Position; 

    switch(action) { 
     case MOVING_FORWARD: { 
      // ... code here ... 
     } 
     case MOVING_BACK: { 
      // ... code here ... 
     } 
     case MOVING_RIGHT: { 
      // ... code here ... 
     } 
     case MOVING_LEFT: { 
      // ... code here ... 
     } 
     case LOOKING_LEFT: {   
      /*float fSin = -sin(fDeltaTime * m_fAngularSpeed); 
      float fCos = cos(fDeltaTime * m_fAngularSpeed); 

      m_v3LookCenter.m_fX = m_v3Position.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX); 
      m_v3LookCenter.m_fZ = m_v3Position.m_fZ + (fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX); 
      break;*/ 

      // Third Person 
      float fSin = sin(fDeltaTime * m_fAngularSpeed); 
      float fCos = -cos(fDeltaTime * m_fAngularSpeed); 

      m_v3Position.m_fX = m_v3LookCenter.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX); 
      m_v3Position.m_fZ = m_v3LookCenter.m_fZ + (fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX); 
      break; 
     } 
     case LOOKING_RIGHT: { 
      /*float fSin = sin(fDeltaTime * m_fAngularSpeed); 
      float fCos = cos(fDeltaTime * m_fAngularSpeed); 

      m_v3LookCenter.m_fX = m_v3Position.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX); 
      m_v3LookCenter.m_fZ = m_v3Position.m_fZ + (fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX); 
      break;*/ 

      // Third Person 
      float fSin = -sin(fDeltaTime * m_fAngularSpeed); 
      float fCos = -cos(fDeltaTime * m_fAngularSpeed); 

      m_v3Position.m_fX = m_v3LookCenter.m_fX + (-fSin * v3LookDirection.m_fZ + fCos * v3LookDirection.m_fX); 
      m_v3Position.m_fZ = m_v3LookCenter.m_fZ + (fCos * v3LookDirection.m_fZ + fSin * v3LookDirection.m_fX); 
      break; 
     } 
     case LOOKING_UP: { 
      m_v3LookCenter.m_fY -= fDeltaTime * m_fAngularSpeed * m_MouseLookState; 

      // Check Maximum Values 
      if (m_v3LookCenter.m_fY > (m_v3Position.m_fY + m_fMaxUp)) { 
       m_v3LookCenter.m_fY = m_v3Position.m_fY + m_fMaxUp; 
      } else if (m_v3LookCenter.m_fY < (m_v3Position.m_fY - m_fMaxDown)) { 
       m_v3LookCenter.m_fY = m_v3Position.m_fY - m_fMaxDown; 
      } 
      break; 
     } 
    } // switch 
} 

所有與m_v3...開始宣稱本地和成員變量是的Vector3對象。 Vector3對象有一個x,y,z組件,並且可以對向量執行的所有可用數學運算都是枚舉類型。

這個功能在我的Scene類中調用。

void Scene::playerAction(float fMouseXDelta, float fMouseYDelta) { 
    if (fMouseXDelta != 0.0f) { 
     m_player.move(LOOKING_RIGHT, fMouseXDelta); 
    } 

    if (fMouseYDelta != 0.0f) { 
     m_player.move(LOOKING_UP, fMouseYDelta); 
    } 
} 

而且還Scene::update()

void Scene::update() { 
    UserSettings* pUserSettings = UserSettings::get(); 
    AudioManager* pAudio = AudioManager::getAudio(); 

    bool bPlayerMoving = false; 

    // Movement 
    if (pUserSettings->isAction(MOVING_FORWARD)) { 
     m_player.move(MOVING_FORWARD, GameOGL::getPhysicsTimeStep()); 
     bPlayerMoving = true; 
    } 

    if (pUserSettings->isAction(MOVING_BACK)) { 
     m_player.move(MOVING_BACK, GameOGL::getPhysicsTimeStep()); 
     bPlayerMoving = true; 
    } 

    if (pUserSettings->isAction(MOVING_LEFT)) { 
     m_player.move(MOVING_LEFT, GameOGL::getPhysicsTimeStep()); 
     bPlayerMoving = true; 
    } 

    if (pUserSettings->isAction(MOVING_RIGHT)) { 
     m_player.move(MOVING_RIGHT, GameOGL::getPhysicsTimeStep()); 
     bPlayerMoving = true; 
    }  

    if (bPlayerMoving && !m_bPlayerWalking) { 
     pAudio->setLooping(AUDIO_FOOTSTEPS, true); 
     pAudio->play(AUDIO_FOOTSTEPS); 
     m_bPlayerWalking = true; 
    } 
    else if (!bPlayerMoving && m_bPlayerWalking) { 
     pAudio->stop(AUDIO_FOOTSTEPS); 
     m_bPlayerWalking = false; 
    } 

    // Bunch more code here. 
} 

這也紮成GameOGL類,與我不打算在這裏顯示messageHandler()工作。這來自一個由近5萬行代碼組成的大中型項目。在這裏展示每件作品都很大,所以請不要問,因爲這款引擎中的所有東西都集成在一起。我只是展示了用於旋轉運動的基本數學運算,無論是按鍵還是鼠標移動。

現在你必須記住這一點,因爲它很重要。您看到的Player課程中的實際計算結果可能無法直接使用。如果座標系的旋向與這裏使用的不一致,您必須使用合適的三角函數將相應的座標軸成員與適當的符號進行正確的計算。當螺旋性改變時,隱含的旋轉軸以及旋轉的初始方向也如此。不是3D數學樂趣?

編輯

哦,我還注意到,您正在使用DirectX's::CreateFromYawPitchRoll()來創建旋轉矩陣;這是好的,但你需要小心使用標準歐拉角的旋轉。如果你開始同時進行多個運動程度的旋轉,你最終會遇到Gimbal Lock。避免在3D旋轉中使用Gimbal鎖定問題;最好使用Quaternions對他們來說數學有點難以接受,他們的概念並不難理解,但使用它們其實很簡單,而且在計算上也非常有效。許多數學圖書館都包含它們; DirectX的數學庫應該和開放源代碼GLM數學庫一樣,廣泛用於OpenGL & GLSL。如果您不確定Gimbal Lock和Quaternion,可以通過Google搜索查找這些主題;有關於他們的大量信息。是不是先進的3D ...呃下襬... 4D數學樂趣?

0

你說從世界觀原點旋轉,像「如果你留在轉盤的邊緣,你在看中央」

我想你想你的對象從它自己的旋轉中央。

解決方案是,你應該旋轉你的對象,然後應用你的位置矩陣。

這是RESPONSABLE

m_view = 
    DirectX::XMMatrixInverse(nullptr, DirectX::XMMatrixMultiply( 
    DirectX::XMMatrixInverse(nullptr, position), rotation)) 

修復我覺得應該是應用旋轉 在OpenGL後的位置,你將適用於模型矩陣的計算

GLM :: MAT4 MVPmatrix =投影旋轉*查看*模型;

您可以旋轉視圖或模型矩陣並獲得2個不同的結果。

我不知道你的代碼和DirectX一般,但也許你應該顛倒2

m_view = 
     DirectX::XMMatrixInverse(nullptr, DirectX::XMMatrixMultiply( 
     DirectX::XMMatrixInverse(nullptr, rotation), position)) 

看看http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/