如何修改推力方向以匹配 SceneKit 中的图像方向?



我有一个宇宙飞船图像资产,它被设计为"面向"+Z方向,+X在其左侧,+Y向上。我想要一个SCNVector3()来在飞船面对的方向上推力,这样如果我在推力方向上增加一个力,飞船就会向前移动。我找到一篇文章告诉我,我可以使用shipNode.worldFront来获得我想要的向量,但它与我的期望不符。我创建了shipNode并给它一个旋转,如下所示。

shipNode.rotation = SCNVector4(0,1,0,0)

当我像这样放置相机时

cameraNode.position = SCNVector3(x: 0, y: 0, z: 10)

我看到船的前部指向我。目前为止,一切都好。在触摸开始时,我保存了推力方向并打印了一些值。在触摸结束时,我重置了位置和推力方向,并在XZ平面上将船转π/2弧度

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
thrustDirection = shipNode.worldFront * Float(-1)
print("touchesBegan.rotation         (shipNode.rotation)")
print("touchesBegan.worldFront       (shipNode.worldFront)")
print("touchesBegan.thrustDirection: (thrustDirection)")
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
print("touchesEnded")
thrustDirection = SCNVector3()
shipNode.position = SCNVector3()
shipNode.rotation.x = 0
shipNode.rotation.y = 1
shipNode.rotation.z = 0
shipNode.rotation.w += Float.pi / 2
}

即使 SceneKit 正确显示飞船(首先朝向我,然后向右,然后向后,然后向左,然后再次朝向我),打印的数据具有一些无法解释的(对我来说)但一致的值。

touchesBegan.rotation         SCNVector4(x: 0.0, y: 1.0, z: 0.0, w: 0.0)
touchesBegan.worldFront       SCNVector3(x: 0.0, y: 0.0, z: -1.0)
touchesBegan.thrustDirection: SCNVector3(x: -0.0, y: -0.0, z: 1.0)
touchesEnded
touchesBegan.rotation         SCNVector4(x: 0.0, y: 1.0, z: 0.0, w: 1.57079625)
touchesBegan.worldFront       SCNVector3(x: -0.25, y: 0.0, z: -0.899999976)
touchesBegan.thrustDirection: SCNVector3(x: 0.25, y: -0.0, z: 0.899999976)
touchesEnded
touchesBegan.rotation         SCNVector4(x: 0.0, y: 1.0, z: 0.0, w: 3.1415925)
touchesBegan.worldFront       SCNVector3(x: -3.77489542e-08, y: 0.0, z: -0.124999881)
touchesBegan.thrustDirection: SCNVector3(x: 3.77489542e-08, y: -0.0, z: 0.124999881)
touchesEnded
touchesBegan.rotation         SCNVector4(x: 0.0, y: 1.0, z: 0.0, w: 4.71238899)
touchesBegan.worldFront       SCNVector3(x: 0.25, y: 0.0, z: -0.899999976)
touchesBegan.thrustDirection: SCNVector3(x: -0.25, y: -0.0, z: 0.899999976)
touchesEnded
touchesBegan.rotation         SCNVector4(x: 0.0, y: 1.0, z: 0.0, w: 6.28318501)
touchesBegan.worldFront       SCNVector3(x: 7.54979084e-08, y: 0.0, z: -1.0)
touchesBegan.thrustDirection: SCNVector3(x: -7.54979084e-08, y: -0.0, z: 1.0)
touchesEnded

第一个数据部分看起来是正确的 - 并且飞船如愿以偿地向前移动,但鉴于报告的旋转,第二,第三和第四个数据部分具有奇怪的.worldFront值。在情况2中,船向我驶来,但稍微向右滑动。在情况 3 中,船向我后退。在情况 4 中,船朝我驶来,但稍微向左滑动。当我旋转 2π 弧度时,飞船再次朝向并正确前进。

我已经阅读了SO在写这篇文章时建议的所有文章,并查看了Apple SceneKit文档,但无法解释我看到的行为。我错过了什么?感谢您的任何帮助!

推力方向似乎需要是船节点localFront方向转换为世界坐标的负数。我对坐标系数学不够好,无法理解为什么会这样,但以下版本的touchesBegan现在可以工作了。

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
thrustDirection = shipNode.convertVector(SCNNode.localFront, to: nil)
thrustDirection.x = -thrustDirection.x
thrustDirection.y = -thrustDirection.y
thrustDirection.z = -thrustDirection.z
}

convertVector调用中的nil显示转换为世界坐标。这条信息实际上来自苹果文档中的convertPosition功能。convertVector的文档页面仅显示"无可用的概述"。

请注意,localFront类型属性是在 iOS 11.0 中引入的。

最新更新