Arkit - What Do the Different Columns in Transform Matrix Represent

Understanding ARKit World Transform Matrices

EDIT: The original question is best addressed by just adding 0.05 to the y component of the node's position. However, the original answer below does address a bit about composing transformation matrices, if that is something you are interested in.

======================================================================

If you want to apply an operation to a matrix, the most immediately simple way is to make a matrix that does that operation, and then multiply your original matrix by that new matrix.

For a translation, assuming you want to translate by x, y, z, you can do this:

let translation = simd_float4x4(
float4(1, 0, 0, 0),
float4(0, 1, 0, 0),
float4(0, 0, 1, 0),
float4(x, y, z, 1)
)

Note that this is just an identity matrix (1 down the diagonal) with the last column (!!!important, the float4s above are COLUMNS, not ROWS, as they would visually seem) set to contain the x/y/z values. You can research further into homogeneous coordinates, but think of this as just how a translation is represented.

Then, in simd, just do this: let newWorldTransform = translation * oldWorldTransform and you will have the old world transform translated by your x/y/z translation values (in your example, [x, y, z] = [0, 0.05, 0]).

However, it may be worth exploring why you want to edit your hit test results. I cannot think of a practical use case for that, so maybe if you explain a bit more about what you are trying to do I could suggest a more intuitive way to do it.

ARKIt and RealityKit – Why in Camera matrix last line always zero?

simd_float4x4 structure represents four columns with the following indices: 0, 1, 2, and 3. The last column with index 3 holds translation values for x, y and z. The fourth element in the last column is not like w in quaternions, it stands for homogeneous coordinates. Three diagonal 1 values are scale for x, y, and z axis.

┌               ┐
| 1 0 0 tx |
| 0 1 0 ty |
| 0 0 1 tz |
| 0 0 0 1 |
└ ┘

If you need a more detailed info on 4x4 matrices, read this post.

First three values in the lowest row are for projection purposes.

What are the first two columns in SCNMatrix4

SCNMatrix4 is the 3d transformation matrix. In short:

M = T * R * S

Translation by (tx, ty, tz):

    ┌             ┐
T = | 1 0 0 tx |
| 0 1 0 ty |
| 0 0 1 tz |
| 0 0 0 1 |
└ ┘

Scale by (sx, sy, sz):

    ┌               ┐
S = | sx 0 0 0 |
| 0 sy 0 0 |
| 0 0 sz 0 |
| 0 0 0 1 |
└ ┘

Rotation by (rx, ry, rz):

R = ZYX
┌ ┐
X = | 1 0 0 0 |
| 0 cos(rx) -sin(rx) 0 |
| 0 sin(rx) cos(rx) 0 |
| 0 0 0 1 |
└ ┘
┌ ┐
Y = | cos(ry) 0 sin(ry) 0 |
| 0 1 0 0 |
| -sin(ry) 0 cos(ry) 0 |
| 0 0 0 1 |
└ ┘
┌ ┐
Z = | cos(rz) -sin(rz) 0 0 |
| sin(rz) cos(rz) 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
└ ┘

By the way, it's simple to decompose the SCNMatrix4 using SceneKit framework:

let n = SCNNode()
n.transform = YOUR_MATRIX
let position = n.position
let orientation = n.orientation
let scale = n.scale

How do I extract rotation values from a simdTransform in ARKit?

The 3D rotation is expressed as a quaternion, which is made of a 3D vector, describing the axis that you are rotating around, and an angle, which describes the angle of rotation about that axis.

To get a quaternion from a 4x4 simd matrix, you can initialise simd_quatf from the matrix:

let m = simd_float4x4([
[0.9482585, 0.0065377234, 0.31743154, 0.0],
[-0.07080679, 0.9789629, 0.1913578, 0.0],
[-0.3095027, -0.20393308, 0.9287729, 0.0],
[0.13866597, 0.20701922, -0.57620335, 1.0]
])
let q = simd_quatf(m)

The rotation property of SCNNode is expressed as SCNVector4, which has x, y, and z properties describing the axis, and w describing the rotation. simd_quatf has axis (Float) and angle (SIMD3<Float>) properties, so to get your vector:

let sq = SCNVector4(q.axis.x, q.axis.y, q.axis.z, q.angle)

You can see here that the results are the same:

Sample Image

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