ARKIT:如何在半空中移动物体,如GiPHY世界应用程序



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

但是,如果物体在半空中,则无法对任何平面进行光线投射。我注意到GIPHY世界应用程序允许您在2种模式之间切换:

  1. 平面检测(只允许将物体放置在 表面(
  2. 自由模式(对象只能漂浮在相机前
  3. (

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

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

。 例如。
  • 如果您在对象前面,请在屏幕上向上/向下拖动 将在 Z 坐标中移动对象...近或远
  • 但是,如果您物理移动到一侧......并再次在屏幕上向上/向下拖动,则对象现在将平移到X坐标上。 <---如何 他们这样做吗?

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

在这里,您可以看到我根据下面的@Vollan答案尝试的内容。你可以看到重新定位不像 GiPHY APP 那样有效。 https://youtu.be/ZoWj6WRBY58

所以,首先,我将在您移动物理对象后讨论移动对象。

当你在现实中放置节点时,你可以选择从相机的角度制作它,或者你是否真的想把它放在世界位置。

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

现在,如果您选择世界位置并选择绕节点或启动位置(例如 90 度(走动。然后,您将在轴的原点上具有另一个角度,因为Z轴和X轴的位置将发生变化。导致 Z 中的向上/向下转换为 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)

什么的。

祝你好运。

最新更新