SceneKit physicalBody 角速度作为局部“身体固定”角速率

问题描述 投票:0回答:1

我正在开发一款 SceneKit iOS 游戏,玩家可以在 3D 空间中控制一艘太空飞船。我的最终目标是实现船舶角度稳定,当用户停止提供旋转输入时,船舶将自动停止滚动/俯仰/偏航。例如,如果飞行员使船舶直线水平飞行并进行“桶滚”,当飞行员不再命令滚滚时,我希望船舶自动提供与滚滚相反方向的扭矩,直到船舶不再命令滚滚。更长的任意滚动角速度。

我能够以编程方式识别船舶当前角旋转的最接近方法是获取

ship.physicsBody?.angularVelocity
并将其转换为欧拉角。只要我没有将船从原来的位置/方向移开,我就能得到我期望的结果。然而,一旦我移动船舶,报告的 angleVelocity 值似乎会旋转(例如不再处于“身体固定”坐标系中)。

有没有办法获得局部“身体固定”坐标中的角速度?例如,假设我的船现在“停止”在某个任意位置,并进行任意旋转。现在假设我开始绕其 z 轴滚动飞船(这样飞行员就可以感知到前窗外的环境顺时针旋转)。如何将 ship.physicsBody?.angularVelocity 的输出转换为仅报告滚动轴上的角速度?

    

swift vector scenekit quaternions rotational-matrices
1个回答
0
投票
angularVelocity

数据相关的有意义的信息。

我过去曾使用过 3d 旋转,但从未使用过四元数。我仍然不太了解四元数,但现在我已经足够了解它们可以用“角轴”表示形式表示,这意味着四元数 

(0.0, 0.0i, 0.0j, 1.0k)

具有表示为

cos(90) + sin(90)(0.0i + 0.0j + 1.0k)
的角轴表示形式。
Grant Sanderson
Ben Eater 制作的这个视频系列 非常有帮助。 学习完之后,我注意到SCNPhysicsBody头文件定义了

angularVelocity

,如下:

//Specifies the angular velocity of the receiver as an axis angle.
open var angularVelocity: SCNVector4

我终于意识到这个数据是以角轴格式表示的四元数。

以下是我想出的解决方案。这并不理想,因为我首先将四元数转换为欧拉角,然后旋转欧拉角。我相信更好的解决方案是首先旋转四元数,然后将最终结果转换为欧拉角。不幸的是,据我所知,SceneKit 只提供了

convertVector

convertTransform
函数来旋转
SCNVector3
SCNMatrix4
数据,但没有提供旋转
SCNQuaternion
的功能。我仍然不太明白这一点,还没有自己手动编写代码来旋转这个四元数。
public extension SCNNode {
    var localAngularVelocity: SCNVector3 {
        let angularVelocity_as_angleAxis = self.physicsBody!.angularVelocity

        let simd_angularVelocityQuat = simd_quatf( angle: angularVelocity_as_angleAxis.w,
                                                   axis: SIMD3<Float>( x: angularVelocity_as_angleAxis.x,
                                                                       y: angularVelocity_as_angleAxis.y,
                                                                       z: angularVelocity_as_angleAxis.z ) )

        let n = SCNNode()
        n.simdOrientation = simd_angularVelocityQuat
        let vectorInWorld = n.eulerAngles

        let me = self.presentation
        // Rotate vector from world coord system to my local coord system
        return me.convertVector(vectorInWorld, from: nil)
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.