2017-03-06 129 views
4

我正在嘗試使用GameplayKit的GKAgent3D類在場景中移動SCNNode。我能夠用代理的位置更新SCNNode,但不能輪換。代理輪換的問題存儲爲matrix_float3x3,與MatrixKit用於存儲旋轉信息的任何數據類型不匹配。將matrix_float3x3旋轉轉換爲SceneKit

所以我想知道的是,如果有一個簡單的函數或方法可以將存儲爲matrix_float3x3的旋轉轉換爲任何SceneKit數據類型?

回答

4

爲了擴展@rickster的答案,這裏有一個很好的方法,在Swift中採用4x4矩陣的左上角3x3,利用iOS 11/tvOS 11/High Sierra版本中的擴展simd支持SceneKit:

extension float4 { 
    var xyz: float3 { 
     return float3(x, y, z) 
    } 

    init(_ vec3: float3, _ w: Float) { 
     self = float4(vec3.x, vec3.y, vec3.z, w) 
    } 
} 

extension float4x4 { 
    var upperLeft3x3: float3x3 { 
     let (a,b,c,_) = columns 
     return float3x3(a.xyz, b.xyz, c.xyz) 
    } 

    init(rotation: float3x3, position: float3) { 
     let (a,b,c) = rotation.columns 
     self = float4x4(float4(a, 0), 
         float4(b, 0), 
         float4(c, 0), 
         float4(position, 1)) 
    } 
} 

然後更新您的代理人,以配合您的節點的方向,你會寫:

agent.rotation = node.simdTransform.upperLeft3x3 

或者,如果有問題的節點是不是在「根」級(如在,根節點的直接子節點)中,您可能想要使用節點的worldTransform:

agent.rotation = node.simdWorldTransform.upperLeft3x3 

編輯:如果所討論的節點具有一個附加的動態物理體,或正在用一種SCNTransaction塊動畫,節點的演示節點將更加準確地反映在屏幕上的當前位置:

agent.position = node.presentation.simdWorldPosition 
agent.rotation = node.presentation.simdWorldTransform.upperLeft3x3 

編輯:添加上面的代碼去往另一個方向,移動節點以匹配代理。

node.simdTransform = float4x4(rotation: agent3d.rotation, position: agent3d.position) 

請注意,如果您有連接到該節點的物理體,它應該是kinematic而非dynamic如果你要直接修改節點的這種方式變換。

+0

感謝發佈,非常有幫助!該代碼比我想出的要乾淨得多。 – Phi

+0

同意,這真的很有幫助。 – possen

5

SceneKit將變換矩陣設置爲SCNMatrix4,並提供了用於從Swift轉換的實用程序,用於從Swift轉換的實用程序:init(_ m: float4x4)以及用於ObjC/C++的SCNMatrix4FromMat4

不幸的是,我沒有看到使用3x3是4x4左上角的假設在SIMD 3x3和4x4矩陣之間進行轉換的內置方法。 (看起來像你期望在SIMD庫中,所以它的值大約爲filing a bug to Apple。)

但是,自己提供一個並不難:只需使用3x3的三列向量構建一個4x4列向量(填充到float4向量,零部件爲w組件)以及第四列的標識(0,0,0,1)。 (實現代碼留給讀者,部分原因是我不想爲三種語言編寫代碼。)在將float3x3轉換爲float4x4後,您可以將其轉換爲SCNMatrix4


編輯:在iOS的11/tvOS 11/MacOS的10.13(爲什麼他們不只是稱今年的MacOS版本11,太?),SceneKit有使用SIMD類型的全並行的API集直接像float4x4;例如simdTransform。但是,您仍然需要將3x3轉換爲4x4矩陣。

+0

謝謝Rickster,我非常感謝你的透徹答覆,對我非常有幫助。至少現在我知道我需要做什麼,我正在通過simd和其他庫進行搜索,只是希望或許我忽略了一種方法/功能。最後一件事,我已經看到了你對其他問題的其他答案,你是一個瘋狂的巫師,我希望有一天能像你一樣有知識。再次感謝! – Phi

+0

嘿瑞恩對於遲到的回覆抱歉,我手上沒有任何示例代碼,但如果您有關於實施的具體問題,請告訴我。 – Phi

+0

感謝您更新Rickster,很高興他們添加了SIMD類型,我非常期待使用它們8)。 – Phi