我试图用SceneKit
来实现增强现实。
我使用ARuco(OpenCV增强现实库)通过估计标记的姿势获得了内在的相机矩阵和外在矩阵。
我使用内在矩阵(fovy,aspect,zNear,zFar)的参数设置SCNCamera
' projectionTransform
。
通常在OpenGL
中,相对于相机坐标的世界坐标是使用ModelView计算的,但在SceneKit中,没有像modelView那样的东西。
所以我计算了外在矩阵的逆矩阵,得到相对于世界坐标的相机坐标(标记坐标)。
我认为我通过包含旋转和平移矩阵的逆矩阵得到了正确的相机位置。
但是我无法从相机那里获得轮换。
你有什么想法吗?
答案 0 :(得分:6)
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矩阵(传递给着色器)以匹配上面代码计算的...但它足够接近我所需要的。
答案 1 :(得分:2)
@lock的回答看起来很不错,只有几个补充:
(1)访问SCNNode worldTransform而不是变换,以防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;