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

时间:2018-03-15 00:30:31

标签: ios swift scenekit scnnode

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

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

当我像这样定位相机时

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

我看到船的前方指着我。到现在为止还挺好。在touchesBegan中,我保存了thrustDirection并打印了一些值。在touchesEnded中,我重置位置和推力方向并在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π弧度时,船正面向并再次向前移动。

我已经阅读了所有这些文章,因为我写了这篇文章,并且已经回顾了Apple SceneKit文档,但无法解释我看到的行为。我错过了什么?谢谢你的帮助!

1 个答案:

答案 0 :(得分:0)

似乎推力方向必须是船舶节点转换为世界坐标的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表示转换为世界坐标。这条信息实际上来自Apple的文档中的convertPosition功能。 convertVector的文档页面仅显示&#34;无概述&#34;

请注意,iOS 11.0中引入了localFront类型属性。