首页 文章

ARKit vs SceneKit 坐标

提问于
浏览
9

我试图理解 ArKit 中引入的不同元素与 SceneKit 中它们可能的等价物之间的区别:

  • SCNNode.simdTransform vs SCNNode.transform。在 ARKit 中,似乎人们使用SCNNode.simdTransform而不是SCNNode.transform。他们有什么不同? simdTransform 似乎使用列主要顺序,而 transform(SCNMatrix4)是行主要。如何将一个转换为另一个?只需转置?我的印象是,如果我使用transform而不是simdTransform,跟踪也不会起作用。这是预期的还是仅仅是一种印象?如果我设置了一个属性,如果我再设置另一个属性会怎样?

  • ARFrame.camera vs Scene.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

它们是相同的减一轮吗?

2 回答

  • 6

    SceneKit 和 ARKit 都包含定义为 SIMD 类型的符号。由于 ARKit 导入 SceneKit,因此两者都可以访问 SceneKit 中定义的 SIMD 符号。 SIMD 类型支持并行计算,因此使用它们可以提高应用程序更新逻辑的性能。正如您所发现的,在 SIMD 类型及其旧版 SceneKit 或 Core Graphics 等效项之间进行转换并不总是方便的方法,因此您通常会尽可能使用 SIMD 来获得更清晰的代码。

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

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

  • 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 - 第 4 列中。由于矩阵被转置,这些值可能存储在m41, m42, m43中,然后它们实际上将转换值存储在第 4 行中。这个涵盖了这种混乱。

相关问题