【问题标题】:How do I rotate a 3d vector with a 4x4 matrix transform or euler angles?如何使用 4x4 矩阵变换或欧拉角旋转 3d 矢量?
【发布时间】:2017-11-28 13:53:18
【问题描述】:

我有一个 3d 矢量作为物理力应用:

let force = SCNVector3(x: 0, y: 0, z: -5)  
node.physicsBody?.applyForce(force, asImpulse: true)

我需要根据mobile device's position 旋转力,我可以使用 4x4 矩阵变换或欧拉角。

var transform :matrix_float4x4 - 相机在世界坐标空间中的位置和方向。

var eulerAngles :vector_float3 - 相机的方向,表示为滚动、俯仰和偏航值。

我认为这更像是一个基本的 3d 图形问题,但它的应用程序是使用 SceneKit 和 ARKit 的基于 Swift 的 iOS 应用程序。

SceneKit 和 simd 库中有一些实用程序可供我使用。不幸的是,我做simd_mul(force, currentFrame.camera.transform) 之类的天真尝试失败了。

【问题讨论】:

    标签: ios matrix graphics 3d scenekit


    【解决方案1】:

    @orangenkopf 提供了一个great answer 帮助我想出了这个:

    let force = simd_make_float4(0, 0, -5, 0)
    let rotatedForce = simd_mul(currentFrame.camera.transform, force)
    let vectorForce = SCNVector3(x:rotatedForce.x, y:rotatedForce.y, z:rotatedForce.z)
    node.physicsBody?.applyForce(vectorForce, asImpulse: true)
    

    【讨论】:

    • 这对我帮助很大!我必须在 simd_make_float4 调用中为我的本地方向切换 X 和 Y 值
    【解决方案2】:

    你的想法是对的。您需要将变换和方向相乘。 我在simd_mul 上找不到任何文档。但我怀疑你至少有以下问题之一:

    1. simd_mul 同时应用变换的旋转和平移
    2. 相机的变换在世界坐标空间中。根据您的节点层次结构,这可能会导致方向偏离。

    SceneKit 并没有提供太多的线性代数函数,所以我们必须自己构建:

    extension SCNMatrix4 {
        static public func *(left: SCNMatrix4, right: SCNVector4) -> SCNVector4 {
            let x = left.m11*right.x + left.m21*right.y + left.m31*right.z + left.m41*right.w
            let y = left.m12*right.x + left.m22*right.y + left.m32*right.z + left.m42*right.w
            let z = left.m13*right.x + left.m23*right.y + left.m33*right.z + left.m43*right.w
            let w = left.m14*right.x + left.m24*right.y + left.m43*right.z + left.m44*right.w
    
            return SCNVector4(x: x, y: y, z: z, w: w)
        }
    }
    extension SCNVector4 {
        public func to3() -> SCNVector3 {
            return SCNVector3(self.x , self.y, self.z)
        }
    }
    

    现在执行以下操作:

    1. 将相机变换转换为节点局部坐标系
    2. 将力创建为 4d 向量,将第四个元素设置为 0 以忽略平移
    3. 将变换和向量相乘

    // Convert the tranform to a SCNMatrix4
    let transform = SCNMatrix4FromMat4(currentFrame.camera.transform)
    // Convert the matrix to the nodes coordinate space
    let localTransform = node.convertTransform(transform, from: nil)
    
    let force = SCNVector4(0, 0, -5, 0)
    let rotatedForce = (localTransform * force).to3()
    
    node.physicsBody?.applyForce(rotatedForce, asImpulse: true)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-07
      • 1970-01-01
      • 2012-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-02
      相关资源
      最近更新 更多