下面的代码旨在模拟 SceneKit 中的默认相机控件,特别是缩放和旋转功能。
但是,代码并不像默认控件那样流畅和通用。
例如,如果您加载这两个模型,则默认缩放对两个模型都有效。然而,下面的代码只适用于模型 1,但对于模型 2 来说缩放速度太快了。
任何帮助,将不胜感激。
模型一:https ://poly.google.com/view/6mRHqTCZHxw
模型 2:https ://poly.google.com/view/cKryD9VnDEZ
// Create camera
let camera = SCNCamera()
camera.automaticallyAdjustsZRange = true
camera.xFov = 30
camera.yFov = 0
// Compute distance to place camera
let theta = GLKMathDegreesToRadians(Float(camera.xFov/2))
let adjacentLength = oppositeLength / Float(tan(theta))
// Add camera to <cameraNode>
cameraNode.camera = camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: adjacentLength)
// Add <cameraNode> to <orbitNode>
orbitNode.addChildNode(cameraNode)
// Add <orbitNode>
scene.rootNode.addChildNode(orbitNode)
// Handle pinches
let pinchRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(didSceneViewPinch))
pinchRecognizer.delegate = self
sceneView.addGestureRecognizer(pinchRecognizer)
// Handle pans
let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didSceneViewPanOneFinger))
panRecognizer.minimumNumberOfTouches = 1
panRecognizer.maximumNumberOfTouches = 1
panRecognizer.delegate = self
sceneView.addGestureRecognizer(panRecognizer)
func rotate(recognizer: UIPanGestureRecognizer) {
// Set throttle value to slow down rotation
let throttleFactor = Float(40)
// Compute rotation
let translation = recognizer.translation(in: recognizer.view!)
let xRadians = GLKMathDegreesToRadians(Float(translation.x)) / throttleFactor
let yRadians = GLKMathDegreesToRadians(Float(translation.y)) / throttleFactor
// Orbit camera via <orbitNode>
orbitNode.eulerAngles.x -= yRadians
orbitNode.eulerAngles.y -= xRadians
}
func zoom(recognizer: UIPinchGestureRecognizer) {
// Set zoom properties
let minVelocity = CGFloat(0.10)
let zoomDelta = 0.5
// Only zoom when gesture changing and when velocity exceeds <minVelocity>
if recognizer.state == .changed {
// Ignore gesture on tiny movements
if abs(recognizer.velocity) <= minVelocity {
return
}
// If here, zoom in or out based on velocity
let deltaFov = recognizer.velocity > 0 ? -zoomDelta : zoomDelta
var newFov = cameraNode.camera!.xFov + deltaFov
// Make sure FOV remains within min and max values
if newFov <= minXFov {
newFov = minXFov
} else if newFov >= maxXFov {
newFov = maxXFov
}
// Update FOV?
if cameraNode.camera?.xFov != newFov {
cameraNode.camera?.xFov = newFov
}
}
}