2016-01-24 74 views
0

我正在構建一個簡單的第一人稱攝像機,它假定向上矢量總是匹配世界+ Z軸,即不滾動。使用四元數的方位在第一人稱攝像機中的夾距

我正在使用四元數來存儲相機的方向。 (我試圖遠離歐拉角。)

現在,假設我想限制攝像機的可能音高到-85到85度的音高。這意味着當我對攝像機應用一些附加音調時,如果音高超過上述閾值,我需要有某種邏輯來限制音高。

考慮到相機的方向存儲爲四元數,有效的方法是什麼?

我目前的想法是從四元數中提取正向(即看看At)和右向量。將前向量和全局X或Y向量投影到由右向量法線形成的平面中,然後找到這些投影向量之間的角度差。儘管每次我改變球場,但這似乎有很多數學要做。假設甚至一個有效的解決方案,我不知道是否有更好和更簡單的方法...

這裏是我當前的間距設置代碼(使用本徵數學庫):

void Camera::pitch(float angleInRadians) 
{ 
    if (angleInRadians != 0.0) 
    { 

     // TODO: Apply pitch restriction. <----------------- how? 

     mRotation *= Quaternionf(AngleAxisf(-angleInRadians, Vector3f::UnitX())); 
     mRotation.normalize(); 

     mIsViewMatrixDirty = true; 
    } 
} 

回答

0

最終通過將音高跟蹤爲成員變量來解決此問題。實際的方向仍然存儲在四元數中。

任何時候我通過pitch()函數累積了方向,或者通過使用lookAt(vec3 target)函數(未在原始問題中發佈)重置音高,此音高成員變量會相應更新。

lookAt函數中,我使用asin(direction.y())來計算音調。如果音高超出界限,就會拋出一個斷言(而不是糾正它)。

pitch(float angleDelta)功能,如果它超過了最小/最大界限間距增量被校正。對三角洲應用適當的限制後,它會累積到四元數中。

1

我不認爲在這種情況下你不必擔心四元數;你的情況關注的是以弧度表示的旋轉角度,無論是俯仰,偏航還是滾轉。你想防止這個角度超越界限或有一個特定的範圍。要做到這一點很簡單,您只需要一個約束或鉗位功能。

template<class T> 
inline void clamp(T min, T max, T &value) {  
    if (value < min) { 
     value = min; 
     return; 
    } 

    if (value > max) { 
     value = max; 
    }  
} // clamp 

一旦你可使用這個方便的通用的數學函數,你那麼有兩種選擇:要麼你可以使其預定此函數調用中所設定的範圍,也可以修改現有的間距功能的簽名包括兩個更多的值,以便呼叫者或用戶可以適當地設置這些值。那麼你的俯仰功能中,你只想用這個如下:

void Camera::pitch(float angleInRadians) { 
    clamp(-85.0f, 85.0f, angleInRadians); 

    mRotation *= Quaternionf(AngleAxisf(-angleInRadians, Vector3f::UnitX())); 
    mRotation.normalize(); 
} 

或者

void Camera::pitch(float angleInRadians, float min, float max) { 
    clamp(min, max, angleInRadians); 

    mRotation *= Quaternionf(AngleAxisf(-angleInRadians, Vector3f::UnitX())); 
    mRotation.normalize(); 
} 

我想這應該解決您的問題,也是它刪除if語句檢查的有效性。我省略了你最後一次在你的職責中的陳述,因爲我不確定你的職業是否需要這個職位,但我相信在回答你的問題時寫出這個答案並不重要。

+0

感謝您抽出寶貴的時間來回答這個問題。我應該更清楚地表明在弧度的角度被累積到mRotation ......你中有我,雖然想...我可以「俯仰」存儲爲成員變量和使用,作爲一個辦法做到在球場上簿記方向。但這種方法的問題在於'pitch()'func不是我支持的唯一會影響音高值的API。我也想支持lookAt(vec3 target,vec3 camPos)功能。我想我可以明確計算該功能的音高,但要保持音高值。 – user8709

+0

你可以使相機擁有這些成員始終使用你的資源的shared_ptr,以確保所有領域都在同步數據。 –

+0

另外;即使你採取了適合你需求的不同方法,所提供的模板鉗位功能在許多其他領域中始終有用,適用於可重用的通用代碼。我在3D圖形引擎中經常使用它;但是當我從OpenGL v1.0切換到3.5-4.5時,我開始使用具有自己鉗位功能的GLM。 –

相關問題