为了扩展@rickster 的答案,这是在 Swift 中采用 4x4 矩阵的左上角 3x3 的好方法,利用 SceneKit 的 iOS 11/tvOS 11/High Sierra 版本中扩展的 simd 支持:
extension float4 {
var xyz: float3 {
return float3(x, y, z)
}
init(_ vec3: float3, _ w: Float) {
self = float4(vec3.x, vec3.y, vec3.z, w)
}
}
extension float4x4 {
var upperLeft3x3: float3x3 {
let (a,b,c,_) = columns
return float3x3(a.xyz, b.xyz, c.xyz)
}
init(rotation: float3x3, position: float3) {
let (a,b,c) = rotation.columns
self = float4x4(float4(a, 0),
float4(b, 0),
float4(c, 0),
float4(position, 1))
}
}
然后,要更新代理以匹配节点的方向,您可以编写:
agent.rotation = node.simdTransform.upperLeft3x3
或者,如果有问题的节点不在“根”级别(例如,rootNode 的直接子节点),您可能希望使用节点的 worldTransform:
agent.rotation = node.simdWorldTransform.upperLeft3x3
编辑:如果有问题的节点附加了动态物理体,或者正在使用 SCNTransaction 块进行动画处理,则节点的表示节点将更准确地反映其在屏幕上的当前位置:
agent.position = node.presentation.simdWorldPosition
agent.rotation = node.presentation.simdWorldTransform.upperLeft3x3
编辑:在上面添加了代码,用于向另一个方向移动,移动节点以匹配代理。
node.simdTransform = float4x4(rotation: agent3d.rotation, position: agent3d.position)
请注意,如果您有一个物理体附加到节点,如果您打算以这种方式直接修改节点的变换,则它应该是 kinematic 而不是 dynamic。