ARKit在真实世界中随机放置模型

3

我正在尝试使用ARKit,想要在用户周围放置一些模型。当应用程序启动时,我希望它会自动将一些模型放置在用户周围,以便用户需要找到它们。

当用户移动了10米左右时,我希望再次添加一些随机模型。我认为可以这样做:

 let cameraTransform = self.sceneView.session.currentFrame?.camera.transform
        let cameraCoordinates = MDLTransform(matrix: cameraTransform!)

        let camX = CGFloat(cameraCoordinates.translation.x)
        let camY = CGFloat(cameraCoordinates.translation.y)
        let cameraPosition = CGPoint(x: camX, y: camY)
        let anchors = self.sceneView.hitTest(cameraPosition, types: [.featurePoint, .estimatedHorizontalPlane])

        if let hit = anchors.first {
            let hitTransform = SCNMatrix4(hit.worldTransform)
            let hitPosition = SCNVector3Make(hitTransform.m41, hitTransform.m42, hitTransform.m43)
            self.sceneView.session.add(anchor: ARAnchor(transform: hit.worldTransform))
            return Coordinate(hitPosition.x, hitPosition.y, hitPosition.z)
        }

        return Coordinate(0, 0, 0)
    }

问题在于有时它找不到任何锚点,那么我就不知道该怎么办了。而且当它找到一些锚点时,它是随机放置在我的后面而不是我面前,但我不知道为什么,因为我从来没有转动相机,所以它找不到任何锚点。

有没有更好的方法将随机模型放置在现实世界中?

1个回答

3
为了实现这个功能,您需要使用 session(_:didUpdate:) 代理方法:
func session(_ session: ARSession, didUpdate frame: ARFrame) {
    guard let cameraTransform = session.currentFrame?.camera.transform else { return }
    let cameraPosition = SCNVector3(
        /* At this moment you could be sure, that camera properly oriented in world coordinates */
        cameraTransform.columns.3.x,
        cameraTransform.columns.3.y,
        cameraTransform.columns.3.z
    )
    /* Now you have cameraPosition with x,y,z coordinates and you can calculate distance between those to points */
    let randomPoint = CGPoint(
        /* Here you can make random point for hitTest. */
        x: CGFloat(arc4random()) / CGFloat(UInt32.max),
        y: CGFloat(arc4random()) / CGFloat(UInt32.max)
    )
    guard let testResult = frame.hitTest(randomPoint, types: .featurePoint).first else { return }
    let objectPoint = SCNVector3(
        /* Converting 4x4 matrix into x,y,z point */
        testResult.worldTransform.columns.3.x,
        testResult.worldTransform.columns.3.y,
        testResult.worldTransform.columns.3.z
    )
    /* do whatever you need with this object point */
}

它允许您在相机位置更新时放置对象:

如果您提供自己的显示来呈现AR体验,则实现此方法。提供的ARFrame对象包含从设备摄像头捕获的最新图像,您可以将其呈现为场景背景,并提供有关摄像机参数和锚点变换的信息,您可以使用这些信息在摄像机图像上方呈现虚拟内容。

在这里真正重要的是,您随机选择hitTest方法的点,而且这个点总是在相机前面。

不要忘记在hitTest方法中使用从0到1.0的坐标系来表示CGPoint:

归一化图像坐标空间中的一个点。(点(0,0)表示图像的左上角,点(1,1)表示右下角。)

如果您想每10米放置一个对象,可以保存相机位置(在session(_:didUpdate:)方法中),并检查x+z坐标是否已更改足够远以放置新对象。

注意:

我假设您正在使用世界跟踪会话:

let configuration = ARWorldTrackingSessionConfiguration()
session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

谢谢您的解释。我有一些问题。在您的示例代码中,hittesting的点arcRandom应该是0到1之间的某个数字,这样点就始终在相机前面?然后是x+z坐标,以查看用户是否移动了足够的距离。我需要与哪些坐标进行比较?是session.currentFrame?.camera.transform x和z吗? - user1007522
1
@user1007522 是的,函数参数中的 frame: ARFrame 总是在相机前面。要比较距离,请使用 cameraPosition(请参见更新的答案 ^)。 - Vasilii Muravev
嘿@Vasilii,非常感谢你详细的答案!我和我的团队遇到了一个问题,困扰了我们好几天:/我发了一个有趣的问题: https://stackoverflow.com/questions/63662318/arkit-apply-filter-cifilter-to-a-specific-part-vertex-of-an-arfaceanchor ,希望得到你的建议! - Roi Mulia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接