How to draw dashed line in ARKit (SceneKit) like in the Measure app?

Viewed 1162

Just wanted to know is it possible (I know it is, but how) to draw dashed line in ARSCNView like in the Measure app? Maybe there is a way to use scene nodes out of the box, idk.

I've been using the SCNCylinder to draw a straight line and IDK is it possible to reuse it and adjust or we have to use a really different way to make the dashed line.

import SceneKit

class CylinderLineNode: SCNNode {

    private(set) var cylinder: SCNCylinder
    private(set) var positionA: SCNVector3
    private(set) var positionB: SCNVector3

    init(with positionA: SCNVector3, positionB: SCNVector3, radius: CGFloat = 0.02, color: UIColor = .red) {
        self.positionA = positionA
        self.positionB = positionB
        let vector = positionB - positionA
        let height = vector.length()
        cylinder = SCNCylinder(radius: radius, height: CGFloat(height))
        cylinder.radialSegmentCount = 8
        cylinder.firstMaterial?.diffuse.contents = color
        super.init()
        geometry = cylinder
        position = (positionB + positionA) / 2
        eulerAngles = SCNVector3.lineEulerAngles(vector: vector)
    }

    ...

}
1 Answers

Probably not the most professional solution, but I started with a very similar approach. And then added the dashed-style like follows.

First I created an image that is half white, half transparent, to create the dashed-style

Then used it in the material of the SCNCylinder:

material.diffuse.contents = UIImage(named: "line")!
material.diffuse.wrapS = .repeat
material.diffuse.wrapT = .repeat
material.isDoubleSided = true // Not sure if this is really needed here^

Next I scaled it accordingly, to repeat it (make it as fine) as I want it:

material.diffuse.contentsTransform = SCNMatrix4MakeScale(width * repeatCountPerMeter, height * repeatCountPerMeter, 1)

As I used a white image, I can "tint" it in any color I want:

material.multiply.contents = UIColor.green

To make it look more "2D like", ignore the lighting, using:

material.lighting = .constant

Additionally (as my Cylinder is rotated by 90°) I had to rotate the material as well:

let rotation = SCNMatrix4MakeRotation(.pi / 2, 0, 0, 1)
material.diffuse.contentsTransform = SCNMatrix4Mult(rotation, material.diffuse.contentsTransform)

And whenever the line gets resized, update its SCNMatrix4MakeScale accordingly (see width and heightabove, where forheight` I just put the diameter (2*r)).

Related