gpt4 book ai didi

matrix - 在 ARKit 中将屏幕点取消投影到水平面

转载 作者:行者123 更新时间:2023-12-04 20:47:14 25 4
gpt4 key购买 nike

我正在尝试使用 ARKit 将屏幕上的某个点取消投影到世界空间中 ARPlaneAnchor 上的坐标。本质上,我想根据相机指向的位置在地平面上绘制一个标记。 ARKit 提供了一些方法来做到这一点,但是它们附加到 ARCamera 类,不幸的是,在我的场景中,我只能访问相机的投影、 View 和变换矩阵,并且没有引用 ARFrame 或 ARCamera 对象本身。我写了一些与 gluUnproject() 类似的东西(据我所知)。

func screenToWorld(screenPoint: CGPoint, depth: Float, screenSize: CGSize, projectionMatrix: simd_float4x4, viewMatrix:simd_float4x4) -> float3{

let viewProj = viewMatrix * projectionMatrix
let inverse = simd_inverse(viewProj)

let x = (2.0 * screenPoint.x ) / screenSize.width - 1.0
let y = (2.0 * screenPoint.y) / screenSize.height - 1.0

let inPoint = float4(Float(x), Float(y), depth * 2.0 - 1.0, 1.0)

var position = inPoint * inverse
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)
}


let pos = screenToWorld(screenPoint: CGPoint(360, 640), depth: depthBufferValue, screenSize: CGSize(720, 1280), projectionMatrix: projectionMatrix, viewMatrix: viewMatrix)
  • screenPoint 是某个窗口坐标
  • 深度是通过在较早的 channel 中读回深度缓冲区中的值来计算的
  • screenSize 是视口(viewport)的大小
  • projectionMatrix 来自 projectionMatrix(for:.portrait, viewportSize: CGSize(720,1280),zNear: 0.001, zFar: 1000)
  • viewMatrix 来自 viewMatrix(for:.portrait)

  • 我唯一不确定的是 viewMatrix 属性。我唯一能想到的可能是附加到相机的变换矩阵。但是,我已经尝试过了,它似乎也没有给我正确的位置。在 gluUnproject 他们将此值称为模型 View 矩阵,在 glm 中它只是称为模型,所以我对这应该是什么感到有点困惑。

    使用从我的 unProject 函数中获得的值,我可以像这样转换一个单位矩阵
    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)

    在我的顶点着色器里面我做
    VertexOut vertexOut;
    float4x4 modelViewMatrix = viewMatrix * modelMatrix;
    vertexOut.position = projectionMatrix * modelViewMatrix * vertexIn.position;
    return vertexOut;

    我认为我的 z 值是正确的(深度缓冲区中的深度值),所以实际上我只需要找到我的 x 和 y。我也不是 100% 确定如何处理我的 unproject 函数返回的值。我认为这只是世界坐标,但也许需要以某种方式缩放?

    我很想得到一些帮助来获得正确的坐标,或者如果上面有任何错误,请指出!

    最佳答案

    对于将来遇到此问题的任何人,解决方案(如@rabbid76 所建议的)正在翻转我的投影和 View 矩阵以及我的逆矩阵和 inPoint 的乘法顺序。我还需要翻转要检查的 screenPoint 的 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)
    }

    关于matrix - 在 ARKit 中将屏幕点取消投影到水平面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52461052/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com