【发布时间】:2015-01-05 15:11:19
【问题描述】:
我迷失了如何在场景包中处理节点空间坐标和旋转。
如何获得节点在旋转后所面对的方向,以便我可以在该方向上施加力。
我假设沿 -z 轴施加到节点的力总是会使其相对于节点向前移动,但事实并非如此。
【问题讨论】:
标签: ios game-physics scenekit
我迷失了如何在场景包中处理节点空间坐标和旋转。
如何获得节点在旋转后所面对的方向,以便我可以在该方向上施加力。
我假设沿 -z 轴施加到节点的力总是会使其相对于节点向前移动,但事实并非如此。
【问题讨论】:
标签: ios game-physics scenekit
负 z 是节点的“面向”方向,仅在其自己的坐标空间中(即其子节点和几何体所在的位置)。当您施加力时,您是在包含节点的坐标空间中工作。
因此,如果您想在节点的向前方向上施加力,则需要使用 convertPosition:toNode: 之类的方法将像 {0,0,-1} 这样的向量从节点的空间转换为其父节点的空间。
【讨论】:
我也无法让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 为获取节点的方向添加了方便的便利功能。在这种情况下,worldForward 属性就是您想要的。此外,SCNNode 上所有返回 SCNVector 的属性和矩阵类型现在都有返回 simd 类型的版本。因为 simd 已经为算术运算符提供了重载,所以您不再需要为 SCNVector 和 SCNMatrix 类型添加算术覆盖集。
所以我们可以去掉上面的getZForward方法,只需要一行:
ship.simdPosition += ship.simdWorldFront * speed
iOS 11 添加的另一组方便的方法是一组convertVector 方法,以补充现有的convertPosition 方法。 convertVector相当于将矩阵乘以0在w位置的向量,从而忽略矩阵的平移。这些是用于将法线、方向等内容从一个节点空间转换到另一个节点空间的适当方法。
因为接受的答案使用convertPosition,我相信它只会对翻译为0,0,0原点的节点产生正确的结果
【讨论】: