【问题标题】:Get distance between the entity anchor and the camera获取实体锚点和相机之间的距离
【发布时间】:2021-03-01 15:57:17
【问题描述】:

我正在向我的ARView 添加一个包含一个实体的场景。我想知道如何才能获得实体的锚点和相机之间的距离。我知道如何获得相机的当前位置,但是我为arScene 获得的位置肯定是错误的,因为减去这两个位置不会产生正确的位置。下面是一些代码。

import RealityKit

class ViewController: UIViewController, ARSessionDelegate {
  let arScene = try! TestProj.loadScene()
  @IBOutlet var sceneView: ARView!

  override func viewDidLoad() {
    ...
    sceneView.scene.addAnchor(arScene)
    ...
  }

  func session(_ session: ARSession, didUpdate frame: ARFrame) {
    // Calculate distance here
    let cameraPos = frame.camera.transform.columns.3
    let entityPos = // Position of entity's anchor
    let distance = // Find distance here
  }
}

【问题讨论】:

  • 场景的位置是什么意思?您实际添加的是带有 HasAnchor (AnchorEntity) 的实体。如果您要向其中添加许多实体子实体,您想要所有这些子实体的边界框中心,还是只是 AnchorEntity 的位置?
  • 锚实体的位置,我会更新我的问题谢谢!

标签: swift augmented-reality arkit realitykit


【解决方案1】:

您需要对 RealityKit 场景中的所有几何图形执行 Convex Raycast 以获取两个端点之间的光线:

import UIKit
import RealityKit

class ViewController: UIViewController {

    @IBOutlet var arView: ARView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let entity = ModelEntity(mesh: .generateBox(size: 0.4))
        entity.name = "Cube"

        let anchor = AnchorEntity(world: [0,0,0])
        anchor.addChild(entity)
        arView.scene.anchors.append(anchor)
    
        // For every entity that could be hit,
        // we must generate a collision shape.
        entity.generateCollisionShapes(recursive: true)
    }

    @IBAction func onTap(_ sender: UITapGestureRecognizer) {

        let query: CollisionCastQueryType = .nearest
        let mask: CollisionGroup = .default

        let camera = arView.session.currentFrame?.camera
        let x = (camera?.transform.columns.3.x)!
        let y = (camera?.transform.columns.3.y)!
        let z = (camera?.transform.columns.3.z)!

        let transform: SIMD3<Float> = [x, y, z]
           
        let raycasts: [CollisionCastHit] = arView.scene.raycast(
                                                           from: transform, 
                                                             to: [0, 0, 0], 
                                                          query: query, 
                                                           mask: mask, 
                                                     relativeTo: nil)
    
        guard let raycast: CollisionCastHit = raycasts.first
        else { return }
    
        print(raycast.distance)     // Distance from the ray origin to the hit
        print(raycast.entity.name)  // The entity that was hit
        print(raycast.position)     // The position of the hit
    }    
}

此外,正如@maxxfrazer 所建议的,您可以更轻松地访问相机转换:

let translate = arView.cameraTransform.translation

let x = translate.x
let y = translate.y
let z = translate.z

let transform: SIMD3<Float> = [x, y, z]

【讨论】:

  • 不幸的是,这没有返回任何光线投射。为了更清楚起见,我在 Reality Composer 中创建了一个实体,并将 .rcproject 加载到 Xcode 中。我可以将场景添加到我的 ARView 中,但是在我放置代码的 session(didUpdate frame:) 方法中,光线投射始终为零。我认为你在正确的轨道上。我希望我们能解决这个问题:)
  • 你生成碰撞形状了吗?
  • 是的,我在将锚点添加到 arView 之前生成了碰撞形状
  • 我明白了!我只需要增加to: 参数以包含实体,这样它也将包含放置在水平面上的实体。我会将您的答案标记为正确。
  • 你可以用let transform = self.cameraTransform.translation得到相机变换,不需要获取可选的currentFrame并强制解包
猜你喜欢
  • 1970-01-01
  • 2019-11-26
  • 1970-01-01
  • 1970-01-01
  • 2018-11-28
  • 2020-01-12
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多