2016-09-30 108 views
0

我的目標是讓用戶上傳的3D模型,並使用他們的網絡瀏覽器放置它們。爲此,我使用BabylonJS - &其工作正常。之後,我希望我的用戶能夠在原生應用程序中查看與使用網絡瀏覽器設置相同位置的相同模型。我用於本地應用程序的框架是OpenSceneGraph(OSG)。我遇到的問題是我無法正確地使旋轉工作,以至於OpenSceneGraph正確地反映了BabylonJS中正在發生的事情。轉換歐拉角度的旋轉,以軸+角

我在BabylonJS中使用歐拉角 - 因爲它們很容易讓網站用戶理解(例如,圍繞X軸旋轉90度,繞Y軸旋轉180度,圍繞Z軸旋轉0度;例如模型。 rotation = new BABYLON.Vec3(90,180,0))。然而,OSG使用OpenGL glrotate()函數,該函數需要旋轉軸和旋轉角度。爲此,我使用BabylonJS從歐拉角度創建一個四元數;然後用我寫的基於關閉Java示例此頁面上的功能:

http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm

function getAxisAngle(){ 
    var q = BABYLON.Quaternion.RotationYawPitchRoll(m.rotation.y,  m.rotation.x, m.rotation.z),s,r={}; 
    /*Convert quaternion to axis+angle*/ 
    if(q.w > 1){ 
     q = q.normalise(); 
    } 
    r.angle = BABYLON.Tools.ToDegrees(2 * Math.acos(q.w)); 
    s = Math.sqrt(1-q.w*q.w); 
    if(s < 0.001){ 
     r.ax = q.x; 
     r.ay = q.y; 
     r.az = q.z; 
    }else{ 
     r.ax = q.x/s; 
     r.ay = q.y/s; 
     r.az = q.z/s; 
    } 
    return r; 
} 

我意識到BJS和OSG之間的根本區別在於BJS是左手座標系; OSG是右撇子;所以我通過將面部繞線設置爲順時針將OSG製成左手;並將我的模型的z軸縮放-1。

它在一個基本水平工作,如果我隔離在時間1軸;例如如果我只圍繞y軸旋轉;並且不要圍繞任何其他軸旋轉 - 它看起來很好。但是,如果我嘗試同時結合兩個或三個歐拉角度,我無法讓它在OSG中看起來一樣。

我讀過,歐拉角不推薦;部分原因是旋轉施加到每個軸的順序很重要。這是一個可能的原因嗎?

+0

我猜,因爲你正在使用一端四元,並使用歐拉角度上,你所熟悉的使用四元對歐拉之間的優勢差異的另一端,由於萬向鎖角度。如果您的應用程序使用歐拉角來旋轉多個旋轉軸併發生萬向節鎖定,那麼您的旋轉將停止工作。如果您更願意繼續使用歐拉角度來旋轉軸線,那麼您需要將它們限制在一起,以防止萬向節鎖定,例如[-89.99,89.99]。 (...續) –

+0

(...續)萬向鎖定的原因是由於90度或PI/4是直角或正交。正弦(90)或正弦(PI/4)= 1,餘弦(90)或餘弦(PI/4)= 0,因爲切線=正弦/餘弦這裏您的正切是未定義的,因爲除以0的所以當旋轉的一種物體在X軸上90°,然後由Y或Z旋轉90°或-90,會發生什麼情況是這兩個軸會互鎖,並且當您再次從兩個鎖定軸中的任何一個旋轉時,該功能無法確定要旋轉哪個軸。 (...繼續) –

+0

(...繼續)你可以查看這個視頻瞭解四元數,也許不是數學上的,而是至少在視覺上。 https://www.youtube.com/watch?v=zc8b2Jo7mno –

回答

0

在我看來,不要試圖讓OSG左撇子,而翻譯你的旋轉角度的「邏輯」的含義,並應用它們來OSG是指所使用的方式。

將您的加載模型放置在osg :: PositionAttitudeTransform(或MatrixTransform)下,然後通過連接2個四元數來計算正確的旋轉(姿態)以適用於您公開給用戶的2個旋轉角度。
舉例來說,如果你認爲「推銷」圍繞X軸旋轉,和「標題」繞Y,做這樣的事情:

osg::Quat attitude = osg::Quat(pitchAngle, osg::X_AXIS) * osg::Quat(headAngle, osg::Y_AXIS); 
transform->setAttitude(attitude); 

您可能需要反轉角度符號來得到正確的結果(從左到右傳遞)。

+0

感謝您的建議將嘗試並報告回! – Reece