首页 文章

如何将相机外部矩阵转换为 SCN 相机位置和旋转

提问于
浏览
3

我正在尝试使用SceneKit实现增强现实。

通过使用 ARuco(OpenCV 增强现实库)估计标记的姿态,我得到了固有的相机矩阵和外部矩阵。

然后使用固有矩阵的参数(fovy,aspect,zNear,zFar)设置SCNCameraprojectionTransform

通常在OpenGL中,相对于摄像机坐标的世界坐标是通过 ModelView 计算的,但是在 SceneKit 中,没有诸如 ModelView 之类的东西。

因此,我计算了外部矩阵的逆矩阵,以获得相机坐标相对于世界坐标(标记坐标)。

而且我想我已经通过包含旋转和平移矩阵的逆矩阵获得了正确的相机位置。

但是我不能从中得到相机的“旋转”。

你有什么想法?

2 回答

  • 6

    SceneKit 具有与 OpenGL 中相同的视图矩阵,只是在您开始使用着色器玩弄之前,它们只是被隐藏了一点。 IMO 有点太隐蔽。

    您似乎已经弄清楚了其中的大部分。投影矩阵来自相机projectionTransform,视图矩阵来自相机矩阵SCNMatrix4Invert(cameraNode.transform)的逆矩阵。就我而言,一切都在世界坐标中,使我的模型矩阵成为简单的单位矩阵。

    我最终用来获取经典 model-view-projection 矩阵的代码类似于...

    let projection = camera.projectionTransform()
    let view = SCNMatrix4Invert(cameraNode.transform)
    let model = SCNMatrix4Identity
    
    let viewProjection = SCNMatrix4Mult(view, projection)
    let modelViewProjection = SCNMatrix4Mult(model, viewProjection)
    

    由于某种原因,我发现SCNMatrix4Mult(...)接受参数的顺序与我期望的顺序不同(例如,与GLKMatrix4Multiply(...)相反)。

    我还不是 100%,因此欢迎 edits/tips。使用这种方法,我无法获得 SceneKit MVP 矩阵(传递给着色器)来与上面的代码计算出的矩阵相匹配...但是它足够接近我的需要。

  • 2

    @lock 的补充几项看起来不错:

    (1)在 cameraNode 是动画或父级的情况下,访问 SCNNode worldTransform 而不是 transform:

    let view = SCNMatrix4Invert(cameraNode.presentationNode.worldTransform)
    

    (2)代码未考虑视图的长宽比。 e.g. ,假设透视投影,您需要执行以下操作:

    perspMatrix.m11 /= viewportAR; //if using Yfov -> adjust Y`
    /* or, */
    perspMatrix.m22 *= viewportAR; //if using Xfov -> adjust X`
    

    viewportAR = viewport.width / viewport.height

    另一种方法是在场景中有一个具有渲染委托的节点,然后从该委托检索 SceneKit 的矩阵(它们作为选项传递):

    FOUNDATION_EXTERN NSString * const SCNModelTransform;
    FOUNDATION_EXTERN NSString * const SCNViewTransform;
    FOUNDATION_EXTERN NSString * const SCNProjectionTransform;
    FOUNDATION_EXTERN NSString * const SCNNormalTransform;
    FOUNDATION_EXTERN NSString * const SCNModelViewTransform;
    FOUNDATION_EXTERN NSString * const SCNModelViewProjectionTransform;
    

相关问题