本文介绍了ARKit hitTest(_:options:) 选择放置的 3d 对象不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试选择一个放置在检测到的平面上的对象,以便对其执行各种任务,例如通过手势旋转.

I am trying to select an object which has been placed on a detected plane in order to perform various task on it such as rotating through gestures.

为了搜索放置的对象并避免获得无关性质的 hitTestResults(例如选择平面或 ARWorldMap 本身),我尝试将 hitTest(_:options:) 与 SCNHitTestOption.categoryBitMask 一起使用.然而,似乎 hitTest 返回所有类型的结果,而不仅仅是具有所选 categoryBitMask = 5 的对象,即使根据我的理解 categoryBitMask 是仅搜索与指定位掩码匹配的对象的选项".我如何解决这个问题,有没有更好的方法来选择 ARKit 中放置的 3D 模型?下面是我必须旋转 3d 模型的功能.

In order to search for placed objects and avoid getting hitTestResults of irrelevant nature (eg. selecting the plane or the ARWorldMap itself) I am trying to use hitTest(_:options:) with SCNHitTestOption.categoryBitMask. However it seems as the hitTest returns results of all types, not just objects with the selected categoryBitMask = 5, even though from my understanding categoryBitMask is "An option to search only for objects matching a specified bitmask." How do I fix this problem, and is there a better way to select placed 3D-models in ARKit? Below is the function I have to rotate a 3d-model.

enum BodyType: Int {
    case model = 5
}

@objc func panned(recognizer :UIPanGestureRecognizer) {
    guard let recognizerView = recognizer.view as? ARSCNView else {return}

    let touch = recognizer.location(in: recognizerView)
    let translation = recognizer.translation(in: recognizerView)

    let hitTestResult = self.sceneView.hitTest(touch, options: [SCNHitTestOption.categoryBitMask: BodyType.model.rawValue])
    guard let modelNodeHit = hitTestResult.first?.node.parent else{return}
    if recognizer.state == .changed {
            self.newAngleY = Float(translation.x) * (Float) (Double.pi) / 180
            self.newAngleY += self.currentAngleY
            modelNodeHit.eulerAngles.y = self.newAngleY
    }else if recognizer.state == .ended {
        self.currentAngleY = self.newAngleY
    }
}

推荐答案

不,你是对的.搜索 SceneKit 内容时使用 SCNSceneRenderer.hitTest(_:, options:),搜索 ARKit 识别的真实对象时使用 ARSCNView.hitTest(_:types:).

No, you are right. Use SCNSceneRenderer.hitTest(_:, options:) when searching for SceneKit content and ARSCNView.hitTest(_:types:) when searching for real objects recognised by ARKit.

这里似乎错误的是 categoryBitMask 是位掩码.5 具有 101 的二进制表示.然后 SceneKit 将每一位与对象上的位进行比较,如果任何匹配,则将对象包含在结果中.
因此,当每个其他对象都具有 1 的默认类别时,它会包含在结果中,因为 101001 具有匹配位.

What seems wrong here is that categoryBitMask is, well, a bitmask. 5 has a binary representation of 101. SceneKit then compares every bit with the bits on your objects and if any of them match, it includes the object in the results.
So when every other object has the default category of 1, it is included in the result, because 101 and 001 have a matching bit.

您可以使用的是 OptionSet 协议.

What you can use is the OptionSet protocol.

struct BodyType: OptionSet {
  let rawValue: Int

  static let `default` = BodyType(rawValue: 1)
  static let userInteraction = BodyType(rawValue: 4)

  static let model: BodyType = [.default, .userInteraction]
}

您的模型获得 model 选项,但在您的命中测试中,您只使用 .userInteraction.

Your model gets the model option, but in your hit-testing you only use .userInteraction.

这篇关于ARKit hitTest(_:options:) 选择放置的 3d 对象不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-14 04:28