0

I want to draw the mesh point on the detected plane as shown in the video link and I don't know how to achieve it.

Can you help me out to achieve this?

Thanks in advance.

Andy Jazz
  • 36,357
  • 13
  • 107
  • 175
  • Hi @KishanBarmawala, your example is ARCore plane detection (not ARKit/RealityKit), and I cannot see any mesh points you're talking about. What do you need exactly: to visualize a meshes of horizontal and vertical detected planes or visualize vertices of detected planes? – Andy Jazz Mar 04 '22 at 06:54
  • 1
    Thanks for the reply @AndyJazz . the given video is shot from an android device and I want to achieve white texture as shown in video and it should remain on the already detected plane. – Kishan Barmawala Mar 04 '22 at 07:02
  • Visible dots (aka "vertices") on ARCore detected plane are just a part of a procedural mesh texture (they are not real vertices). – Andy Jazz Mar 04 '22 at 07:05
  • Ok, I've got it. I'll post my answer later in the evening... – Andy Jazz Mar 04 '22 at 07:10
  • 1
    Thanks for the help sir @AndyJazz. I'll wait for your response. – Kishan Barmawala Mar 04 '22 at 07:11

1 Answers1

3

In ARKit/RealityKit, in order to visualize the plane detection process similarly to the behavior you can see in ARCore, you should use the Scene Reconstruction feature – for iOS devices with a LiDAR scanner – however, this is a completely different story (Metal story), because you have to develop a procedural texture with soft mask for front edge.

In this post I want to show you how to use the "classic" visualization of plane detection process using ARKit/RealityKit. But in this case, I do not promise to show this process as visually pleasing as it's implemented in ARCore.

Here's a code:

import ARKit
import RealityKit

class Grid: Entity, HasModel, HasAnchoring {        
    var planeAnchor: ARPlaneAnchor
    var planeGeometry: MeshResource!
    
    init(planeAnchor: ARPlaneAnchor) {
        self.planeAnchor = planeAnchor
        super.init()
        self.didSetup()
    }
        
    fileprivate func didSetup() {            
        self.planeGeometry = .generatePlane(width: planeAnchor.extent.x,
                                            depth: planeAnchor.extent.z)
        var material = UnlitMaterial()
        material.color = .init(tint: .white.withAlphaComponent(0.999),
                            texture: .init(try! .load(named: "grid.png")))
        let model = ModelEntity(mesh: planeGeometry, materials: [material])
        model.position = [planeAnchor.center.x, 0, planeAnchor.center.z]
        self.addChild(model)
    }
    
    fileprivate func didUpdate(anchor: ARPlaneAnchor) {            
        self.planeGeometry = .generatePlane(width: anchor.extent.x,
                                            depth: anchor.extent.z)
        let pose: SIMD3<Float> = [anchor.center.x, 0, anchor.center.z]
        let model = self.children[0] as! ModelEntity
        model.position = pose
    }        
    required init() { fatalError("Hasn't been implemented yet") }
}

ViewController.swift

class ViewController: UIViewController {
    
    @IBOutlet var arView: ARView!
    var grids = [Grid]()

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        arView.session.delegate = self
        
        let config = ARWorldTrackingConfiguration()
        config.planeDetection = [.horizontal, .vertical]
        arView.session.run(config)
    }
}

ARSessionDelegate

extension ViewController: ARSessionDelegate {
    
    func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
        
        guard let planeAnchor = anchors.first as? ARPlaneAnchor else { return }
        let grid = Grid(planeAnchor: planeAnchor)
        grid.transform.matrix = planeAnchor.transform
        self.arView.scene.anchors.append(grid)
        self.grids.append(grid)
    }
    
    func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
        
        guard let planeAnchor = anchors[0] as? ARPlaneAnchor else { return }
        let grid: Grid? = grids.filter { grd in
            grd.planeAnchor.identifier == planeAnchor.identifier }[0]
        guard let updatedGrid: Grid = grid else { return }
        updatedGrid.transform.matrix = planeAnchor.transform
        updatedGrid.didUpdate(anchor: planeAnchor)
    }
}

Only coplanar detected planes may be updated.

Andy Jazz
  • 36,357
  • 13
  • 107
  • 175
  • Hello @AndyJazz. Thanks for the quick response. I have tried your code. but it is not showing the expected result as I provided in the question. I have used only white color with opacity and didn't use texture which gives me this output: https://drive.google.com/file/d/1ZUHiZtP19MjSyou0TiWMNKmZIObugOsp/view?usp=sharing in this video white color is there, but it shows in a rectangular way. And what I want is I want to fill all the surfaces including corners and whatever shape is. You can clearly be shown in the questions video and output of given code is just drawing rectangular shape. – Kishan Barmawala Mar 04 '22 at 20:02
  • And @AndyJazz I've noticed you've answered lots of questions on iOS ARKit so I am hoping for you to help me out to achieve or else guide me to achieve my desired output, please? – Kishan Barmawala Mar 04 '22 at 20:05
  • You can use any grid texture (four channel `.png` file with premultiplied RGB*A) or any color (opaque or semi-transparent) to get a desired result. My code is a starting point for your own solution, so you can experiment with it the way you want to. – Andy Jazz Mar 04 '22 at 20:11
  • One important detail - ARCore plane detection works technically and visually differently from ARKit plane detection. – Andy Jazz Mar 04 '22 at 20:15
  • I understand completely but As you have already generated a plane that accept only width and height so it is obvious that it'll create a rectangle surface using thing below syntax .generatePlane(width: planeAnchor.extent.x, depth: planeAnchor.extent.z) but I want to show textures in each and every direction... so how would I do that? – Kishan Barmawala Mar 04 '22 at 20:16
  • It's a story about `didUpdate(anchor: ARPlaneAnchor)` method that works inside delegate's `session(_ , didUpdate: )` instance method. – Andy Jazz Mar 04 '22 at 20:21
  • Look at ARPlaneAnchor's properties – `extent` and `center`. They describe plane. – Andy Jazz Mar 04 '22 at 20:23
  • I understand what you're saying but ARPlaneAnchor is giving us the `extent` and `center` but MeshResource's `generatePlane` function accepts only width and depth and those are in only rectangular shape!!! – Kishan Barmawala Mar 04 '22 at 20:32
  • [In this link](https://www.wikitude.com/blog-plane-detection-ios12-android9/) you can get the exact idea of what I'm trying to say. That blue colored texture I want to implement or something like that but in dynamically expanding in any type of shape not only the rectangular shape – Kishan Barmawala Mar 04 '22 at 20:35
  • Use soft edges for your grid texture. – Andy Jazz Mar 04 '22 at 20:45
  • 1
    ARCore and ARKit principles of building detected planes are different. In ARKit, try grid texture with soft and irregular edges that has any repetitive pattern (even like in ARCore)... For texture use a PNG file with transparent and opaque areas... – Andy Jazz Mar 04 '22 at 20:52