Ios scnqueternion乘法

Ios scnqueternion乘法,ios,swift,f#,quaternions,scenekit,Ios,Swift,F#,Quaternions,Scenekit,我正试图用Swift在SceneKit中执行一个SCNqueternion乘法。下面的代码在F#(Xamarin iOS开发)中。我正试着把代码翻译成Swift 我陷入了困境:让dqm=scnqueternion.Multiply。。。 SceneKit没有名为multiply的成员 你知道我该怎么做吗 let rr = CMAttitudeReferenceFrame.XArbitraryCorrectedZVertical this.motion.DeviceMotionUp

我正试图用Swift在SceneKit中执行一个SCNqueternion乘法。下面的代码在F#(Xamarin iOS开发)中。我正试着把代码翻译成Swift

我陷入了困境:让dqm=scnqueternion.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
        ()
    ))
让rr=CMAttitudeReferenceFrame.XArbitraryCorrectedZVertical
this.motion.DeviceMotionUpdateInterval
让a=这个。运动。设备运动。姿态
设q=a.四元数
设dq=new scnqueternion(float32 q.x,float32 q.y,float32 q.z,float32 q.w)
设dqm=scnqueternion.Multiply(dq,scnqueternion.FromAxisAngle(SCNVector3.UnitZ,piover2))

camNode.OrientationSceneKit不包括用于进行四元数数学运算的库
SCNqueternion
只是
SCConverctor4
的一个类型别名-换句话说,它是一个保存四元数的四个系数的地方,但您需要自己做数学运算来解释或使用它们

在Xcode 9/iOS 11/macOS 10.13 High Sierra/etc中,有一种更好的方法来处理SceneKit中的四元数(以及其他向量/矩阵数学):SIMD库包括两种四元数类型(用于双精度和浮点),SceneKit复制了所有SCNVector/SCNMatrix/SCnQueternion访问器以提供SIMD版本。使用SIMD类型而不是SCN类型有很多很好的理由:

  • SIMD类型用于多个iOS/macOS/etc框架,因此您可以使用它们在(例如)SceneKit、ARKit和模型I/O之间传递向量/矩阵/四元数值,而无需强制转换或转换
  • Metal shader语言对其向量/矩阵类型使用相同的库,因此您的数学代码可以在CPU和GPU之间轻松移植
  • 在Swift中,SIMD类型显示为带有初始值设定项、属性和方法的结构,因此大多数(*)代码都是Swift友好的
  • 在Swift和C++中,运算符重载覆盖了所有的基本操作,所以你的数学代码和读写一样的数学。李>
  • 以上所有内容都是使用编译器内部函数实现的,因此它们使用运行代码的CPU的本机向量指令集(x86 SSE,ARM NEON)来快速运行
不幸的是,CoreMotion尚未(目前?)采用SIMD库作为其向量/矩阵/四元数类型,因此在使用SIMD函数或基于SceneKit SIMD的API之前,您需要将输入的
CMQuaternion
转换为
SIMD_quatf
。如果您发现自己经常这样做,您可能需要对其进行扩展:

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#right),你的代码在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
}
(*)一些有用的SIMD操作仍然是C风格的全局函数:检查
SIMD/quaternion.h
中的slerp和Bézier插值之类的内容


对于早期的Xcode/SDK版本

  • 在Xcode 9/iOS 11/macOS 10.13/etc之前,SIMD中没有四元数,SceneKit中也没有SIMD特定的访问器。对于除四元数以外的所有类型,采用SCN类型,将它们按组件方式转换为等效的SIMD类型,并在那里进行计算仍然很有用

  • 苹果确实在GLKit中提供了一个四元数库。用于从
    scnqueternion
    的四个组件生成
    glk四元数。然后,您可以使用
    GLKQuaternion
    函数对其进行乘法、slerp运算。完成后,使用结果的组件创建另一个
    scnqueternion

  • 在Swift 1.x(Xcode 6.x)中,Swift无法提供SIMD库。GLKit math是一个相当不错的替代品,但是你最好只使用一个更新的Xcode——记住,即使使用Swift 4,你也可以一直瞄准iOS 7/macOS 10.9 Mavericks(而SIMD库可以追溯到iOS 8/macOS 10.10 Yosemite)


在我看API之前,我一直认为slerp是你编造的一个词。