【问题标题】:Getting direction that SCNNode is facing获取 SCNNode 面临的方向
【发布时间】:2015-01-05 15:11:19
【问题描述】:

我迷失了如何在场景包中处理节点空间坐标和旋转。

如何获得节点在旋转后所面对的方向,以便我可以在该方向上施加力。

我假设沿 -z 轴施加到节点的力总是会使其相对于节点向前移动,但事实并非如此。

【问题讨论】:

    标签: ios game-physics scenekit


    【解决方案1】:

    负 z 是节点的“面向”方向,仅在其自己的坐标空间中(即其子节点和几何体所在的位置)。当您施加力时,您是在包含节点的坐标空间中工作。

    因此,如果您想在节点的向前方向上施加力,则需要使用 convertPosition:toNode: 之类的方法将像 {0,0,-1} 这样的向量从节点的空间转换为其父节点的空间。

    【讨论】:

    • 我一直在使用这种方法,但我似乎无法得到我想要的东西。将像 (0,0,1) 这样的向量转换为要移动的节点的presentationNode 坐标空间按预期工作,直到节点移动为止,一旦移动,转换就不再代表节点的朝向。
    • @user3765506 您介意与仍然需要解决方案的人分享您的解决方案吗?
    【解决方案2】:

    我也无法让convertPosition:toNode 工作。 ship.convertPosition(SCNVector3(0,0,-0.1), toNode: ship.parentNode) 的变化使节点以不可预测的方向和速度飞走。

    对我有用的是获取节点worldTransform 矩阵的第三行,它对应于它的 z 前向轴:

    func getZForward(node: SCNNode) -> SCNVector3 {
        return SCNVector3(node.worldTransform.m31, node.worldTransform.m32, node.worldTransform.m33)
    }
    
    ship.position += getZForward(ship) * speed
    // if node has a physics body, you might need to use the presentationNode, eg:
    // getZForward(ship.presentationNode)
    // though you probably don't want to be directly modifying the position of a node with a physics body
    
    // overrides for SCNVector arithmetic
    #if os(iOS)
        typealias VecFloat = Float
    #elseif os (OSX)
        typealias VecFloat = CGFloat
    #endif
    
    func + (lhs: SCNVector3, rhs: SCNVector3) -> SCNVector3 {
        return SCNVector3(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z)
    }
    
    func * (lhs: SCNVector3, rhs: VecFloat) -> SCNVector3 {
        return SCNVector3(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs)
    }
    
    func += (lhs: inout SCNVector3, rhs: SCNVector3) {
        lhs = lhs + rhs
    }
    

    如果节点有物理体,您可能必须将node.presentationNode 传递给函数。

    当 iOS 11/High Sierra 出现时,覆盖 SCNVector3 的需求将减少,因为所有SCNNode 属性都有simd 等价物,所以.position 还有.simdPosition 等等,并且内置了很多常用的simd操作。

    iOS 11 更新

    iOS 11 为获取节点的方向添加了方便的便利功能。在这种情况下,worldForward 属性就是您想要的。此外,SCNNode 上所有返回 SCNVector 的属性和矩阵类型现在都有返回 simd 类型的版本。因为 simd 已经为算术运算符提供了重载,所以您不再需要为 SCNVectorSCNMatrix 类型添加算术覆盖集。

    所以我们可以去掉上面的getZForward方法,只需要一行:

    ship.simdPosition += ship.simdWorldFront * speed
    

    iOS 11 添加的另一组方便的方法是一组convertVector 方法,以补充现有的convertPosition 方法。 convertVector相当于将矩阵乘以0w位置的向量,从而忽略矩阵的平移。这些是用于将法线、方向等内容从一个节点空间转换到另一个节点空间的适当方法。

    因为接受的答案使用convertPosition,我相信它只会对翻译为0,0,0原点的节点产生正确的结果

    【讨论】:

    • 不能对SCNVector进行二元运算“+”:
    • @johndoe 我用 SCNVector 覆盖更新了答案
    • worldFront 是您正在寻找的物业。 . .
    • 谢谢,ship.simdPosition += ship.simdWorldFront * 速度正是我所需要的。无论我的旋转是什么,它都给了我正面的矢量。
    猜你喜欢
    • 1970-01-01
    • 2014-07-29
    • 2020-09-21
    • 2018-03-19
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 2017-04-15
    • 2019-04-04
    相关资源
    最近更新 更多