I would like to allow users to rotate the model with a pan gesture. The rotation should follow the finger movement. The possible movement could look like https://www.youtube.com/watch?v=50EjlzVsQM8 but with rotation along the z-axis as well.
I implemented a pan gesture handler:
@objc private func handlePan(recognizer: UIPanGestureRecognizer) {
let currentTouchPoint = recognizer.location(in: self.arView)
guard let ray = self.arView.ray(through: currentTouchPoint) else {
return
}
anchorEntity.transform.rotation = .init(angle: .pi, axis: ray.direction)
}
but now, there are several problems with this code:
I believe I need to somehow adapt the angle / direction, but not sure where to start, I am not really familiar with the 3D transformations. Any help would be appreciated.
Since the 2D pan gesture has just x/y coordinates, with pan, you're able to control the rotation of your model around definite pair of axes, such as x/y or y/z. Here's the code:
import RealityKit
import ARKit
class ViewController : UIViewController {
@IBOutlet var arView: ARView!
let boxPrim = ModelEntity(mesh: .generateBox(size: 0.75))
var previousPoint = CGPoint()
let anchor = AnchorEntity()
var deg: Float = .zero
@objc func panning(recognizer: UIPanGestureRecognizer) {
deg += 5.0
var currentPoint = recognizer.location(in: arView)
let rad = deg * .pi / 180
if currentPoint.x > previousPoint.x {
boxPrim.transform = Transform(yaw: rad * 1.5) // Y
currentPoint.y = 0
}
if currentPoint.x < previousPoint.x {
boxPrim.transform = Transform(yaw: -rad * 1.5) // Y
currentPoint.y = 0
}
if currentPoint.y > previousPoint.y {
boxPrim.transform = Transform(pitch: rad) // X
}
if currentPoint.y < previousPoint.y {
boxPrim.transform = Transform(pitch: -rad) // X
}
previousPoint = currentPoint
}
func gestureRecognizer() {
let recognizer = UIPanGestureRecognizer(target: self,
action: #selector(panning))
arView.addGestureRecognizer(recognizer)
}
override func viewDidLoad() {
super.viewDidLoad()
anchor.addChild(boxPrim)
arView.scene.addAnchor(anchor)
self.gestureRecognizer()
}
}