问题
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.
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
}
}
回答1:
is there a better way to select placed 3D-models in ARKit
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.
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.
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]
}
Your model gets the model
option, but in your hit-testing you only use .userInteraction
.
来源:https://stackoverflow.com/questions/53490388/arkit-hittest-options-to-select-placed-3d-objects-not-working