GameplayKit + SceneKit, GKAgent 旋转转换
GameplayKit + SceneKit, GKAgent rotation conversion
我在 Scenekit(和 ARKit,尽管这对这个问题并不重要)应用程序中使用 GameplayKit 一直很有趣。
具体来说,我一直在为行为使用实体、组件和代理,除了一件事,它们都运行良好。
我已经设法在组件内使用 GKAgent 在场景中四处移动,并避开其他对象。这一切似乎都在起作用。但是,我只能让 GKAgent 位置工作,而不是 "rotation" 属性。
import Foundation
import SceneKit
import GameplayKit
class MoveComponent: GKScnComponent, GKAgentDelegate {
//this class is abbreviated for perfunctory sakes
func agentWillUpdate(_ agent: GKAgent) {
guard let visualComponent = entity?.component(ofType: self.visualType) as? VisualComponent else {
return
}
//works with just "position", but turns possessed with both rotation and position
agentSeeking.rotation = convertToFloat3x3(float4x4: visualComponent.parentMostNode.simdTransform)
agentSeeking.position = visualComponent.parentMostNode.simdPosition
}
func agentDidUpdate(_ agent: GKAgent) {
guard let visualComponent = entity?.component(ofType: self.visualType) as? VisualComponent else {
return
}
//works with just "position", but turns possessed with both rotation and position
visualComponent.parentMostNode.simdPosition = agentSeeking.position
visualComponent.parentMostNode.simdTransform = convertToFloat4x4(float3x3: agentSeeking.rotation)
}
}
我写了一些3x3矩阵和4x4矩阵之间的转换代码,感谢这个问题:
import Foundation
import GameplayKit
func convertToFloat3x3(float4x4: simd_float4x4) -> simd_float3x3 {
let column0 = convertToFloat3 ( float4: float4x4.columns.0 )
let column1 = convertToFloat3 ( float4: float4x4.columns.1 )
let column2 = convertToFloat3 ( float4: float4x4.columns.2 )
return simd_float3x3.init(column0, column1, column2)
}
func convertToFloat3(float4: simd_float4) -> simd_float3 {
return simd_float3.init(float4.x, float4.y, float4.z)
}
func convertToFloat4x4(float3x3: simd_float3x3) -> simd_float4x4 {
let column0 = convertToFloat4 ( float3: float3x3.columns.0 )
let column1 = convertToFloat4 ( float3: float3x3.columns.1 )
let column2 = convertToFloat4 ( float3: float3x3.columns.2 )
let identity3 = simd_float4.init(x: 0, y: 0, z: 0, w: 1)
return simd_float4x4.init(column0, column1, column2, identity3)
}
func convertToFloat4(float3: simd_float3) -> simd_float4 {
return simd_float4.init(float3.x, float3.y, float3.z, 0)
}
我对这一切有点陌生,而且我不是线性代数大师,所以我不能 100% 确定我的矩阵转换函数是否完全按照它们应该做的去做。
当我只用agent的"position"属性的时候,一切正常,但是当我从agent到node中加上rotation/transform的时候,一切都开始附体了。
我做错了什么thoughts/pointers/help?
我明白了。矩阵乘法是实现此功能的关键。任何有 3d 游戏开发经验的人都可能告诉我,无需任何脑力劳动:)
func agentWillUpdate(_ agent: GKAgent) {
guard let visualComponent = entity?.component(ofType: self.visualType) as? VisualComponent else {
return
}
agentSeeking.position = visualComponent.parentMostNode.simdPosition
let rotation = visualComponent.parentMostNode.rotation
let rotationMatrix = SCNMatrix4MakeRotation(rotation.w, rotation.x, rotation.y, rotation.z)
let float4x4 = SCNMatrix4ToMat4(rotationMatrix)
agentSeeking.rotation = convertToFloat3x3(float4x4: float4x4)
}
func agentDidUpdate(_ agent: GKAgent) {
guard let visualComponent = entity?.component(ofType: self.visualType) as? VisualComponent else {
return
}
// visualComponent.parentMostNode.simdPosition = agentSeeking.position
let rotation3x3 = agentSeeking.rotation
let rotation4x4 = convertToFloat4x4(float3x3: rotation3x3)
let rotationMatrix = SCNMatrix4FromMat4(rotation4x4)
let position = agentSeeking.position
let translationMatrix = SCNMatrix4MakeTranslation(position.x, position.y, position.z)
let transformMatrix = SCNMatrix4Mult(rotationMatrix, translationMatrix)
visualComponent.parentMostNode.transform = transformMatrix
}
我希望有人觉得这有用。
我在 Scenekit(和 ARKit,尽管这对这个问题并不重要)应用程序中使用 GameplayKit 一直很有趣。
具体来说,我一直在为行为使用实体、组件和代理,除了一件事,它们都运行良好。
我已经设法在组件内使用 GKAgent 在场景中四处移动,并避开其他对象。这一切似乎都在起作用。但是,我只能让 GKAgent 位置工作,而不是 "rotation" 属性。
import Foundation
import SceneKit
import GameplayKit
class MoveComponent: GKScnComponent, GKAgentDelegate {
//this class is abbreviated for perfunctory sakes
func agentWillUpdate(_ agent: GKAgent) {
guard let visualComponent = entity?.component(ofType: self.visualType) as? VisualComponent else {
return
}
//works with just "position", but turns possessed with both rotation and position
agentSeeking.rotation = convertToFloat3x3(float4x4: visualComponent.parentMostNode.simdTransform)
agentSeeking.position = visualComponent.parentMostNode.simdPosition
}
func agentDidUpdate(_ agent: GKAgent) {
guard let visualComponent = entity?.component(ofType: self.visualType) as? VisualComponent else {
return
}
//works with just "position", but turns possessed with both rotation and position
visualComponent.parentMostNode.simdPosition = agentSeeking.position
visualComponent.parentMostNode.simdTransform = convertToFloat4x4(float3x3: agentSeeking.rotation)
}
}
我写了一些3x3矩阵和4x4矩阵之间的转换代码,感谢这个问题:
import Foundation
import GameplayKit
func convertToFloat3x3(float4x4: simd_float4x4) -> simd_float3x3 {
let column0 = convertToFloat3 ( float4: float4x4.columns.0 )
let column1 = convertToFloat3 ( float4: float4x4.columns.1 )
let column2 = convertToFloat3 ( float4: float4x4.columns.2 )
return simd_float3x3.init(column0, column1, column2)
}
func convertToFloat3(float4: simd_float4) -> simd_float3 {
return simd_float3.init(float4.x, float4.y, float4.z)
}
func convertToFloat4x4(float3x3: simd_float3x3) -> simd_float4x4 {
let column0 = convertToFloat4 ( float3: float3x3.columns.0 )
let column1 = convertToFloat4 ( float3: float3x3.columns.1 )
let column2 = convertToFloat4 ( float3: float3x3.columns.2 )
let identity3 = simd_float4.init(x: 0, y: 0, z: 0, w: 1)
return simd_float4x4.init(column0, column1, column2, identity3)
}
func convertToFloat4(float3: simd_float3) -> simd_float4 {
return simd_float4.init(float3.x, float3.y, float3.z, 0)
}
我对这一切有点陌生,而且我不是线性代数大师,所以我不能 100% 确定我的矩阵转换函数是否完全按照它们应该做的去做。
当我只用agent的"position"属性的时候,一切正常,但是当我从agent到node中加上rotation/transform的时候,一切都开始附体了。
我做错了什么thoughts/pointers/help?
我明白了。矩阵乘法是实现此功能的关键。任何有 3d 游戏开发经验的人都可能告诉我,无需任何脑力劳动:)
func agentWillUpdate(_ agent: GKAgent) {
guard let visualComponent = entity?.component(ofType: self.visualType) as? VisualComponent else {
return
}
agentSeeking.position = visualComponent.parentMostNode.simdPosition
let rotation = visualComponent.parentMostNode.rotation
let rotationMatrix = SCNMatrix4MakeRotation(rotation.w, rotation.x, rotation.y, rotation.z)
let float4x4 = SCNMatrix4ToMat4(rotationMatrix)
agentSeeking.rotation = convertToFloat3x3(float4x4: float4x4)
}
func agentDidUpdate(_ agent: GKAgent) {
guard let visualComponent = entity?.component(ofType: self.visualType) as? VisualComponent else {
return
}
// visualComponent.parentMostNode.simdPosition = agentSeeking.position
let rotation3x3 = agentSeeking.rotation
let rotation4x4 = convertToFloat4x4(float3x3: rotation3x3)
let rotationMatrix = SCNMatrix4FromMat4(rotation4x4)
let position = agentSeeking.position
let translationMatrix = SCNMatrix4MakeTranslation(position.x, position.y, position.z)
let transformMatrix = SCNMatrix4Mult(rotationMatrix, translationMatrix)
visualComponent.parentMostNode.transform = transformMatrix
}
我希望有人觉得这有用。