下面是使用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數學樂趣?