3

我正在尝试使用SceneKit.

我通过使用 ARuco(OpenCV 增强现实库)估计标记的姿势得到了一个内在的相机矩阵和一个外在的矩阵。

我用内在矩阵的参数(fovy、aspect、zNear、zFar)设置了SCNCamera's 。projectionTransform

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

所以我计算了外在矩阵的逆矩阵,得到相机相对于世界坐标(标记坐标)的坐标。

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

但是我无法从中获得相机的旋转

你有什么想法?

4

2 回答 2

8

SceneKit 具有与您在 OpenGL 中遇到的相同的视图矩阵,它们只是稍微隐藏了一点,直到您开始使用着色器。IMO 有点太隐蔽了。

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

我最终用来获取经典模型-视图-投影矩阵的代码类似于...

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%,所以欢迎编辑/提示。使用这种方法,我无法让 SceneKit MVP 矩阵(传递给着色器)与上面代码计算的矩阵相匹配……但它已经足够接近我需要的了。

于 2015-11-16T08:42:24.737 回答
2

@lock 的答案看起来不错,有几个补充:

(1) 访问 SCNNode worldTransform 而不是 transform 如果 cameraNode 是动画或父节点:

let view = SCNMatrix4Invert(cameraNode.presentationNode.worldTransform)

(2) 代码没有考虑视图的纵横比。例如,假设一个透视投影,你会想要做:

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;
于 2016-10-03T18:10:48.203 回答