J'ai un simple SCNNode dans ARKit et j'essaie de le faire glisser partout où j'ai déplacé mon doigt sur le téléphone. Voici mon code.
@objc func pan(recognizer :UIGestureRecognizer) {
guard let currentFrame = self.sceneView.session.currentFrame else {
return
}
var translation = matrix_identity_float4x4
translation.columns.3.z = -1.5
let sceneView = recognizer.view as! ARSCNView
let touchLocation = recognizer.location(in: sceneView)
let hitTestResult = sceneView.hitTest(touchLocation, options: [:])
if !hitTestResult.isEmpty {
print("hit result")
guard let hitResult = hitTestResult.first else {
return
}
let node = hitResult.node
node.simdTransform = matrix_multiply(currentFrame.camera.transform, translation)
}
}
Le problème est que la traînée est très lente et non lisse.
Je gère la traduction avec PanGesture comme ceci. La division par 700 consiste à lisser et à ajuster la vitesse de déplacement. J'ai atteint cette valeur par essai ou erreur. Vous pouvez expérimenter.
@objc func onTranslate(_ sender: UIPanGestureRecognizer) {
let position = sender.location(in: scnView)
let state = sender.state
if (state == .failed || state == .cancelled) {
return
}
if (state == .began) {
// Check it's on a virtual object
if let objectNode = virtualObject(at: position) {
// virtualObject(at searches for root node if it's a subnode
targetNode = objectNode
latestTranslatePos = position
}
}
else if let _ = targetNode {
// Translate virtual object
let deltaX = Float(position.x - latestTranslatePos!.x)/700
let deltaY = Float(position.y - latestTranslatePos!.y)/700
targetNode!.localTranslate(by: SCNVector3Make(deltaX, 0.0, deltaY))
latestTranslatePos = position
if (state == .ended) {
targetNode = nil
}
}
}
Avait le même problème. Utiliser un SCNTransaction
a fait l'affaire pour moi.
@objc private func handlePan(_ gesture: UIPanGestureRecognizer) {
[...]
SCNTransaction.begin()
SCNTransaction.animationDuration = 0
imagePlane.position.x = hitTestResult.localCoordinates.x
imagePlane.position.y = hitTestResult.localCoordinates.y
SCNTransaction.commit()
}
J'avais un problème similaire. Bien que vous deviez utiliser les conseils de John dans les commentaires et utiliser les états de geste panoramique corrects (début, changement, fin), je pense que le problème pourrait être que vous récupériez le hitResult.node alors que vous devriez récupérer le parent du nœud, ou même le parent du parent, etc ... J'ai eu ce problème et j'ai fini par le résoudre en remontant les niveaux du parent jusqu'à ce que l'objet entier soit sélectionné au lieu d'une partie de celui-ci.