【问题标题】:How do I modify thrust direction to match image direction in SceneKit?如何修改推力方向以匹配 SceneKit 中的图像方向?
【发布时间】:2018-03-16 04:10:20
【问题描述】:

我有一个宇宙飞船图像资源,它被设计为“面向”+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 中,我重置了 position 和推力方向,并在 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 文档,但无法解释我看到的行为。我错过了什么?感谢您的帮助!

【问题讨论】:

    标签: ios swift scenekit scnnode


    【解决方案1】:

    看来推力方向需要是船舶节点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 表示转换为世界坐标。这条信息实际上来自 Apple 文档中的 convertPosition 函数。 convertVector 的文档页面仅显示“没有可用的概述”

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

    【讨论】:

      猜你喜欢
      • 2018-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-13
      • 2021-01-19
      • 1970-01-01
      • 2017-07-03
      • 1970-01-01
      相关资源
      最近更新 更多