具有多个 UIPanGestureRecognizers 的 SceneKit 立方体旋转
SceneKit cube rotation with multiple UIPanGestureRecognizers
感谢您查看此内容。我确定这是非常基本的东西。我是初学者。
我正在尝试使用平移手势在 SceneKit 视图中旋转立方体。到目前为止,我已经成功地将此示例应用程序加载到我的 iPad 上,并在 y 轴上平移我的手指以在其 x 轴上旋转立方体,或沿屏幕 x 轴平移以沿其 y 旋转立方体-轴。
目前,我注意到最后添加到 sceneView 的手势识别器是有效的。我的问题 是如何让立方体响应 x 平移手势然后响应 y 平移手势,反之亦然。
这是我到目前为止编写的代码:
import UIKit
import SceneKit
class ViewController: UIViewController {
//geometry
var geometryNode: SCNNode = SCNNode()
//gestures
var currentYAngle: Float = 0.0
var currentXAngle: Float = 0.0
override func viewDidLoad() {
super.viewDidLoad()
sceneSetup()
}
func sceneSetup () {
//setup scene
let scene = SCNScene()
let sceneView = SCNView(frame: self.view.frame)
self.view.addSubview(sceneView)
//add camera
let camera = SCNCamera()
let cameraNode = SCNNode()
cameraNode.camera = camera
cameraNode.position = SCNVector3(x: 0.0, y: 0.0, z: 5.0)
//add light
let light = SCNLight()
light.type = SCNLightTypeOmni
let lightNode = SCNNode()
lightNode.light = light
lightNode.position = SCNVector3(x: 1.5, y: 1.5, z: 1.5)
//add cube
let cubeGeometry = SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0.0)
let boxNode = SCNNode(geometry: cubeGeometry)
scene.rootNode.addChildNode(lightNode)
scene.rootNode.addChildNode(cameraNode)
scene.rootNode.addChildNode(boxNode)
geometryNode = boxNode
//add recognizers
let panXRecognizer = UIPanGestureRecognizer(target: self, action: "rotateXGesture:")
let panYRecognizer = UIPanGestureRecognizer(target: self, action: "rotateYGesture:")
sceneView.addGestureRecognizer(panXRecognizer)
sceneView.addGestureRecognizer(panYRecognizer)
sceneView.scene = scene
}
func rotateXGesture (sender: UIPanGestureRecognizer) {
let translation = sender.translationInView(sender.view)
var newXAngle = (Float)(translation.y)*(Float)(M_PI)/180.0
newXAngle += currentXAngle
geometryNode.transform = SCNMatrix4MakeRotation(newXAngle, 1, 0, 0)
if(sender.state == UIGestureRecognizerState.Ended) {
currentXAngle = newXAngle
}
}
func rotateYGesture (sender: UIPanGestureRecognizer) {
let translation = sender.translationInView(sender.view)
var newYAngle = (Float)(translation.x)*(Float)(M_PI)/180.0
newYAngle += currentYAngle
geometryNode.transform = SCNMatrix4MakeRotation(newYAngle, 0, 1, 0)
if(sender.state == UIGestureRecognizerState.Ended) {
currentYAngle = newYAngle
}
}
}
您设置两个手势识别器的方式是相同的,它们都会针对相同的事件触发(这就是为什么要添加的最后一个占主导地位)。平移内没有控件专门将其限制为垂直或水平平移。相反,请考虑分析平移的方向,然后根据哪个方向更大来决定是将手势旋转到一个方向还是另一个方向。
将您当前的两个手势合二为一。这是我正在使用的代码的相关部分:
func panGesture(sender: UIPanGestureRecognizer) {
let translation = sender.translationInView(sender.view!)
var newAngleX = (Float)(translation.y)*(Float)(M_PI)/180.0
newAngleX += currentAngleX
var newAngleY = (Float)(translation.x)*(Float)(M_PI)/180.0
newAngleY += currentAngleY
baseNode.eulerAngles.x = newAngleX
baseNode.eulerAngles.y = newAngleY
if(sender.state == UIGestureRecognizerState.Ended) {
currentAngleX = newAngleX
currentAngleY = newAngleY
}
}
这里还有一个缩放手势:
func pinchGesture(sender: UIPinchGestureRecognizer) {
let zoom = sender.scale
var z = cameraNode.position.z * Float(1.0 / zoom)
z = fmaxf(zoomLimits.min, z)
z = fminf(zoomLimits.max, z)
cameraNode.position.z = z
}
编辑:我找到了一种更好的旋转模型的方法。在顶部的 panGesture
代码中,x 轴在您围绕 y 轴旋转时旋转。这意味着如果您围绕 y 旋转 180,则围绕 x 的旋转与您的手指运动相反。该方法还将运动限制为两个自由度。下面链接的方法,即使它不直接影响 z 轴,但似乎以某种方式允许三个自由度。它还使所有垂直滑动围绕 x 沿逻辑方向旋转。
感谢您查看此内容。我确定这是非常基本的东西。我是初学者。
我正在尝试使用平移手势在 SceneKit 视图中旋转立方体。到目前为止,我已经成功地将此示例应用程序加载到我的 iPad 上,并在 y 轴上平移我的手指以在其 x 轴上旋转立方体,或沿屏幕 x 轴平移以沿其 y 旋转立方体-轴。
目前,我注意到最后添加到 sceneView 的手势识别器是有效的。我的问题 是如何让立方体响应 x 平移手势然后响应 y 平移手势,反之亦然。
这是我到目前为止编写的代码:
import UIKit
import SceneKit
class ViewController: UIViewController {
//geometry
var geometryNode: SCNNode = SCNNode()
//gestures
var currentYAngle: Float = 0.0
var currentXAngle: Float = 0.0
override func viewDidLoad() {
super.viewDidLoad()
sceneSetup()
}
func sceneSetup () {
//setup scene
let scene = SCNScene()
let sceneView = SCNView(frame: self.view.frame)
self.view.addSubview(sceneView)
//add camera
let camera = SCNCamera()
let cameraNode = SCNNode()
cameraNode.camera = camera
cameraNode.position = SCNVector3(x: 0.0, y: 0.0, z: 5.0)
//add light
let light = SCNLight()
light.type = SCNLightTypeOmni
let lightNode = SCNNode()
lightNode.light = light
lightNode.position = SCNVector3(x: 1.5, y: 1.5, z: 1.5)
//add cube
let cubeGeometry = SCNBox(width: 1.0, height: 1.0, length: 1.0, chamferRadius: 0.0)
let boxNode = SCNNode(geometry: cubeGeometry)
scene.rootNode.addChildNode(lightNode)
scene.rootNode.addChildNode(cameraNode)
scene.rootNode.addChildNode(boxNode)
geometryNode = boxNode
//add recognizers
let panXRecognizer = UIPanGestureRecognizer(target: self, action: "rotateXGesture:")
let panYRecognizer = UIPanGestureRecognizer(target: self, action: "rotateYGesture:")
sceneView.addGestureRecognizer(panXRecognizer)
sceneView.addGestureRecognizer(panYRecognizer)
sceneView.scene = scene
}
func rotateXGesture (sender: UIPanGestureRecognizer) {
let translation = sender.translationInView(sender.view)
var newXAngle = (Float)(translation.y)*(Float)(M_PI)/180.0
newXAngle += currentXAngle
geometryNode.transform = SCNMatrix4MakeRotation(newXAngle, 1, 0, 0)
if(sender.state == UIGestureRecognizerState.Ended) {
currentXAngle = newXAngle
}
}
func rotateYGesture (sender: UIPanGestureRecognizer) {
let translation = sender.translationInView(sender.view)
var newYAngle = (Float)(translation.x)*(Float)(M_PI)/180.0
newYAngle += currentYAngle
geometryNode.transform = SCNMatrix4MakeRotation(newYAngle, 0, 1, 0)
if(sender.state == UIGestureRecognizerState.Ended) {
currentYAngle = newYAngle
}
}
}
您设置两个手势识别器的方式是相同的,它们都会针对相同的事件触发(这就是为什么要添加的最后一个占主导地位)。平移内没有控件专门将其限制为垂直或水平平移。相反,请考虑分析平移的方向,然后根据哪个方向更大来决定是将手势旋转到一个方向还是另一个方向。
将您当前的两个手势合二为一。这是我正在使用的代码的相关部分:
func panGesture(sender: UIPanGestureRecognizer) {
let translation = sender.translationInView(sender.view!)
var newAngleX = (Float)(translation.y)*(Float)(M_PI)/180.0
newAngleX += currentAngleX
var newAngleY = (Float)(translation.x)*(Float)(M_PI)/180.0
newAngleY += currentAngleY
baseNode.eulerAngles.x = newAngleX
baseNode.eulerAngles.y = newAngleY
if(sender.state == UIGestureRecognizerState.Ended) {
currentAngleX = newAngleX
currentAngleY = newAngleY
}
}
这里还有一个缩放手势:
func pinchGesture(sender: UIPinchGestureRecognizer) {
let zoom = sender.scale
var z = cameraNode.position.z * Float(1.0 / zoom)
z = fmaxf(zoomLimits.min, z)
z = fminf(zoomLimits.max, z)
cameraNode.position.z = z
}
编辑:我找到了一种更好的旋转模型的方法。在顶部的 panGesture
代码中,x 轴在您围绕 y 轴旋转时旋转。这意味着如果您围绕 y 旋转 180,则围绕 x 的旋转与您的手指运动相反。该方法还将运动限制为两个自由度。下面链接的方法,即使它不直接影响 z 轴,但似乎以某种方式允许三个自由度。它还使所有垂直滑动围绕 x 沿逻辑方向旋转。