ARKit与SceneKit坐标系的比较

10
我试图理解ArKit中引入的不同元素及它们在SceneKit中的可能对等物之间的区别:
  • SCNNode.simdTransformSCNNode.transform。在ARKit中,人们似乎使用SCNNode.simdTransform而非SCNNode.transform。它们有什么不同?simdTransform似乎使用列优先顺序,而transform(SCNMatrix4)是行优先的。如何将它们转换为彼此?只需转置吗?如果我使用transform而非simdTransform,跟踪似乎不会那么好。这是预期的还是只是一种印象?如果我设置一个属性,然后设置另一个属性会发生什么?

  • ARFrame.cameraScene.pointOfView:查看它们的变换,它们似乎有些不同:

.

// ARFrame.camera.transform (matrix_float4x4)
-0.01 0.99  -0.11 0.02
-0.99 0.00  0.11  0.06
0.10  0.11  0.98  0.0
0.0   0.0   0.0   1.0

// sceneView.pointOfView.transform (SCNMatrix4)
// or sceneView.pointOfView.simdTransform^T (matrix_float4x4)
0.99  0     0.11   0
0.01  0.99  -0.12  0
-0.11 0.11  0.98   0
0.03  0.6   0.0    0.99

他们除了旋转方向不同,还有其他区别吗?

1
我有这样的印象,如果我使用transform而不是simdTransform,跟踪效果不太好。这是预期的还是只是我的印象?;-) 只有你能告诉我们,是你的印象还是你通过查看Xcode日志等硬证据发现了问题,例如“[Technique] World tracking performance is being affected by resource constraints”。如果是后者,那将非常有趣。 - PDK
2个回答

6

无论是SceneKit还是ARKit,都包含了被定义为SIMD类型的符号。由于ARKit导入了SceneKit,因此在SceneKit中定义的SIMD符号可供两者使用。SIMD类型使并行计算成为可能,因此使用它们可以提高应用更新逻辑的性能。正如你所发现的那样,有时候没有方便的方法来转换SIMD类型及其旧的SceneKit或Core Graphics等价物之间的差异,因此通常通过在可能的情况下一致地使用SIMD来获得更清晰的代码。

更新影响节点变换的任何属性也会更新其其他变换属性。这同样适用于本地和世界坐标。

ARFramecamera属性描述了设备的硬件摄像头,而不是用于渲染场景的虚拟相机。虽然我希望有一个紧密的对应关系,但我猜测您正在轮询SCNCamera实例之前的ARCamera实例已在渲染循环期间更新。如果可以的话,我建议从适当的委托方法驱动这些更新,因为您将知道相关数据已经更新。


1
很好的总结。此外,有关ARAnchorSCNNode定位的更多信息,请参见此答案 - rickster

0

我不认为SCNMatrix4遵循你所说的行主约定。请考虑以下内容:

func makeTranslationMatrix(tx: Float, ty: Float, tz: Float) -> simd_float4x4 {
    var matrix = matrix_identity_float4x4

    matrix[3, 0] = tx
    matrix[3, 1] = ty
    matrix[3, 2] = tz

    return matrix
}

var T1 = makeTranslationMatrix(tx: 1, ty: 2, tz: 3)
print(T1.columns.0)
print(T1.columns.1) 
print(T1.columns.2) 
print(T1.columns.3) 
/*
T1
float4(1.0, 0.0, 0.0, 0.0)
float4(0.0, 1.0, 0.0, 0.0)
float4(0.0, 0.0, 1.0, 0.0)
float4(1.0, 2.0, 3.0, 1.0)
*/

var sceneT1 = SCNMatrix4MakeTranslation(1, 2, 3)
print("\(sceneT1.m11), \(sceneT1.m12), \(sceneT1.m13), \(sceneT1.m14)")
print("\(sceneT1.m21), \(sceneT1.m22), \(sceneT1.m23), \(sceneT1.m24)")
print("\(sceneT1.m31), \(sceneT1.m32), \(sceneT1.m33), \(sceneT1.m34)")
print("\(sceneT1.m41), \(sceneT1.m42), \(sceneT1.m43), \(sceneT1.m44)")
/*
sceneT1
1.0, 0.0, 0.0, 0.0
0.0, 1.0, 0.0, 0.0
0.0, 0.0, 1.0, 0.0
1.0, 2.0, 3.0, 1.0
*/

正如您所看到的,SCNMatrix4 的翻译值存储在第四列中的 m41、m42、m43 中。由于矩阵被转置,这些值可能存储在 m41、m42、m43 中,并且实际上将翻译值存储在第四行中。这个 问题 解决了这种混淆。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接