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
Add Datepicker in Uiactionsheet Using Swift
How to Define an Extension to Collectiontype So That Its Methods Are Available to Dictionaries
Build Realm for Swift 3 & Xcode 8
Swiftui Hstack with Equal Height
How to Record My MAC's Internal Sound, Not the Microphone!, Using Avcapturesession
Why It Is Called the Memberwise Initialiser
Closure Use of Non-Escaping Parameter - Swift 3 Issue
Callback Url Not Approved Despite Being Provided Twitter API
Swiftui: Update Navigationview After Deletion (Ipad)
Subclass Uiscrollview in Swift for Touches Began & Touches Moved
Margin Between Images in Uiscrollview
Creating a Type Bound to a Certain Range in Swift
Scntext Alignment Not Working in iOS
How to Prevent a Spacer to Make a VStack Greedly Grow Beyond Necessary