How to rotate a 3D vector with 4x4 matrix transformation or Euler angles?

I have a 3d vector that I use as physical force:

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

I need to rotate the force based on the position of the mobile device , which is available to me as a 4x4 matrix transformation or Euler angles.

var transform: matrix_float4x4 - The position and orientation of the camera in world coordinate space.

var eulerAngles: vector_float3 - Camera orientation expressed as roll, pitch, and yaw values.

I think this is a more fundamental issue with 3D graphics, but applying this is a Swift-based iOS app using SceneKit and ARKit.

There are several utilities available to me in SceneKit and simd libraries. Unfortunately, my naive attempts to do something like simd_mul(force, currentFrame.camera.transform)fail.

+4
source share
2 answers

@orangenkopf provided a great answer that helped me come up with this:

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)
+5
source

Your idea is right. You need to multiply the conversion and direction. I can not find the documentation on simd_mul. But I suspect that you have at least one of the following problems:

  • simd_mul applies both rotation and translation translation
  • . node , .

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)
    }
}

:

  • 4d, 0,

// 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)
+3

Source: https://habr.com/ru/post/1680069/


All Articles