微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ARKit - 3D 空间中某个点的 2D 投影结果在某些设备位置/方向突然变化

如何解决ARKit - 3D 空间中某个点的 2D 投影结果在某些设备位置/方向突然变化

我正在开发一个使用 SceneKit 作为渲染引擎的 ARKit 应用程序。它做一些典型的 ARKit 事情,比如允许用户在场景中放置 3D 虚拟内容,检测和绘制水平和垂直平面等。

该应用程序还包含一项功能,可以创建与 Apple 的 Measure 应用程序中的测量对象类似的测量对象。用户点击“添加端点”按钮添加测量的第一个点,移动设备以定位第二个点,然后再次点击“添加端点”按钮完成测量。 Measurement Working

问题在于,在某些设备方向和与测量对象的距离下,测量对象的行为不规律。第一个端点将突然改变位置,并且线和第一个端点将围绕第二个端点“翻转”。 Measurement "Flipping"

测量功能创建 SpriteKit 资产并将它们添加overlaySKScenesceneView。这些测量记录了它们在 3D 空间中的起点和终点位置,并将这些点投影到 2D 以重新定位它们的 SpriteKit 组件。

这是我当前更新测量项目位置的方式:

func renderer(_ renderer: SCNSceneRenderer,updateAtTime time: TimeInterval) {
    measurementNodes.forEach { $0.updateComponentPositions(renderer: sceneView) }
    //...
}

使用 updateComponentPositions 方法 SCNSceneRendererDelegate 每帧调用方法 renderer(_,updateAtTime)

func updateComponentPositions(renderer: SCNSceneRenderer) {
    // update start circle
    let projectedStartPointScreenPosition = renderer.projectPoint(startPointPosition)
    let startPointSKPosition = CGPoint(x: CGFloat(projectedStartPointScreenPosition.x),y: scene.size.height - CGFloat(projectedStartPointScreenPosition.y) - startPointNode.frame.height/2)
    startPointNode.position = startPointSKPosition

    // update end circle
    let projectedEndPointScreenPosition = renderer.projectPoint(endPointPosition)
    let endPointSKPosition = CGPoint(x: CGFloat(projectedEndPointScreenPosition.x),y: scene.size.height - CGFloat(projectedEndPointScreenPosition.y) - endPointNode.frame.height/2)
    endPointNode.position = endPointSKPosition

    // update label
    labelBackgroundNode.position = CGPoint(x: (startPointSKPosition.x + endPointSKPosition.x) / 2,y: (startPointSKPosition.y + endPointSKPosition.y) / 2)

    // reset line path
    lineNode.path = getLinePath(from: startPointSKPosition,to: endPointSKPosition)
}

这是 updateComponentPositionsMeasurementNode 方法,它将渲染器作为参数,将 3D 点投影到 2D 位置,然后更新其几何位置。

在尝试调试此问题时,我专注于 renderer.projectPoint(startPointPosition) 的结果。 startPointPosition一个静态的 SCNVector3,它在创建第一个端点时保存 3D 位置。但是,此 projectPoint 方法的结果是在此特定设备方向上变得不稳定。 这是当我用设备击中那个“翻转”点时 renderer.projectPoint(startPointPosition) 的日志示例:

SCNVector3(x: -6692.817,y: -13238.885,z: 0.49546456)
SCNVector3(x: -8706.296,y: -17154.777,z: 0.49417993)
SCNVector3(x: -12774.009,y: -25042.207,z: 0.491588)
SCNVector3(x: -24064.623,y: -46880.246,z: 0.48439798)
SCNVector3(x: -164018.86,y: -317208.25,z: 0.39538962) // magnitude becomes very large for x and y
SCNVector3(x: 17587.36,y: 33517.477,z: 0.510834) // x and y "flip"
SCNVector3(x: 9163.234,y: 17199.012,z: 0.50547314)
SCNVector3(x: 7649.4766,y: 14249.298,z: 0.5045147)
SCNVector3(x: 6688.1143,y: 12365.713,z: 0.5039065)

我尝试将 updateComponentPositions 方法替换为以 ARCamera 作为参数的方法,以查看使用它的 projectPoint(_ point: simd_float3,orientation: UIInterfaceOrientation,viewportSize: CGSize) 方法是否会更好。我使用相同的 renderer(_,updateAtTime) 方法调用它,但获得了相同的结果。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。