How to Rotate an Arkit 4X4 Matrix Around Y Using Apple's Simd Library

Xcode simd - issue with Translation and Rotation Matrix Example

This can be confusing, yes.

The documentation you mentions makes the following computation:

let translatedVector = positionVector * translationMatrix

Note that the matrix is on the right side of the multiplication.
You are probably used to the notation b = M * a but if you take the transpose you get b' = a' * M' which is what the sample does.

In SIMD there's no way to differentiate a vector from its transpose (b from b') and the library allows you to make the multiplication in both ways:

static simd_float3 SIMD_CFUNC simd_mul(simd_float3x3 __x, simd_float3 __y);
static simd_float3 SIMD_CFUNC simd_mul(simd_float3 __x, simd_float3x3 __y) { return simd_mul(simd_transpose(__y), __x); }

In iOS/Swift, what module is MatrixHelper a part of?

I think he just wrote a custom class to wrap the functions provided by GLKit.

He named that class MatrixHelper.

With MatrixHelper.rotateAboutY() he is calling something like:

GLKMatrix4 GLKMatrix4Rotate(GLKMatrix4 matrix, float radians, float x, float y, float z);

So the package used in MatrixHelper is GLKit and to be more precise GLKMatrix4

https://developer.apple.com/documentation/glkit/glkmatrix4-pce

Converting matrix_float3x3 rotation to SceneKit

To expand on @rickster 's answer, here's a nice way to take the top-left 3x3 of a 4x4 matrix in Swift, taking advantage of the expanded simd support in the iOS 11/ tvOS 11/ High Sierra version of SceneKit:

extension float4 {
var xyz: float3 {
return float3(x, y, z)
}

init(_ vec3: float3, _ w: Float) {
self = float4(vec3.x, vec3.y, vec3.z, w)
}
}

extension float4x4 {
var upperLeft3x3: float3x3 {
let (a,b,c,_) = columns
return float3x3(a.xyz, b.xyz, c.xyz)
}

init(rotation: float3x3, position: float3) {
let (a,b,c) = rotation.columns
self = float4x4(float4(a, 0),
float4(b, 0),
float4(c, 0),
float4(position, 1))
}
}

Then, to update your agent to match your node's orientation, you'd write:

agent.rotation = node.simdTransform.upperLeft3x3

Or, if the node in question is not at the "root" level (as in, a direct child of the rootNode), you might want to use the node's worldTransform:

agent.rotation = node.simdWorldTransform.upperLeft3x3

EDIT: If the node in question has a dynamic physics body attached, or is being animated with an SCNTransaction block, the node's presentation node will more accurately reflect its current position on screen:

agent.position = node.presentation.simdWorldPosition
agent.rotation = node.presentation.simdWorldTransform.upperLeft3x3

EDIT: added code above for going in the other direction, moving the node to match the agent.

node.simdTransform = float4x4(rotation: agent3d.rotation, position: agent3d.position)

Note that if you have a physics body attached to the node, it should be kinematic rather than dynamic if you're going to be directly modifying the node's transform in this way.

ARKit – eulerAngles of Transform Matrix 4x4

Assuming mij is matrix element in the i-th row and j-th column.

R=atan2(m12, m22)
c2 = sqrt(m00^2 + m01^2)
P = atan2(-m02, c2)
s1 = sin(R), c1 = cos(R)
Y = atan2(s1*m20 - c1*m10, c1*m11-s1*m21)

Source:
The math is described in this document really well: https://pdfs.semanticscholar.org/6681/37fa4b875d890f446e689eea1e334bcf6bf6.pdf

As opposed to going to quaternion, there are some corner cases (gimbal lock) you have to worry about that the above solution handles pretty well.



Related Topics



Leave a reply



Submit