I have an object in ARKit's screen and I want to know the horizontal angle between it and the camera direction, or at least is the object on the left, center or right of the screen?
Asked
Active
Viewed 622 times
1 Answers
2
Definitely (well kind of)
First, we need to understand ARKit.
ARKit objects are not in
actual
space and are based off of what the camera sees.The camera is not perfect; You will notice "stationary" objects moving around either due to lighting, surroundings, etc.
No one's hand is steady; not only will the object be moving, but the phone will be doing small adjustments as well.
Now, provided this information, we can use the variables we know to calculate the angle between 3 known positions (in 3D Space of course!).
Using this answer, we can see that through lots of math we can get to an angle from 3 3D points
Now, getting into the code of it.
Let's get our variables
- You can get your
phone
position using a function provided bySCNSceneRendererDelegate
func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) {
guard let pointOfView = sceneView.pointOfView else { return }
let transform = pointOfView.transform
let orientation = SCNVector3(-transform.m31, -transform.m32, transform.m33)
let location = SCNVector3(transform.m41, transform.m42, transform.m43)
let currentPositionOfCamera = orientation + location
print(currentPositionOfCamera)
}
func +(lhv:SCNVector3, rhv:SCNVector3) -> SCNVector3 {
return SCNVector3(lhv.x + rhv.x, lhv.y + rhv.y, lhv.z + rhv.z)
}
- You can get your
object
by doing
let anObject = SCNNode()
let pos = anObject.position
- You can get your
userViewDirection
in a slightly creative way -- the best way I can come up with is to create a newSCNNode
and place it some distance in front of you. We can do this by using this link
func updatePositionAndOrientationOf(_ node: SCNNode, withPosition position: SCNVector3, relativeTo referenceNode: SCNNode) {
let referenceNodeTransform = matrix_float4x4(referenceNode.transform)
// Setup a translation matrix with the desired position
var translationMatrix = matrix_identity_float4x4
translationMatrix.columns.3.x = position.x
translationMatrix.columns.3.y = position.y
translationMatrix.columns.3.z = position.z
// Combine the configured translation matrix with the referenceNode's transform to get the desired position AND orientation
let updatedTransform = matrix_multiply(referenceNodeTransform, translationMatrix)
node.transform = SCNMatrix4(updatedTransform)
}
//Create a global node
let lookingNode:SCNNode = SCNNode()
//Now update node say `2` away in the Z (looking direction)
let position = SCNVector3(x: 0, y: 0, z: -2)
updatePositionAndOrientationOf(lookingNode, withPosition: position, relativeTo: cameraNode)
Now we have our 3 variables.
We can san simply do math on them :)
//Vertex is pos1
func calculateAngleBetween3Positions(pos1:SCNVector3, pos2:SCNVector3, pos3:SCNVector3) -> Float {
let v1 = SCNVector3(x: pos2.x-pos1.x, y: pos2.y-pos1.y, z: pos2.z-pos1.z)
let v2 = SCNVector3(x: pos3.x-pos1.x, y: pos3.y-pos1.y, z: pos3.z-pos1.z)
let v1Magnitude = sqrt(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z)
let v1Normal = SCNVector3(x: v1.x/v1Magnitude, y: v1.y/v1Magnitude, v1.z/v1Magnitude)
let v2Magnitude = sqrt(v2.x * v2.x + v2.y * v2.y + v2.z * v2.z)
let v2Normal = SCNVector3(x: v2.x/v2Magnitude, y: v2.y/v2Magnitude, v2.z/v2Magnitude)
let result = v1Normal.x * v2Normal.x + v1Normal.y * v2Normal.y + v1Normal.z * v2Normal.z
let angle = acos(result)
return angle
}

aheze
- 24,434
- 8
- 68
- 125

impression7vx
- 1,728
- 1
- 20
- 50
-
What is cameraNode? – aheze Feb 12 '21 at 04:05
-
Never mind, it's `sceneView.pointOfView` I think – aheze Feb 12 '21 at 04:14