2017-08-29 168 views
0

我使用的是帶有SceneKit的ARKit。當用戶按下一個按鈕時,我創建一個錨點並與其對應的SCNNode添加一個3D對象(從項目中的.scn文件加載)。SceneKit - 圍繞X軸和Z軸旋轉對象

將3D物體朝向相機放置,與相機具有相同的方向。我想讓它看起來像物體躺在平面上,如果是這樣的話,不要傾斜。所以,如果我知道了,我需要應用一個旋轉變換,以便圍繞X和Z軸的旋轉變爲0.

我的嘗試是:取節點的x和z eulerAngles,將它們顛倒和旋轉是圍繞量各軸

let rotationZ = rotationMatrixAroundZ(radians: -node.eulerAngles.z) 
let rotationX = rotationMatrixAroundX(radians: -node.eulerAngles.x) 

let rotationTransform = simd_mul(rotationTransformX, rotationTransformZ) 
node.transform = SCNMatrix4(simd_mul(simd_float4x4(node.transform), rotationTransform)) 

這適用所有適合大多數情況下,但在某些物體在完全陌生的方式旋轉。我應該將 旋轉角度設置爲除當前歐拉角的倒數之外的任何其他值嗎?直接將角度設置爲0根本不起作用。

+0

你使用約束? –

+0

不,我試着用SCNLookAtConstraint和look(at :)方法試驗,但沒有一個滿足我的需求 – leandrodemarco

回答

2

我已經在做SCNMatrix4旋轉簡單遇到這個,並找出我遇到gimbal lock。解決方案是圍繞一個軸旋轉節點,將其父節點轉換爲另一個節點SCNNode(),然後圍繞另一個軸旋轉父節點。希望有所幫助。

+0

謝謝!我想我正在跑到萬向節鎖,但沒想到用這種方法來解決它! – leandrodemarco

0

嗯,我設法解決了一個問題,但我並不滿意,所以我不會回答這個問題。基本上,我定義了2度的閾值,並繼續應用這些旋轉,直到X和Z周圍的歐拉角都低於上述閾值。

func layDownNode(_ node: SCNNode) { 
    let maxErrDegrees: Float = 2.0 
    let maxErrRadians = GLKMathDegreesToRadians(maxErrDegrees) 

    while (abs(node.eulerAngles.x) > maxErrRadians || abs(node.eulerAngles.z) > maxErrRadians) { 
     let rotationZ = -node.eulerAngles.z 
     let rotationX = -node.eulerAngles.x 

     let rotationTransformZ = rotationMatrixAroundZ(radians: rotationZ) 
     let rotationTransformX = rotationMatrixAroundX(radians: rotationX) 

     let rotationTransform = simd_mul(rotationTransformX, rotationTransformZ) 

     node.transform = SCNMatrix4(simd_mul(simd_float4x4(node.transform), rotationTransform)) 
    } 
} 
0

您不必到節點上的矩陣變換,你可以簡單地繞特定軸可能在做旋轉邏輯上有點簡單。

你可以這樣做:

node.runAction(SCNAction.rotateBy(x: x, y: y, z: z, duration: 0.0)) 

不知道這是什麼樣的,你正在尋找的東西,但它是比

+0

感謝您的建議,沒有探索過這個選項。我會試試看! – leandrodemarco