获得SCNNode面临的方向

时间:2014-11-09 03:43:52

标签: ios game-physics scenekit

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

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

我假设应用于节点的沿-z轴的力总是相对于节点向前移动,但事实并非如此。

2 个答案:

答案 0 :(得分:4)

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

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

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 {1}}等等,内置了许多常见的simd操作。

iOS 11更新

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

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

ship.simdPosition += ship.simdWorldFront * speed

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

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

答案 1 :(得分:2)

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

因此,如果要在节点的前向方向上应用力,则需要使用convertPosition:toNode:等方法将节点空间中的{0,0,-1}等向量转换为父节点。 / p>