问题
I'm trying to understand the difference between the different element introduced in ArKit and their maybe equivalents in SceneKit:
SCNNode.simdTransform
vsSCNNode.transform
. In ARKit, it seems that people useSCNNode.simdTransform
instead ofSCNNode.transform
. How do they differ? simdTransform seems to use column major order, while transform (SCNMatrix4) is row major. How do I convert one to the other? Just transpose? I've the impression that the tracking doesn't work as well if I usetransform
instead ofsimdTransform
. Is that expected or just an impression? If I set one property, what happens if I then set the other one?ARFrame.camera
vsScene.pointOfView
: Looking at their transforms, they seem to be a bit different:
.
// ARFrame.camera.transform (matrix_float4x4)
-0.01 0.99 -0.11 0.02
-0.99 0.00 0.11 0.06
0.10 0.11 0.98 0.0
0.0 0.0 0.0 1.0
// sceneView.pointOfView.transform (SCNMatrix4)
// or sceneView.pointOfView.simdTransform^T (matrix_float4x4)
0.99 0 0.11 0
0.01 0.99 -0.12 0
-0.11 0.11 0.98 0
0.03 0.6 0.0 0.99
Are they the same minus one rotation?
回答1:
Both SceneKit and ARKit include symbols defined as SIMD types. Since ARKit imports SceneKit, the SIMD symbols defined in SceneKit are accessible to both. SIMD types enable parallel computation, so using them can improve the performance of your app's update logic. As you've found, there isn't always a convenient way to convert between a SIMD type and its older SceneKit or Core Graphics equivalent, so you'll usually get cleaner code by consistently using SIMD where possible.
Updating any property that affects the transform of a node also updates its other transform properties. This goes for local and world coordinates as well.
The camera
property of ARFrame
describes the device's hardware camera, not the virtual camera used to render the scene. While I would expect a close correspondence, my guess is you're polling the ARCamera
instance before the SCNCamera
instance has been updated during the render loop. If you can, I recommend driving those updates from the appropriate delegate methods, since you'll know the relevant data is up to date.
回答2:
I don't think that SCNMatrix4
is following the row major convention as you say. Consider the following:
func makeTranslationMatrix(tx: Float, ty: Float, tz: Float) -> simd_float4x4 {
var matrix = matrix_identity_float4x4
matrix[3, 0] = tx
matrix[3, 1] = ty
matrix[3, 2] = tz
return matrix
}
var T1 = makeTranslationMatrix(tx: 1, ty: 2, tz: 3)
print(T1.columns.0)
print(T1.columns.1)
print(T1.columns.2)
print(T1.columns.3)
/*
T1
float4(1.0, 0.0, 0.0, 0.0)
float4(0.0, 1.0, 0.0, 0.0)
float4(0.0, 0.0, 1.0, 0.0)
float4(1.0, 2.0, 3.0, 1.0)
*/
var sceneT1 = SCNMatrix4MakeTranslation(1, 2, 3)
print("\(sceneT1.m11), \(sceneT1.m12), \(sceneT1.m13), \(sceneT1.m14)")
print("\(sceneT1.m21), \(sceneT1.m22), \(sceneT1.m23), \(sceneT1.m24)")
print("\(sceneT1.m31), \(sceneT1.m32), \(sceneT1.m33), \(sceneT1.m34)")
print("\(sceneT1.m41), \(sceneT1.m42), \(sceneT1.m43), \(sceneT1.m44)")
/*
sceneT1
1.0, 0.0, 0.0, 0.0
0.0, 1.0, 0.0, 0.0
0.0, 0.0, 1.0, 0.0
1.0, 2.0, 3.0, 1.0
*/
As you can see, the translation values for SCNMatrix4
are stored in m41, m42, m43
- in the 4th column. It may be possible that these values are stored in m41, m42, m43
due to the matrix being transposed and then they actually store the translation values in the 4th row. This question covers that confusion.
来源:https://stackoverflow.com/questions/44732476/arkit-vs-scenekit-coordinates