Scenekit将节点旋转到面对抽头点

时间:2018-07-16 18:22:58

标签: ios swift scenekit

我正在使用默认的Scenekit游戏项目来尝试实现一些轻击控件以使飞船飞来飞去,这是该项目随附的默认控件。我想弄清楚的是如何旋转我的船的鼻子,以面对屏幕上点击的点。我一直在关注我所见过的所有示例,并提出以下建议:

let point:CGPoint = sender.location(in: sender.view)
let deltaY:Float = Float(point.y) - ship.position.y
let deltaX:Float = Float(point.x) - ship.position.x
let degreesToRadians = Float.pi / 180
let angle = atan2(deltaY, deltaX) + (90 * degreesToRadians)
ship.rotation = SCNVector4(0,1,0,angle)

一些注意事项:

  • 我并没有更改装载船的rotationposition,两个属性的每个点都显示0
  • 当我加载项目时,船朝下。据我了解,您需要将angle的计算偏移为0度,这就是为什么我在+ (90 * degreesToRadians)的计算中进行angle的原因。

当我用手指在船上绕圈旋转时会发生什么情况,即船从0deg-90deg旋转了90度弧。万一我不清楚(或正确),无论我在屏幕上的什么位置,它都会在东西方向之间移动。

最后一件事要注意。我的相机锁定在俯视图上,所以我只想旋转Y轴,这是方向和第一个加载位置的快速屏幕截图: first load position

如果您有任何技巧,想法或知识来发送我的方式,那就太好了。这个问题让我难过。

1 个答案:

答案 0 :(得分:2)

越来越近,您的失踪只有几步之遥。

首先在视图坐标中转换水龙头的位置,这与您的代码相同,只是名称不同。

let viewPoint = gestureRecognize.location(in: scnView)

由于视图是2D的,而SCNScene是3D的,因此您需要使用scnView.unprojectPoint转换为场景坐标。

let camera = cameraNode.camera
let distance = camera.zFar - camera.zNear / cameraNode.position.y
let scenePoint = scnView.unprojectPoint(SCNVector3(viewPoint.x, viewPoint.y, CGFloat(distance)))

然后计算角度。在您的情况下,重要的是您要向下看,所以要使用的轴是X和Z。此外,正X在右边,但正Z在向下,这需要考虑。 / p>

let deltaZ = scenePoint.z - ship.position.z
let deltaX = scenePoint.x - ship.position.x
let angle = atan2(deltaZ, deltaX) - .pi / 2
ship.rotation = SCNVector4(0, -1, 0, angle)

那应该做到。同样不是说,如果您将相机旋转了任何角度(不是90度的倍数),则2D-> 3D转换和角度计算将更加复杂,因为它不像将一个轴视为另一个轴那样简单。


编辑-旋转0/360度边界

您需要检查顺时针旋转还是逆时针旋转需要更多的移动并更新角度。

if abs(angle - .pi * 2 - ship.rotation.w) < abs(angle - ship.rotation.w) {
    angle -= .pi * 2
}

此外,我认为四元数可能会自动处理此问题,但我对它们不够熟悉,无法发布解决方案。