How can I calculate a distance between two AnchorEntities?
Theory
It's a bit tricky in RealityKit 2.0 . The position of the entity relative to its parent is:
public var position: SIMD3<Float>
// the same as: entity.transform.translation
But in your case, it doesn't work for AnchorEntity that has no parent. What actually does work is an instance method that returns a position of an entity relative to referenceEntity
(even if it's nil
, because nil
implies a world space):
public func position(relativeTo referenceEntity: Entity?) -> SIMD3<Float>
Solution
import UIKit
import RealityKit
class ViewController: UIViewController {
@IBOutlet var arView: ARView!
let anchor_01 = AnchorEntity(world: [ 1.22, 1.47,-2.75])
let anchor_02 = AnchorEntity(world: [-2.89, 0.15, 1.46])
override func viewDidLoad() {
super.viewDidLoad()
arView.scene.anchors.append(anchor_01)
arView.scene.anchors.append(anchor_02)
let dst = distanceBetweenEntities(anchor_01.position(relativeTo: nil),
and: anchor_02.position(relativeTo: nil))
print("The distance is: \(dst)") // WORKS
print("The position is: \(anchor_01.position)") // doesn't work
}
private func distanceBetweenEntities(_ a: SIMD3<Float>,
and b: SIMD3<Float>) -> SIMD3<Float> {
var distance: SIMD3<Float> = [0, 0, 0]
distance.x = abs(a.x - b.x)
distance.y = abs(a.y - b.y)
distance.z = abs(a.z - b.z)
return distance
}
}
Result:
// The distance is: SIMD3<Float>(4.11, 1.32, 4.21)
// The position is: SIMD3<Float>(0.0, 0.0, 0.0)
Get distance between the entity anchor and the camera
You need to perform a Convex Raycast
against all the geometry in the RealityKit's scene for a ray between two end points:
import UIKit
import RealityKit
class ViewController: UIViewController {
@IBOutlet var arView: ARView!
override func viewDidLoad() {
super.viewDidLoad()
let entity = ModelEntity(mesh: .generateBox(size: 0.4))
entity.name = "Cube"
let anchor = AnchorEntity(world: [0,0,0])
anchor.addChild(entity)
arView.scene.anchors.append(anchor)
// For every entity that could be hit,
// we must generate a collision shape.
entity.generateCollisionShapes(recursive: true)
}
@IBAction func onTap(_ sender: UITapGestureRecognizer) {
let query: CollisionCastQueryType = .nearest
let mask: CollisionGroup = .default
let camera = arView.session.currentFrame?.camera
let x = (camera?.transform.columns.3.x)!
let y = (camera?.transform.columns.3.y)!
let z = (camera?.transform.columns.3.z)!
let transform: SIMD3<Float> = [x, y, z]
let raycasts: [CollisionCastHit] = arView.scene.raycast(
from: transform,
to: [0, 0, 0],
query: query,
mask: mask,
relativeTo: nil)
guard let raycast: CollisionCastHit = raycasts.first
else { return }
print(raycast.distance) // Distance from the ray origin to the hit
print(raycast.entity.name) // The entity that was hit
print(raycast.position) // The position of the hit
}
}
Also, as @maxxfrazer suggested, you can access camera transforms more easily:
let translate = arView.cameraTransform.translation
let x = translate.x
let y = translate.y
let z = translate.z
let transform: SIMD3<Float> = [x, y, z]
ARKit - getting distance from camera to anchor
The last column of a 4x4 transform matrix is the translation vector (or position relative to a parent coordinate space), so you can get the distance in three dimensions between two transforms by simply subtracting those vectors.
let anchorPosition = anchor.transforms.columns.3
let cameraPosition = camera.transform.columns.3
// here’s a line connecting the two points, which might be useful for other things
let cameraToAnchor = cameraPosition - anchorPosition
// and here’s just the scalar distance
let distance = length(cameraToAnchor)
What you’re doing isn’t working right because you’re subtracting the z-coordinates of each vector. If the two points are different in x, y, and z, just subtracting z doesn’t get you distance.
RealityKit – What's the difference between Anchor and Entity translation?
In RealityKit, both AnchorEntity and ModelEntity are subclasses of their parental Entity class, which means that both of these subclasses have a Transform component. This implies that both objects can be moved, rotated and scaled.
The difference between ModelEntity and AnchorEntity is that an anchor is a special object that is automatically tracked in RealityKit. Model or several models need to be attached to the anchor, to prevent models from drifting. Thus, you can move the anchor itself (together with the models attached to it) and each model individually, if you need to.
Answering your question:
For an anchor with a single child, is there any difference between repositioning the anchor and repositioning the child entity?
In that particular case there's no difference. The only thing you need to think of is THIS.
Related Topics
How to Stop Playback of Avplayerviewcontroller as UIviewrepresentable After Dismissal
Call Function on App Termination in Swift
Need Clarification on Anyobject in Swift
What's a Placeholder? Why Do We Need to Define Placeholder Data Type for Generics
Why Run Loop Is Needed When Using Dispatchqueue.Main.Async in MAC Command Line Tool in Swift
Metal: Limit Mtlrendercommandencoder Texture Loading to Only Part of Texture
Gmsmarker Not Appearing on Map
Swift Ensembles Set Up & Ubiquitycontaineridentifier
Tab Bar Item Icons Appear Darker
How Make Polygon Without Intersection in Swift
Updating Existing Constraints Does Not Work, Wrong Use of .Active Property
Cache That Can Purge Unused Objects by Demand
How to Name File Stored to Files App via Uactivityviewcontroller