首页 文章

ARKIT:如何像 GiPHY World app 一样在半空中移动物体

提问于
浏览
0

我已经实现了使用 UIPanGesture 移动位于表面顶部的对象的方法,并利用对平面进行光线投射的技术..在拖动时定位对象的新坐标。

但是如果物体处于半空中,你就不能在任何飞机上进行射线照射。我注意到 GIPHY World 应用程序,允许您在两种模式之间切换:

  • 平面检测(允许物体仅放置在表面上)

  • 自由模式(物体只能漂浮在相机前面)

当对象浮动时,用户可以在任何方向上拖动屏幕,即使您实际移动,对象也会正确跟随。我注意到你不必触摸物体来移动它,只要你在屏幕上拖动即可。

我想知道你们是否可以提出一些代码来将 2D 屏幕拖动转换为 3d 对象的移动方式。防爆。

  • 如果您在对象前面,拖动屏幕 UP/DOWN 将移动 Z 坐标中的对象...近或远。

  • 但是如果你身体移动到一边......再次拖动屏幕 UP/DOWN,对象现在可以翻转 X 坐标。 <---他们怎么做的?

这是一个如何工作的视频。 https://youtu.be/16iMMuwjfIc

在这里你可以看到我在@Vollan 的答案中所尝试的内容。你可以看到重新定位如何像 GiPHY APP 一样工作。 https://youtu.be/ZoWj6WRBY58

1 回答

  • 0

    所以,首先,我会在你移动身体后移动物体。

    当您将节点放置在现实中时,您可以选择从摄影机角度制作节点,或者如果您确实想要将节点置于世界位置。

    1:世界位置将 Z,X,Y 轴的原点放置在启动 AR 会话时摄像机所在的位置。 2:摄像机位置意味着原点将跟随您并被绑定到摄像机。这将使节点始终为 3D。

    现在,如果您选择世界位置,并选择绕节点或启动位置走动,例如 90 度。然后你将在轴的原点上有另一个角度,因为 Z 和 X 轴将改变位置。在 Z 中导致 UP/DOWN 转换为 X.

    其次我使用这段代码:

    @objc func adjustWindow(_ gesture: UIPinchGestureRecognizer) {
        var startPosition: CGPoint = CGPoint(x: 0, y: 0)
    
        // Fetch location for touch in sceneView
        let location: CGPoint = gesture.location(in: sceneView)
    
        // Fetch targets at the current location
        let hits = self.sceneView.hitTest(location, options: nil)
    
        // Check if it's a node and it's a window node that has been touched
        guard let node = hits.first?.node, node.name == "name" else {return}
    
        // Make sure user is using 1 finger to move the view
        if gesture.numberOfTouches == 1 {
            switch gesture.state {
            case .failed, .cancelled, .ended:
                // Reset position after finished
                startPosition = CGPoint(x: 0, y: 0)
                break
            case .began:
                // Save start position, so that we can check how far the user have moved
                startPosition = location
            case .changed:
                // Fetch new x and y position
                let deltaX = Float(location.x - startPosition.x)/20
                let deltaY = Float(location.y - startPosition.y)/20
    
                // Transform and apply the new location
                let box = node.transform
                let translation = SCNMatrix4MakeTranslation(deltaX, deltaY, 1)
                let newTrans = SCNMatrix4Mult(box, translation)
                node.transform = newTrans
    
                node.localTranslate(by: SCNVector3Make(deltaX, deltaY, 1))
                // Set new location
                startPosition = location
            default:
                break
            }
            // Make sure user is using 2 fingers for scaling the view
        }
     }
    

    这是我写的这个场景的第一个版本,它的移动方式可能只适用于我的应用程序,因为我在.DAE 文件中的对象有点不对。但是你可能会想到获取触摸位置并跟踪它的变化。

    实现ARSessionDelegate

    var matrix: matrix_float4x4!
    
        func session(_ session: ARSession, didUpdate frame: ARFrame) {
            // Fetch and store current camera position
            matrix = frame.camera.transform
        }
    

    当您移动相机时,它会随时更新您当前的相机位置。我还没弄明白如何应用这个。也许通过使用:

    let translation = SCNMatrix4MakeTranslation(deltaX*matrix.m41, deltaY*matrix.m42, 1*matrix.m43)

    或者其他的东西。

    祝好运。

相关问题