I am using SwiftUI/ARKit/RealityKit to try and perform some live changes in my ARView. It consists in drawing planes when the user applies a long pressure on the view and moves his finger.
The drawing of the plane happens in the following way:
- a sphere is drawn where the user presses for more than 0.5 sec.
- when the user moves his finger, a sphere follows the user's finger.
- when the user moves his finger, a plane is drawn with its center positioned in the center of the spheres in 1. and 2. using the following code.
- when the user removes his finger the steps 2. and 3. are performed to finalise the position of the end sphere and plane.
My issue is, the drawn plane's normal vector (and probably the spheres as well) is tilted with an angle in comparison with the surface's actual normal vector.
When showing the anchor origins in the debug options of the arView, there always is an anchor origin which would correspond to the touched surface and have axes that are collinear to the gravity and the normal of the surface. Is there a way to access this anchor origin to be able to project the device's world anchor?
Bellow the code I am using to draw the surface.
let location = sender.location(in: parent.arView)
var position = SIMD3<Float>()
let raycastResults = parent.arView.raycast(from: location, allowing: .existingPlaneGeometry, alignment: .vertical)
if let raycastResult = raycastResults.first {
position = SIMD3(x: raycastResult.worldTransform.columns.3.x, y: raycastResult.worldTransform.columns.3.y, z: raycastResult.worldTransform.columns.3.z)
let anchorDistance = distance(position, self.parent.arView.cameraTransform.translation)
switch sender.state {
case .began:
clearAllAnchors()
let startSphereModel = sphere(radius: anchorDistance*0.005, color: .red)
let startSphereAnchorEntity = AnchorEntity(world: raycastResult.worldTransform)
startSphereAnchorEntity.addChild(startSphereModel)
self.currentAnchor.append(startSphereAnchorEntity)
parent.arView.scene.addAnchor(startSphereAnchorEntity)
startPosition = position
startSphere = startSphereModel
case .changed:
clearAnchors(tempAnchor)
let tempEndSphereModel = sphere(radius: anchorDistance*0.005, color: .red)
guard let anchor = raycastResult.anchor as? ARPlaneAnchor else {return}
let width = computeRectangleParameters(position: position, anchor: anchor).width
let height = computeRectangleParameters(position: position, anchor: anchor).height
let midPosition = (startPosition + position)/2
let planeMesh = MeshResource.generatePlane(width: width, height: height)
let tempPlaneModel = ModelEntity(mesh: planeMesh, materials: [SimpleMaterial(color: UIColor(red: 1, green: 0, blue: 0, alpha: 0.4), isMetallic: false)])
let tempPlaneAnchorEntity = AnchorEntity(world: midPosition)
let tempEndSphereAnchorEntity = AnchorEntity(world: raycastResult.worldTransform)
tempEndSphereAnchorEntity.addChild(tempEndSphereModel)
tempPlaneAnchorEntity.addChild(tempPlaneModel)
self.tempAnchor.append(tempPlaneAnchorEntity)
self.tempAnchor.append(tempEndSphereAnchorEntity)
parent.arView.scene.addAnchor(tempEndSphereAnchorEntity)
parent.arView.scene.addAnchor(tempPlaneAnchorEntity)
I have not posted the ending state since it is pretty similar to the changed state.
On top of that, the plane dimensions are actually not correct as the code is now (expanding in the right directions) but this is easily resolvable once I manage to get access to the plane's "intrinsic" anchor