gpt4 book ai didi

ios - 如何使用平移手势识别器旋转 SCNSphere

转载 作者:搜寻专家 更新时间:2023-10-31 22:05:03 24 4
gpt4 key购买 nike

我创建了一个 SCNSphere,所以现在它看起来像是一颗行星。这正是我想要的。我的下一个目标是允许用户使用平移手势识别器旋转球体。他们可以围绕 X 或 Y 轴旋转它。我只是想知道我该怎么做。这是我目前所拥有的。

origin = sceneView.frame.origin
node.geometry = SCNSphere(radius: 1)
node.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "world.jpg")

let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(CategoryViewController.panGlobe(sender:)))
sceneView.addGestureRecognizer(panGestureRecognizer)

func panGlobe(sender: UIPanGestureRecognizer) {
// What should i put inside this method to allow them to rotate the sphere/ball
}

最佳答案

我们有一个 ViewController,它包含一个包含我们的球体的节点 sphereNode。要旋转球体,我们可以使用 UIPanGestureRecognizer .由于识别器会报告我们的手指在屏幕上移动的总距离,因此我们会缓存报告给我们的最后一个点。

var previousPanPoint: CGPoint?
let pixelToAngleConstant: Float = .pi / 180
func handlePan(_ newPoint: CGPoint) {
if let previousPoint = previousPanPoint {
let dx = Float(newPoint.x - previousPoint.x)
let dy = Float(newPoint.y - previousPoint.y)

rotateUp(by: dy * pixelToAngleConstant)
rotateRight(by: dx * pixelToAngleConstant)
}

previousPanPoint = newPoint
}

我们计算 dxdy self 们上次调用识别器以来我们的手指在每个方向上移动了多少像素。使用 pixelToAngleConstant,我们将像素值转换为一个角度(以 randians 为单位)以旋转我们的球体。使用更大的常量以获得更快的旋转。

手势识别器返回一个状态,我们可以使用它来确定手势是开始、结束还是手指已经移动。当手势开始时,我们将手指位置保存在 previousPanPoint 中。当我们的手指移动时,我们调用上面的函数。当手势结束或取消时,我们清除我们的 previousPanPoint

@objc func handleGesture(_ gestureRecognizer: UIPanGestureRecognizer) {
switch gestureRecognizer.state {
case .began:
previousPanPoint = gestureRecognizer.location(in: view)
case .changed:
handlePan(gestureRecognizer.location(in: view))
default:
previousPanPoint = nil
}
}

我们如何旋转球体?函数 rotateUprotateRight 只是调用我们更通用的函数,rotate(by: around:) 不仅接受角度而且接受轴旋转。rotateUp 绕 x 轴旋转,rotateRight 绕 y 轴旋转。

func rotateUp(by angle: Float) {
let axis = SCNVector3(1, 0, 0) // x-axis
rotate(by: angle, around: axis)
}

func rotateRight(by angle: Float) {
let axis = SCNVector3(0, 1, 0) // y-axis
rotate(by: angle, around: axis)
}

在这种情况下,rotate(by:around:) 相对简单,因为我们假设节点未平移/我们希望围绕节点局部坐标系的原点旋转。当我们查看一般情况时,一切都会稍微复杂一些,但这个答案只是一个小起点。

func rotate(by angle: Float, around axis: SCNVector3) {
let transform = SCNMatrix4MakeRotation(angle, axis.x, axis.y, axis.z)
sphereNode.transform = SCNMatrix4Mult(sphereNode.transform, transform)
}

我们从角度创建一个旋转矩阵,并将球体的旧变换乘以计算得到的新的转换

这是我创建的小演示:

Demo


这种方法有两个主要缺点。

  1. 它仅围绕节点坐标原点旋转,并且仅在节点位置为 SCNVector3Zero

  2. 时才能正常工作
  3. 它既不考虑手势的速度,也不会在手势停止时球体继续旋转。使用这种方法无法轻松实现类似于表格 View 的效果,您可以在其中滑动手指,表格 View 快速滚动然后减慢速度。一种解决方案是为此使用物理系统。

关于ios - 如何使用平移手势识别器旋转 SCNSphere,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45851641/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com