Matrix 将屏幕点取消投影到ARKit中的水平面
我正在尝试使用ARKit将屏幕上的某个点投影到世界空间中ARPlaneAnchor上的坐标。基本上,我想根据相机的指向在地平面上画一个标记。ARKit提供了一些方法来实现这一点,但是它们附加到ARCamera类,不幸的是,在我的场景中,我只能访问相机的投影、视图和变换矩阵,而没有参考ARFrame或ARCamera对象本身。我写了一些与glunproject()类似的东西(据我所知)Matrix 将屏幕点取消投影到ARKit中的水平面,matrix,opengl-es,augmented-reality,arkit,metal,Matrix,Opengl Es,Augmented Reality,Arkit,Metal,我正在尝试使用ARKit将屏幕上的某个点投影到世界空间中ARPlaneAnchor上的坐标。基本上,我想根据相机的指向在地平面上画一个标记。ARKit提供了一些方法来实现这一点,但是它们附加到ARCamera类,不幸的是,在我的场景中,我只能访问相机的投影、视图和变换矩阵,而没有参考ARFrame或ARCamera对象本身。我写了一些与glunproject()类似的东西(据我所知) 屏幕点是一些窗口坐标 通过在前面的过程中从深度缓冲区读回值来计算深度 screenSize是视口的大小 投影矩阵
var modelMatrix = matrix_identity_float4x4
modelMatrix = modelMatrix.translatedBy(x: pos.x, y: pos.y, z: pos.z)
然后这些值被发送到着色器,就像这样
encoder.setVertexBytes(&projectionMatrix, length: MemoryLayout<simd_float4x4>.stride, index: 1)
encoder.setVertexBytes(&viewMatrix, length: MemoryLayout<simd_float4x4>.stride, index: 2)
encoder.setVertexBytes(&modelMatrix, length: MemoryLayout<simd_float4x4>.stride, index: 3)
我认为我的z值是正确的(深度缓冲区中的深度值),所以实际上我只需要找到我的x和y。我也不能100%确定如何处理unproject函数返回的值。我假设这只是世界坐标,但可能需要以某种方式进行缩放
我希望得到一些帮助来获得正确的坐标,或者如果上面有任何错误,请指出它们 对于将来遇到此问题的任何人来说,解决方案(如@rabbi76所建议的)是翻转投影矩阵和视图矩阵以及逆矩阵和输入点的乘法顺序。我还需要翻转我想要检查的屏幕点的y坐标 以下是完整的函数:
func screenToWorld(screenPoint: CGPoint, depth: Float, screenSize: CGSize, projectionMatrix: simd_float4x4, viewMatrix:simd_float4x4) -> float3{
let viewProj = projectionMatrix * viewMatrix
let inverse = simd_inverse(viewProj)
let x = (2.0 * screenPoint.x ) / screenSize.width - 1.0
let y = 1.0 - (2.0 * screenPoint.y) / screenSize.height
let inPoint = float4(Float(x), Float(y), depth * 2.0 - 1.0, 1.0)
var position = inverse * inPoint
position.w = 1.0 / position.w
position.x *= position.w
position.y *= position.w
position.z *= position.w
return float3(position.x, position.y, position.z)
}
它必须是
viewProj=projectionMatrix*viewMatrix
和position=inverse*inPoint
Aha!我想这就成功了。离得这么近很痛苦,但…对我来说不起作用,如果我找到原因,我会回来的
VertexOut vertexOut;
float4x4 modelViewMatrix = viewMatrix * modelMatrix;
vertexOut.position = projectionMatrix * modelViewMatrix * vertexIn.position;
return vertexOut;
func screenToWorld(screenPoint: CGPoint, depth: Float, screenSize: CGSize, projectionMatrix: simd_float4x4, viewMatrix:simd_float4x4) -> float3{
let viewProj = projectionMatrix * viewMatrix
let inverse = simd_inverse(viewProj)
let x = (2.0 * screenPoint.x ) / screenSize.width - 1.0
let y = 1.0 - (2.0 * screenPoint.y) / screenSize.height
let inPoint = float4(Float(x), Float(y), depth * 2.0 - 1.0, 1.0)
var position = inverse * inPoint
position.w = 1.0 / position.w
position.x *= position.w
position.y *= position.w
position.z *= position.w
return float3(position.x, position.y, position.z)
}