我有一个太空船图像资源,它被设计成“面向”+Z方向,左边是+X,上面是+Y。我想要一个SCNVector3()来计算船所面对的方向上的推力,这样如果我在推力方向上加一个力,船就会向前移动。我发现一篇文章告诉我可以使用shipNode.worldFront
来获得我想要的向量,但是它与我期望的不匹配。我创建了shipNode并按如下方式对其进行了旋转。
shipNode.rotation = SCNVector4(0,1,0,0)
当我放置这样的相机时
cameraNode.position = SCNVector3(x: 0, y: 0, z: 10)
我看到船头指着我。到目前为止,还不错。在touchesbearth中,我保存了推力方向并打印了一些值。在触地定向中,我重置了位置和推力方向,并使飞船在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
值与报告的旋转有关。在第二种情况下,船向我驶来,但稍微向右滑动。在案例3中,船向我后退。在案例4中,船向我驶来,但稍微向左滑动。当我旋转过2π弧度时,飞船再次朝着正确的方向前进。我已经阅读了所有在我写这篇文章时提出的建议,并且已经审阅了applesecenekit文档,但是无法解释我看到的行为。我错过了什么?谢谢你的帮助!
最佳答案
似乎推力方向需要是转换为世界坐标的船舶节点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
}
nil
调用中的convertVector
表示要转换为世界坐标。这条信息实际上来自苹果文档中的convertPosition
函数。convertVector
的doc页面只显示“没有可用的概述”。注意,
localFront
类型属性是在iOS 11.0中引入的。