SCN四元数乘法
SCNQuaternion Multiplication
我正在尝试使用 Swift 在 SceneKit 中执行 SCNQuaternion 乘法。下面的代码是在 F# (Xamarin iOS Development) 中。我正在尝试将该代码翻译成 Swift.
我卡在了这条线上:让 dqm = SCNQuaternion.Multiply...
SceneKit 没有名为 multiply 的成员。
知道我该怎么做吗?
let rr = CMAttitudeReferenceFrame.XArbitraryCorrectedZVertical
this.motion.DeviceMotionUpdateInterval <- float (1.0f / 30.0f)
this.motion.StartDeviceMotionUpdates (rr,NSOperationQueue.CurrentQueue, (fun d e ->
let a = this.motion.DeviceMotion.Attitude
let q = a.Quaternion
let dq = new SCNQuaternion(float32 q.x, float32 q.y, float32 q.z, float32 q.w)
let dqm = SCNQuaternion.Multiply (dq, SCNQuaternion.FromAxisAngle(SCNVector3.UnitZ, piover2))
camNode.Orientation <- dqm
()
))
SceneKit 不包含用于进行四元数数学运算的库。 SCNQuaternion
只是 SCNVector4
的类型别名——换句话说,它是一个保存四元数的四个系数的地方,但你需要自己做数学来解释或使用它们。
在 Xcode 9 / iOS 11 / macOS 10.13 High Sierra 等中,SceneKit 中有一种更好的处理四元数(和其他 vector/matrix 数学)的方法:SIMD库包括两个四元数类型(用于双精度和浮点数),SceneKit 复制所有 SCNVector/SCNMatrix/SCNQuaternion 访问器以提供 SIMD 版本。使用 SIMD 类型而不是 SCN 类型的原因有很多:
- SIMD 类型用于多个 iOS/macOS/etc 框架,因此您可以使用它们在(例如)SceneKit、ARKit 和模型 I/O 之间传递 vector/matrix/四元数值,而无需强制转换或转换。
- Metal 着色器语言对其 vector/matrix 类型使用相同的库,因此您的数学代码可以在 CPU 和 GPU 之间轻松移植。
- 在 Swift 中,SIMD 类型显示为具有初始值设定项、属性和方法的结构,因此您的大部分 (*) 代码可以 Swift 友好。
- 在Swift和C++中,运算符重载涵盖了所有的基本操作,所以你的数学代码和读写就像数学一样。
- 以上所有内容都是使用编译器内部函数实现的,因此它们使用 CPU 的本机向量指令集,您的代码 运行 在(x86 SSE,ARM NEON)上运行速度更快。
不幸的是,CoreMotion 还没有(还?)为其 vector/matrix/四元数类型采用 SIMD 库,因此您需要将输入 CMQuaternion
转换为 simd_quatf
在使用 SIMD 函数或基于 SceneKit SIMD 的 API 之前。如果您发现自己经常这样做,您可能需要对其进行扩展:
extension simd_quatf {
init(_ cmq: CMQuaternion) {
self.init(ix: Float(cmq.x), iy: Float(cmq.y), iz: Float(cmq.z), r: Float(cmq.w))
}
}
然后(假设我没看错你的 F#),你的代码在 Swift:
中变成这样
let zAxis = float3(x: 0, y: 0, z: 1)
let rotateAroundZ = simd_quatf(angle: .pi/2, axis: zAxis)
manager.startDeviceMotionUpdates(using: .xArbitraryZVertical, to: queue) { motion, error in
guard let motion = motion else { /* handle error and */ return }
let deviceQuaternion = simd_quatf(motion.attitude.quaternion)
cameraNode.simdOrientation = deviceQuaternion * rotateAroundZ
}
(*) Some of the useful SIMD operations are still C-style global functions: Check simd/quaternion.h
for stuff like slerp and Bézier interpolation.
对于早期 Xcode/SDK 版本...
在 Xcode 9 /iOS 11 / macOS 10.13 / etc 之前,SIMD 中没有四元数,SceneKit 中也没有特定于 SIMD 的访问器。对于除四元数以外的所有内容,采用 SCN 类型、将它们按组件方式转换为等效的 SIMD 类型并在那里进行数学运算仍然很有用。
Apple 确实在 GLKit 中提供了一个四元数库。使用 GLKQuaternionMake
将 SCNQuaternion
的四个组成部分组成 GLKQuaternion
。然后你可以使用 GLKQuaternion
函数将它相乘,slerp 它。完成后,使用结果的组件制作另一个 SCNQuaternion
.
在 Swift 1.x (Xcode 6.x) 中,SIMD 库在 Swift 中不可用。 GLKit 数学是一个半途而废的替代品,但你最好只使用更新的 Xcode — 记住你可以一直瞄准 iOS 7 / macOS 10.9 Mavericks 即使 Swift 4(并且 SIMD 库可追溯到 iOS 8 / macOS 10.10 Yosemite)。
我正在尝试使用 Swift 在 SceneKit 中执行 SCNQuaternion 乘法。下面的代码是在 F# (Xamarin iOS Development) 中。我正在尝试将该代码翻译成 Swift.
我卡在了这条线上:让 dqm = SCNQuaternion.Multiply... SceneKit 没有名为 multiply 的成员。
知道我该怎么做吗?
let rr = CMAttitudeReferenceFrame.XArbitraryCorrectedZVertical
this.motion.DeviceMotionUpdateInterval <- float (1.0f / 30.0f)
this.motion.StartDeviceMotionUpdates (rr,NSOperationQueue.CurrentQueue, (fun d e ->
let a = this.motion.DeviceMotion.Attitude
let q = a.Quaternion
let dq = new SCNQuaternion(float32 q.x, float32 q.y, float32 q.z, float32 q.w)
let dqm = SCNQuaternion.Multiply (dq, SCNQuaternion.FromAxisAngle(SCNVector3.UnitZ, piover2))
camNode.Orientation <- dqm
()
))
SceneKit 不包含用于进行四元数数学运算的库。 SCNQuaternion
只是 SCNVector4
的类型别名——换句话说,它是一个保存四元数的四个系数的地方,但你需要自己做数学来解释或使用它们。
在 Xcode 9 / iOS 11 / macOS 10.13 High Sierra 等中,SceneKit 中有一种更好的处理四元数(和其他 vector/matrix 数学)的方法:SIMD库包括两个四元数类型(用于双精度和浮点数),SceneKit 复制所有 SCNVector/SCNMatrix/SCNQuaternion 访问器以提供 SIMD 版本。使用 SIMD 类型而不是 SCN 类型的原因有很多:
- SIMD 类型用于多个 iOS/macOS/etc 框架,因此您可以使用它们在(例如)SceneKit、ARKit 和模型 I/O 之间传递 vector/matrix/四元数值,而无需强制转换或转换。
- Metal 着色器语言对其 vector/matrix 类型使用相同的库,因此您的数学代码可以在 CPU 和 GPU 之间轻松移植。
- 在 Swift 中,SIMD 类型显示为具有初始值设定项、属性和方法的结构,因此您的大部分 (*) 代码可以 Swift 友好。
- 在Swift和C++中,运算符重载涵盖了所有的基本操作,所以你的数学代码和读写就像数学一样。
- 以上所有内容都是使用编译器内部函数实现的,因此它们使用 CPU 的本机向量指令集,您的代码 运行 在(x86 SSE,ARM NEON)上运行速度更快。
不幸的是,CoreMotion 还没有(还?)为其 vector/matrix/四元数类型采用 SIMD 库,因此您需要将输入 CMQuaternion
转换为 simd_quatf
在使用 SIMD 函数或基于 SceneKit SIMD 的 API 之前。如果您发现自己经常这样做,您可能需要对其进行扩展:
extension simd_quatf {
init(_ cmq: CMQuaternion) {
self.init(ix: Float(cmq.x), iy: Float(cmq.y), iz: Float(cmq.z), r: Float(cmq.w))
}
}
然后(假设我没看错你的 F#),你的代码在 Swift:
中变成这样let zAxis = float3(x: 0, y: 0, z: 1)
let rotateAroundZ = simd_quatf(angle: .pi/2, axis: zAxis)
manager.startDeviceMotionUpdates(using: .xArbitraryZVertical, to: queue) { motion, error in
guard let motion = motion else { /* handle error and */ return }
let deviceQuaternion = simd_quatf(motion.attitude.quaternion)
cameraNode.simdOrientation = deviceQuaternion * rotateAroundZ
}
(*) Some of the useful SIMD operations are still C-style global functions: Check
simd/quaternion.h
for stuff like slerp and Bézier interpolation.
对于早期 Xcode/SDK 版本...
在 Xcode 9 /iOS 11 / macOS 10.13 / etc 之前,SIMD 中没有四元数,SceneKit 中也没有特定于 SIMD 的访问器。对于除四元数以外的所有内容,采用 SCN 类型、将它们按组件方式转换为等效的 SIMD 类型并在那里进行数学运算仍然很有用。
Apple 确实在 GLKit 中提供了一个四元数库。使用
GLKQuaternionMake
将SCNQuaternion
的四个组成部分组成GLKQuaternion
。然后你可以使用GLKQuaternion
函数将它相乘,slerp 它。完成后,使用结果的组件制作另一个SCNQuaternion
.在 Swift 1.x (Xcode 6.x) 中,SIMD 库在 Swift 中不可用。 GLKit 数学是一个半途而废的替代品,但你最好只使用更新的 Xcode — 记住你可以一直瞄准 iOS 7 / macOS 10.9 Mavericks 即使 Swift 4(并且 SIMD 库可追溯到 iOS 8 / macOS 10.10 Yosemite)。